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:
parent
fa2cb7ba56
commit
e87bf5b029
24 changed files with 1029 additions and 415 deletions
|
@ -45,7 +45,8 @@ namespace Beefy
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
public delegate void UpdateDelegate(bool batchStart);
|
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 static BFApp sApp;
|
||||||
public int32 mUpdateCnt;
|
public int32 mUpdateCnt;
|
||||||
|
@ -106,7 +107,7 @@ namespace Beefy
|
||||||
static extern void BFApp_Shutdown();
|
static extern void BFApp_Shutdown();
|
||||||
|
|
||||||
[CallingConvention(.Stdcall), CLink]
|
[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]
|
[CallingConvention(.Stdcall), CLink]
|
||||||
static extern char8* BFApp_GetInstallDir();
|
static extern char8* BFApp_GetInstallDir();
|
||||||
|
@ -132,7 +133,11 @@ namespace Beefy
|
||||||
[CallingConvention(.Stdcall), CLink]
|
[CallingConvention(.Stdcall), CLink]
|
||||||
public static extern void* BFApp_GetSoundManager();
|
public static extern void* BFApp_GetSoundManager();
|
||||||
|
|
||||||
|
[CallingConvention(.Stdcall), CLink]
|
||||||
|
public static extern int BFApp_GetCriticalThreadId(int32 idx);
|
||||||
|
|
||||||
UpdateDelegate mUpdateDelegate ~ delete _;
|
UpdateDelegate mUpdateDelegate ~ delete _;
|
||||||
|
UpdateFDelegate mUpdateFDelegate ~ delete _;
|
||||||
DrawDelegate mDrawDelegate ~ delete _;
|
DrawDelegate mDrawDelegate ~ delete _;
|
||||||
|
|
||||||
#if STUDIO_CLIENT
|
#if STUDIO_CLIENT
|
||||||
|
@ -165,9 +170,9 @@ namespace Beefy
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static void Static_Draw()
|
static void Static_Draw(bool forceDraw)
|
||||||
{
|
{
|
||||||
sApp.Draw();
|
sApp.Draw(forceDraw);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void Static_Update(bool batchStart)
|
static void Static_Update(bool batchStart)
|
||||||
|
@ -175,6 +180,11 @@ namespace Beefy
|
||||||
sApp.Update(batchStart);
|
sApp.Update(batchStart);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void Static_UpdateF(float updatePct)
|
||||||
|
{
|
||||||
|
sApp.UpdateF(updatePct);
|
||||||
|
}
|
||||||
|
|
||||||
float mLastUpdateDelta; // In seconds
|
float mLastUpdateDelta; // In seconds
|
||||||
|
|
||||||
public this()
|
public this()
|
||||||
|
@ -198,9 +208,10 @@ namespace Beefy
|
||||||
BFApp_SetRefreshRate(mRefreshRate);
|
BFApp_SetRefreshRate(mRefreshRate);
|
||||||
|
|
||||||
mUpdateDelegate = new => Static_Update;
|
mUpdateDelegate = new => Static_Update;
|
||||||
|
mUpdateFDelegate = new => Static_UpdateF;
|
||||||
mDrawDelegate = new => Static_Draw;
|
mDrawDelegate = new => Static_Draw;
|
||||||
#endif
|
#endif
|
||||||
BFApp_SetCallbacks(mUpdateDelegate.GetFuncPtr(), mDrawDelegate.GetFuncPtr());
|
BFApp_SetCallbacks(mUpdateDelegate.GetFuncPtr(), mUpdateFDelegate.GetFuncPtr(), mDrawDelegate.GetFuncPtr());
|
||||||
}
|
}
|
||||||
|
|
||||||
#if STUDIO_CLIENT
|
#if STUDIO_CLIENT
|
||||||
|
@ -515,6 +526,14 @@ namespace Beefy
|
||||||
structuredData.Load(resFileName);
|
structuredData.Load(resFileName);
|
||||||
mResourceManager.ParseConfigData(structuredData);
|
mResourceManager.ParseConfigData(structuredData);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (int32 i = 0; true; i++)
|
||||||
|
{
|
||||||
|
int threadId = BFApp_GetCriticalThreadId(i);
|
||||||
|
if (threadId == 0)
|
||||||
|
break;
|
||||||
|
GC.ExcludeThreadId(threadId);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void InitGraphics()
|
public void InitGraphics()
|
||||||
|
@ -671,6 +690,14 @@ namespace Beefy
|
||||||
//Utils.BFRT_CPP("gBFGC.MutatorSectionExit()");
|
//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()
|
public virtual void DoDraw()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
@ -695,12 +722,11 @@ namespace Beefy
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
public virtual void Draw()
|
public virtual void Draw(bool forceDraw)
|
||||||
{
|
{
|
||||||
#if STUDIO_CLIENT
|
#if STUDIO_CLIENT
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
PerfTimer.ZoneStart("BFApp.Draw");
|
PerfTimer.ZoneStart("BFApp.Draw");
|
||||||
PerfTimer.Message("Client Draw Start");
|
PerfTimer.Message("Client Draw Start");
|
||||||
|
|
||||||
|
@ -716,7 +742,8 @@ namespace Beefy
|
||||||
|
|
||||||
for (BFWindow window in mWindows)
|
for (BFWindow window in mWindows)
|
||||||
{
|
{
|
||||||
if ((window.mVisible) && ((window.mIsDirty) || (mAutoDirty)))
|
if ((window.mVisible) &&
|
||||||
|
((window.mIsDirty) || (mAutoDirty) || (forceDraw)))
|
||||||
{
|
{
|
||||||
window.PreDraw(mGraphics);
|
window.PreDraw(mGraphics);
|
||||||
if (mColorMatrix != null)
|
if (mColorMatrix != null)
|
||||||
|
|
|
@ -664,6 +664,11 @@ namespace Beefy
|
||||||
public virtual void Update()
|
public virtual void Update()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public virtual void UpdateF(float updatePct)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
public class BFWindow : BFWindowBase, IStudioClientWindow
|
public class BFWindow : BFWindowBase, IStudioClientWindow
|
||||||
|
|
|
@ -19,6 +19,11 @@ namespace Beefy.theme.dark
|
||||||
public bool mAllowOpen = true;
|
public bool mAllowOpen = true;
|
||||||
public bool mIsReversed;
|
public bool mIsReversed;
|
||||||
|
|
||||||
|
public this()
|
||||||
|
{
|
||||||
|
mAlwaysUpdateF = true;
|
||||||
|
}
|
||||||
|
|
||||||
public override void Draw(Graphics g)
|
public override void Draw(Graphics g)
|
||||||
{
|
{
|
||||||
base.Draw(g);
|
base.Draw(g);
|
||||||
|
@ -52,9 +57,9 @@ namespace Beefy.theme.dark
|
||||||
mRot = mIsOpen ? (Math.PI_f / 2) : 0;
|
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;
|
int childCount = mItem.mChildItems.Count;
|
||||||
|
|
||||||
|
@ -62,15 +67,17 @@ namespace Beefy.theme.dark
|
||||||
|
|
||||||
if ((mIsOpen) && (mRot < Math.PI_f / 2))
|
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;
|
mItem.mListView.mListSizeDirty = true;
|
||||||
MarkDirty();
|
MarkDirty();
|
||||||
|
mWidgetWindow.mTempWantsUpdateF = true;
|
||||||
}
|
}
|
||||||
else if ((!mIsOpen) && (mRot > 0))
|
else if ((!mIsOpen) && (mRot > 0))
|
||||||
{
|
{
|
||||||
mRot = (float)Math.Max(0, mRot - rotSpeed);
|
mRot = (float)Math.Max(0, mRot - rotSpeed * updatePct);
|
||||||
mItem.mListView.mListSizeDirty = true;
|
mItem.mListView.mListSizeDirty = true;
|
||||||
MarkDirty();
|
MarkDirty();
|
||||||
|
mWidgetWindow.mTempWantsUpdateF = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
float x;
|
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
|
public class DarkListView : ListView
|
||||||
|
|
|
@ -37,9 +37,9 @@ namespace Beefy.utils
|
||||||
get { return mPct != 1.0f; }
|
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)
|
public void Set(double val, bool immediate = false)
|
||||||
|
|
|
@ -788,7 +788,12 @@ namespace Beefy.widgets
|
||||||
public override void UpdateAll()
|
public override void UpdateAll()
|
||||||
{
|
{
|
||||||
base.UpdateAll();
|
base.UpdateAll();
|
||||||
|
UpdateListSize();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void UpdateFAll(float updatePct)
|
||||||
|
{
|
||||||
|
base.UpdateFAll(updatePct);
|
||||||
UpdateListSize();
|
UpdateListSize();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -802,7 +807,7 @@ namespace Beefy.widgets
|
||||||
|
|
||||||
public void UpdateListSize()
|
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)
|
if (mListSizeDirty)
|
||||||
{
|
{
|
||||||
float listWidth = GetListWidth();
|
float listWidth = GetListWidth();
|
||||||
|
|
|
@ -50,6 +50,7 @@ namespace Beefy.widgets
|
||||||
mScrollContentContainer.mClipGfx = true;
|
mScrollContentContainer.mClipGfx = true;
|
||||||
mScrollContentContainer.mClipMouse = true;
|
mScrollContentContainer.mClipMouse = true;
|
||||||
AddWidget(mScrollContentContainer);
|
AddWidget(mScrollContentContainer);
|
||||||
|
mAlwaysUpdateF = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ~this()
|
public ~this()
|
||||||
|
@ -248,10 +249,18 @@ namespace Beefy.widgets
|
||||||
{
|
{
|
||||||
base.Update();
|
base.Update();
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void UpdateF(float updatePct)
|
||||||
|
{
|
||||||
|
base.UpdateF(updatePct);
|
||||||
|
|
||||||
if ((mHorzPos.IsMoving) || (mVertPos.IsMoving))
|
if ((mHorzPos.IsMoving) || (mVertPos.IsMoving))
|
||||||
{
|
{
|
||||||
mHorzPos.Update();
|
mWidgetWindow.mTempWantsUpdateF = true;
|
||||||
mVertPos.Update();
|
mHorzPos.Update(updatePct);
|
||||||
|
mVertPos.Update(updatePct);
|
||||||
UpdateContentPosition();
|
UpdateContentPosition();
|
||||||
MarkDirty();
|
MarkDirty();
|
||||||
}
|
}
|
||||||
|
|
|
@ -39,6 +39,7 @@ namespace Beefy.widgets
|
||||||
public float mWidth;
|
public float mWidth;
|
||||||
public float mHeight;
|
public float mHeight;
|
||||||
public int32 mUpdateCnt;
|
public int32 mUpdateCnt;
|
||||||
|
public double mUpdateCntF;
|
||||||
public String mIdStr ~ delete _;
|
public String mIdStr ~ delete _;
|
||||||
public List<Widget> mChildWidgets;
|
public List<Widget> mChildWidgets;
|
||||||
public MouseFlag mMouseFlags;
|
public MouseFlag mMouseFlags;
|
||||||
|
@ -56,6 +57,7 @@ namespace Beefy.widgets
|
||||||
public bool mDeferredDelete;
|
public bool mDeferredDelete;
|
||||||
public Insets mMouseInsets ~ delete _;
|
public Insets mMouseInsets ~ delete _;
|
||||||
public bool mAutoFocus;
|
public bool mAutoFocus;
|
||||||
|
public bool mAlwaysUpdateF;
|
||||||
|
|
||||||
public float X { get { return mX; } set { mX = value; } }
|
public float X { get { return mX; } set { mX = value; } }
|
||||||
public float Y { get { return mY; } set { mY = value; } }
|
public float Y { get { return mY; } set { mY = value; } }
|
||||||
|
@ -455,6 +457,14 @@ namespace Beefy.widgets
|
||||||
public virtual void Update()
|
public virtual void Update()
|
||||||
{
|
{
|
||||||
mUpdateCnt++;
|
mUpdateCnt++;
|
||||||
|
if ((mAlwaysUpdateF) && (mWidgetWindow != null))
|
||||||
|
UpdateF((float)(mUpdateCnt - mUpdateCntF));
|
||||||
|
mUpdateCntF = mUpdateCnt;
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual void UpdateF(float updatePct)
|
||||||
|
{
|
||||||
|
mUpdateCntF += updatePct;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void DeferDelete()
|
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)
|
public virtual void Resize(float x, float y, float width, float height)
|
||||||
{
|
{
|
||||||
Debug.Assert(width >= 0);
|
Debug.Assert(width >= 0);
|
||||||
|
|
|
@ -62,6 +62,8 @@ namespace Beefy.widgets
|
||||||
public bool mHasMouseInside;
|
public bool mHasMouseInside;
|
||||||
public bool mHasProxyMouseInside;
|
public bool mHasProxyMouseInside;
|
||||||
public bool mIsKeyDownHandled;
|
public bool mIsKeyDownHandled;
|
||||||
|
public bool mWantsUpdateF;
|
||||||
|
public bool mTempWantsUpdateF;
|
||||||
|
|
||||||
public int32 mContentClientWidth;
|
public int32 mContentClientWidth;
|
||||||
public int32 mContentClientHeight;
|
public int32 mContentClientHeight;
|
||||||
|
@ -153,9 +155,19 @@ namespace Beefy.widgets
|
||||||
return;
|
return;
|
||||||
base.Update();
|
base.Update();
|
||||||
RehupMouse(false);
|
RehupMouse(false);
|
||||||
|
mTempWantsUpdateF = false;
|
||||||
mRootWidget.UpdateAll();
|
mRootWidget.UpdateAll();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override void UpdateF(float updatePct)
|
||||||
|
{
|
||||||
|
if (mRootWidget == null)
|
||||||
|
return;
|
||||||
|
base.Update();
|
||||||
|
if (mWantsUpdateF || mTempWantsUpdateF)
|
||||||
|
mRootWidget.UpdateFAll(updatePct);
|
||||||
|
}
|
||||||
|
|
||||||
public override int32 CloseQuery()
|
public override int32 CloseQuery()
|
||||||
{
|
{
|
||||||
bool hadFalse = false;
|
bool hadFalse = false;
|
||||||
|
|
|
@ -133,6 +133,8 @@ namespace System
|
||||||
public extern static void SetMaxPausePercentage(int maxPausePercentage); // 0 = disabled. Defaults to 20.
|
public extern static void SetMaxPausePercentage(int maxPausePercentage); // 0 = disabled. Defaults to 20.
|
||||||
[CallingConvention(.Cdecl)]
|
[CallingConvention(.Cdecl)]
|
||||||
extern static void AddPendingThread(void* internalThread);
|
extern static void AddPendingThread(void* internalThread);
|
||||||
|
[CallingConvention(.Cdecl)]
|
||||||
|
public extern static void ExcludeThreadId(int thereadId);
|
||||||
#else
|
#else
|
||||||
public static void Collect(bool async = true) {}
|
public static void Collect(bool async = true) {}
|
||||||
private static void MarkAllStaticMembers() {}
|
private static void MarkAllStaticMembers() {}
|
||||||
|
@ -144,6 +146,7 @@ namespace System
|
||||||
public static void SetCollectFreeThreshold(int freeBytes) {}
|
public static void SetCollectFreeThreshold(int freeBytes) {}
|
||||||
public static void SetMaxPausePercentage(int maxPausePercentage) {}
|
public static void SetMaxPausePercentage(int maxPausePercentage) {}
|
||||||
static void AddPendingThread(void* internalThreadInfo) {}
|
static void AddPendingThread(void* internalThreadInfo) {}
|
||||||
|
public static void ExcludeThreadId(int thereadId) {}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static void MarkDerefedObject(Object* obj)
|
static void MarkDerefedObject(Object* obj)
|
||||||
|
|
|
@ -1429,6 +1429,9 @@ bool BFGC::ScanThreads()
|
||||||
thread = mThreadList[threadIdx++];
|
thread = mThreadList[threadIdx++];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (thread->mExcluded)
|
||||||
|
continue;
|
||||||
|
|
||||||
if (!thread->mRunning)
|
if (!thread->mRunning)
|
||||||
{
|
{
|
||||||
AutoCrit autoCrit(mCritSect);
|
AutoCrit autoCrit(mCritSect);
|
||||||
|
@ -2367,11 +2370,12 @@ void BFGC::SuspendThreads()
|
||||||
auto curThreadId = GetCurrentThreadId();
|
auto curThreadId = GetCurrentThreadId();
|
||||||
for (auto thread : mThreadList)
|
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
|
// We must lock this before suspending so we can access mStackMarkableObjects
|
||||||
// Otherwise we could deadlock
|
// Otherwise we could deadlock
|
||||||
thread->mCritSect.Lock();
|
thread->mCritSect.Lock();
|
||||||
|
thread->mSuspended = true;
|
||||||
|
|
||||||
BfpThreadResult result;
|
BfpThreadResult result;
|
||||||
BfpThread_Suspend(thread->mThreadHandle, &result);
|
BfpThread_Suspend(thread->mThreadHandle, &result);
|
||||||
|
@ -2386,11 +2390,12 @@ void BFGC::ResumeThreads()
|
||||||
auto curThreadId = GetCurrentThreadId();
|
auto curThreadId = GetCurrentThreadId();
|
||||||
for (auto thread : mThreadList)
|
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
|
// Previously locked in SuspendThreads
|
||||||
thread->mCritSect.Unlock();
|
thread->mCritSect.Unlock();
|
||||||
|
|
||||||
|
thread->mSuspended = false;
|
||||||
BfpThread_Resume(thread->mThreadHandle, NULL);
|
BfpThread_Resume(thread->mThreadHandle, NULL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2743,6 +2748,16 @@ void BFGC::SetMaxRawDeferredObjectFreePercentage(intptr maxPercentage)
|
||||||
mMaxRawDeferredObjectFreePercentage = 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;
|
using namespace bf::System;
|
||||||
|
|
||||||
void GC::Run()
|
void GC::Run()
|
||||||
|
@ -2832,6 +2847,11 @@ BFRT_EXPORT void bf::System::GC::SetMaxRawDeferredObjectFreePercentage(intptr ma
|
||||||
gBFGC.SetMaxRawDeferredObjectFreePercentage(maxPercentage);
|
gBFGC.SetMaxRawDeferredObjectFreePercentage(maxPercentage);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BFRT_EXPORT void bf::System::GC::ExcludeThreadId(intptr threadId)
|
||||||
|
{
|
||||||
|
gBFGC.ExcludeThreadId(threadId);
|
||||||
|
}
|
||||||
|
|
||||||
#else // BF_GC_SUPPORTED
|
#else // BF_GC_SUPPORTED
|
||||||
|
|
||||||
void* BfObjectAllocate(intptr size, bf::System::Type* type)
|
void* BfObjectAllocate(intptr size, bf::System::Type* type)
|
||||||
|
|
|
@ -181,6 +181,8 @@ public:
|
||||||
intptr mStackStart;
|
intptr mStackStart;
|
||||||
intptr mLastStackPtr;
|
intptr mLastStackPtr;
|
||||||
bool mRunning;
|
bool mRunning;
|
||||||
|
bool mExcluded;
|
||||||
|
bool mSuspended;
|
||||||
Beefy::Array<bf::System::Object*> mStackMarkableObjects;
|
Beefy::Array<bf::System::Object*> mStackMarkableObjects;
|
||||||
|
|
||||||
ThreadInfo()
|
ThreadInfo()
|
||||||
|
@ -192,6 +194,8 @@ public:
|
||||||
mTEB = NULL;
|
mTEB = NULL;
|
||||||
mStackStart = NULL;
|
mStackStart = NULL;
|
||||||
mRunning = true;
|
mRunning = true;
|
||||||
|
mExcluded = false;
|
||||||
|
mSuspended = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
~ThreadInfo();
|
~ThreadInfo();
|
||||||
|
@ -424,6 +428,7 @@ public:
|
||||||
void SetCollectFreeThreshold(int freeBytes);
|
void SetCollectFreeThreshold(int freeBytes);
|
||||||
void SetMaxPausePercentage(int maxPausePercentage);
|
void SetMaxPausePercentage(int maxPausePercentage);
|
||||||
void SetMaxRawDeferredObjectFreePercentage(intptr maxPercentage);
|
void SetMaxRawDeferredObjectFreePercentage(intptr maxPercentage);
|
||||||
|
void ExcludeThreadId(intptr threadId);
|
||||||
};
|
};
|
||||||
|
|
||||||
extern BFGC gBFGC;
|
extern BFGC gBFGC;
|
||||||
|
@ -488,6 +493,7 @@ namespace bf
|
||||||
BFRT_EXPORT static void SetCollectFreeThreshold(intptr freeBytes);
|
BFRT_EXPORT static void SetCollectFreeThreshold(intptr freeBytes);
|
||||||
BFRT_EXPORT static void SetMaxPausePercentage(intptr maxPausePercentage);
|
BFRT_EXPORT static void SetMaxPausePercentage(intptr maxPausePercentage);
|
||||||
BFRT_EXPORT static void SetMaxRawDeferredObjectFreePercentage(intptr maxPercentage);
|
BFRT_EXPORT static void SetMaxRawDeferredObjectFreePercentage(intptr maxPercentage);
|
||||||
|
BFRT_EXPORT static void ExcludeThreadId(intptr threadId);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,10 +19,11 @@ BFApp::BFApp()
|
||||||
mTitle = "Beefy Application";
|
mTitle = "Beefy Application";
|
||||||
mRefreshRate = 60;
|
mRefreshRate = 60;
|
||||||
mLastProcessTick = BFTickCount();
|
mLastProcessTick = BFTickCount();
|
||||||
mFrameTimeAcc = 0;
|
mPhysFrameTimeAcc = 0;
|
||||||
mDrawEnabled = true;
|
mDrawEnabled = true;
|
||||||
|
|
||||||
mUpdateFunc = NULL;
|
mUpdateFunc = NULL;
|
||||||
|
mUpdateFFunc = NULL;
|
||||||
mDrawFunc = NULL;
|
mDrawFunc = NULL;
|
||||||
|
|
||||||
gBFApp = this;
|
gBFApp = this;
|
||||||
|
@ -43,6 +44,12 @@ BFApp::BFApp()
|
||||||
mRunning = false;
|
mRunning = false;
|
||||||
mRenderDevice = NULL;
|
mRenderDevice = NULL;
|
||||||
mVSynched = false;
|
mVSynched = false;
|
||||||
|
mVSyncActive = false;
|
||||||
|
mForceNextDraw = false;
|
||||||
|
|
||||||
|
mUpdateCnt = 0;
|
||||||
|
mUpdateCntF = 0;
|
||||||
|
mClientUpdateCntF = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
BFApp::~BFApp()
|
BFApp::~BFApp()
|
||||||
|
@ -90,10 +97,16 @@ void BFApp::Update(bool batchStart)
|
||||||
mPendingWindowDeleteList.clear();
|
mPendingWindowDeleteList.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void BFApp::UpdateF(float updatePct)
|
||||||
|
{
|
||||||
|
mUpdateFFunc(updatePct);
|
||||||
|
}
|
||||||
|
|
||||||
void BFApp::Draw()
|
void BFApp::Draw()
|
||||||
{
|
{
|
||||||
gPerfManager->ZoneStart("BFApp::Draw");
|
gPerfManager->ZoneStart("BFApp::Draw");
|
||||||
mDrawFunc();
|
mDrawFunc(mForceNextDraw);
|
||||||
|
mForceNextDraw = false;
|
||||||
gPerfManager->ZoneEnd();
|
gPerfManager->ZoneEnd();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -103,18 +116,39 @@ void BFApp::Process()
|
||||||
{
|
{
|
||||||
//Beefy::DebugTimeGuard suspendTimeGuard(30, "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)
|
if (mInProcess)
|
||||||
return; // No reentry
|
return; // No reentry
|
||||||
mInProcess = true;
|
mInProcess = true;
|
||||||
|
|
||||||
int updates;
|
|
||||||
|
|
||||||
uint32 tickNow = BFTickCount();
|
uint32 tickNow = BFTickCount();
|
||||||
const int vSyncTestingPeriod = 250;
|
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;
|
int ticksSinceLastProcess = tickNow - mLastProcessTick;
|
||||||
|
|
||||||
mUpdateSampleCount++;
|
mUpdateSampleCount++;
|
||||||
|
@ -132,60 +166,37 @@ void BFApp::Process()
|
||||||
mVSynched = false;
|
mVSynched = false;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
if (!mVSyncFailed)
|
if (!mVSyncFailed)
|
||||||
mVSynched = true;
|
mVSynched = true;
|
||||||
|
}
|
||||||
|
|
||||||
mUpdateSampleCount = 0;
|
mUpdateSampleCount = 0;
|
||||||
mUpdateSampleTimes = 0;
|
mUpdateSampleTimes = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
mFrameTimeAcc += tickNow - mLastProcessTick;
|
mPhysFrameTimeAcc += tickNow - mLastProcessTick;
|
||||||
|
|
||||||
bool vSynched = mVSynched;
|
if (didVBlankWait)
|
||||||
|
|
||||||
if (vSynched)
|
|
||||||
{
|
{
|
||||||
// For the startup, try not to go hyper during those first samplings
|
// Try to keep time synced with vblank
|
||||||
if (mUpdateSampleTimes <= vSyncTestingPeriod)
|
if (mPhysFrameTimeAcc < physTicksPerFrame * 2)
|
||||||
{
|
{
|
||||||
if (ticksSinceLastProcess < ticksPerFrame / 1.5)
|
float timeAdjust = physTicksPerFrame - mPhysFrameTimeAcc + 0.001f;
|
||||||
vSynched = false;
|
mPhysFrameTimeAcc += timeAdjust;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (vSynched)
|
/*if (updates > 2)
|
||||||
{
|
OutputDebugStrF("Updates: %d TickDelta: %d\n", updates, tickNow - mLastProcessTick);*/
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Compensate for "slow start" by limiting the number of catchup-updates we can do when starting the app
|
// 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);
|
int maxUpdates = BF_MIN(mNumPhysUpdates + 1, mMaxUpdatesPerDraw);
|
||||||
|
|
||||||
updates = BF_MIN(updates, maxUpdates);
|
while (mPhysFrameTimeAcc >= physTicksPerFrame)
|
||||||
|
|
||||||
/*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)
|
|
||||||
{
|
{
|
||||||
// Yield
|
mPhysFrameTimeAcc -= physTicksPerFrame;
|
||||||
BfpThread_Sleep(1);
|
mUpdateCntF += physTicksPerFrame / ticksPerFrame;
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint32 lastUpdate = BFTickCount();
|
static uint32 lastUpdate = BFTickCount();
|
||||||
|
@ -202,17 +213,46 @@ void BFApp::Process()
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (updates > 0)
|
|
||||||
mNumPhysUpdates++;
|
|
||||||
|
|
||||||
for (int updateNum = 0; updateNum < updates; updateNum++)
|
int didUpdateCnt = 0;
|
||||||
|
|
||||||
|
if (mClientUpdateCntF - mUpdateCntF > physRefreshRate / 2)
|
||||||
{
|
{
|
||||||
if (!mRunning)
|
// Too large of a difference, just sync
|
||||||
break;
|
mClientUpdateCntF = mUpdateCntF - 1;
|
||||||
Update(updateNum == 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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();
|
Draw();
|
||||||
|
|
||||||
#ifdef PERIODIC_PERF_TIMING
|
#ifdef PERIODIC_PERF_TIMING
|
||||||
|
@ -229,6 +269,8 @@ void BFApp::Process()
|
||||||
|
|
||||||
void BFApp::RemoveWindow(BFWindow* window)
|
void BFApp::RemoveWindow(BFWindow* window)
|
||||||
{
|
{
|
||||||
|
AutoCrit autoCrit(mCritSect);
|
||||||
|
|
||||||
auto itr = std::find(mWindowList.begin(), mWindowList.end(), window);
|
auto itr = std::find(mWindowList.begin(), mWindowList.end(), window);
|
||||||
if (itr == mWindowList.end()) // Allow benign failure (double removal)
|
if (itr == mWindowList.end()) // Allow benign failure (double removal)
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -1,12 +1,14 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "Common.h"
|
#include "Common.h"
|
||||||
|
#include "util/CritSect.h"
|
||||||
#include <list>
|
#include <list>
|
||||||
|
|
||||||
NS_BF_BEGIN;
|
NS_BF_BEGIN;
|
||||||
|
|
||||||
typedef void (*BFApp_UpdateFunc)(bool batchStart);
|
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 BFApp;
|
||||||
class BFSoundManager;
|
class BFSoundManager;
|
||||||
|
@ -50,12 +52,15 @@ public:
|
||||||
class BFApp
|
class BFApp
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
CritSect mCritSect;
|
||||||
String mTitle;
|
String mTitle;
|
||||||
String mInstallDir;
|
String mInstallDir;
|
||||||
String mDataDir;
|
String mDataDir;
|
||||||
bool mDrawEnabled;
|
bool mDrawEnabled;
|
||||||
float mRefreshRate;
|
float mRefreshRate;
|
||||||
int mMaxUpdatesPerDraw;
|
int mMaxUpdatesPerDraw;
|
||||||
|
double mUpdateCntF;
|
||||||
|
double mClientUpdateCntF;
|
||||||
|
|
||||||
bool mInProcess;
|
bool mInProcess;
|
||||||
bool mRunning;
|
bool mRunning;
|
||||||
|
@ -63,16 +68,20 @@ public:
|
||||||
int mSysDialogCnt;
|
int mSysDialogCnt;
|
||||||
int mUpdateCnt;
|
int mUpdateCnt;
|
||||||
int mNumPhysUpdates;
|
int mNumPhysUpdates;
|
||||||
|
SyncEvent mVSyncEvent;
|
||||||
|
volatile bool mVSyncActive;
|
||||||
bool mVSynched;
|
bool mVSynched;
|
||||||
bool mVSyncFailed;
|
bool mVSyncFailed;
|
||||||
|
bool mForceNextDraw;
|
||||||
|
|
||||||
int mUpdateSampleCount;
|
int mUpdateSampleCount;
|
||||||
int mUpdateSampleTimes;
|
int mUpdateSampleTimes;
|
||||||
|
|
||||||
uint32 mLastProcessTick;
|
uint32 mLastProcessTick;
|
||||||
float mFrameTimeAcc;
|
float mPhysFrameTimeAcc;
|
||||||
|
|
||||||
BFApp_UpdateFunc mUpdateFunc;
|
BFApp_UpdateFunc mUpdateFunc;
|
||||||
|
BFApp_UpdateFFunc mUpdateFFunc;
|
||||||
BFApp_DrawFunc mDrawFunc;
|
BFApp_DrawFunc mDrawFunc;
|
||||||
int mCursor;
|
int mCursor;
|
||||||
|
|
||||||
|
@ -81,6 +90,7 @@ public:
|
||||||
|
|
||||||
public:
|
public:
|
||||||
virtual void Update(bool batchStart);
|
virtual void Update(bool batchStart);
|
||||||
|
virtual void UpdateF(float updatePct);
|
||||||
virtual void Draw();
|
virtual void Draw();
|
||||||
virtual void Process();
|
virtual void Process();
|
||||||
virtual void PhysSetCursor() = 0;
|
virtual void PhysSetCursor() = 0;
|
||||||
|
@ -114,6 +124,8 @@ public:
|
||||||
virtual FileStream* OpenBinaryFile(const StringImpl& fileName);
|
virtual FileStream* OpenBinaryFile(const StringImpl& fileName);
|
||||||
|
|
||||||
virtual BFSoundManager* GetSoundManager() { return NULL; }
|
virtual BFSoundManager* GetSoundManager() { return NULL; }
|
||||||
|
|
||||||
|
virtual intptr GetCriticalThreadId(int idx) { return 0; }
|
||||||
};
|
};
|
||||||
|
|
||||||
extern BFApp* gBFApp;
|
extern BFApp* gBFApp;
|
||||||
|
|
|
@ -210,9 +210,10 @@ BF_EXPORT const char* BF_CALLTYPE BFApp_GetDataDir()
|
||||||
return gBFApp->mDataDir.c_str();
|
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->mUpdateFunc = updateFunc;
|
||||||
|
gBFApp->mUpdateFFunc = updateFFunc;
|
||||||
gBFApp->mDrawFunc = drawFunc;
|
gBFApp->mDrawFunc = drawFunc;
|
||||||
//public delegate void UpdateProc();
|
//public delegate void UpdateProc();
|
||||||
}
|
}
|
||||||
|
@ -276,6 +277,11 @@ BF_EXPORT BFSoundManager* BF_CALLTYPE BFApp_GetSoundManager()
|
||||||
return gBFApp->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,
|
BF_EXPORT void BF_CALLTYPE BFWindow_SetCallbacks(BFWindow* window, BFWindow_MovedFunc movedFunc, BFWindow_CloseQueryFunc closeQueryFunc, BFWindow_ClosedFunc closedFunc,
|
||||||
|
|
|
@ -62,6 +62,7 @@ RenderDevice::RenderDevice() :
|
||||||
mCurRenderTarget = NULL;
|
mCurRenderTarget = NULL;
|
||||||
mCurDrawLayer = NULL;
|
mCurDrawLayer = NULL;
|
||||||
mPhysRenderWindow = NULL;
|
mPhysRenderWindow = NULL;
|
||||||
|
mApp = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
RenderDevice::~RenderDevice()
|
RenderDevice::~RenderDevice()
|
||||||
|
|
|
@ -76,6 +76,8 @@ public:
|
||||||
virtual void SetAsTarget() = 0;
|
virtual void SetAsTarget() = 0;
|
||||||
virtual void Resized() = 0;
|
virtual void Resized() = 0;
|
||||||
virtual void Present() = 0;
|
virtual void Present() = 0;
|
||||||
|
virtual float GetRefreshRate() { return 60.0f; }
|
||||||
|
virtual bool WaitForVBlank() { return false; }
|
||||||
};
|
};
|
||||||
|
|
||||||
const int DRAWBUFFER_IDXBUFFER_SIZE = 8*1024;
|
const int DRAWBUFFER_IDXBUFFER_SIZE = 8*1024;
|
||||||
|
@ -175,6 +177,14 @@ public:
|
||||||
mElementData = NULL;
|
mElementData = NULL;
|
||||||
mNumElements = 0;
|
mNumElements = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
VertexDefinition(VertexDefinition* src)
|
||||||
|
{
|
||||||
|
mElementData = new VertexDefData[src->mNumElements];
|
||||||
|
mNumElements = src->mNumElements;
|
||||||
|
memcpy(mElementData, src->mElementData, sizeof(VertexDefData) * mNumElements);
|
||||||
|
}
|
||||||
|
|
||||||
virtual ~VertexDefinition()
|
virtual ~VertexDefinition()
|
||||||
{
|
{
|
||||||
delete [] mElementData;
|
delete [] mElementData;
|
||||||
|
@ -262,6 +272,7 @@ class RenderDevice
|
||||||
public:
|
public:
|
||||||
Array<DrawBatch*> mDrawBatchPool;
|
Array<DrawBatch*> mDrawBatchPool;
|
||||||
|
|
||||||
|
BFApp* mApp;
|
||||||
RenderWindow* mPhysRenderWindow;
|
RenderWindow* mPhysRenderWindow;
|
||||||
RenderState* mPhysRenderState;
|
RenderState* mPhysRenderState;
|
||||||
int mResizeCount;
|
int mResizeCount;
|
||||||
|
|
|
@ -18,6 +18,7 @@ using namespace DirectX;
|
||||||
//#include <D3DX11async.h>
|
//#include <D3DX11async.h>
|
||||||
//#include <D3DX10math.h>
|
//#include <D3DX10math.h>
|
||||||
//#include <DxErr.h>
|
//#include <DxErr.h>
|
||||||
|
#include <dxgi1_3.h>
|
||||||
#pragma warning(pop)
|
#pragma warning(pop)
|
||||||
|
|
||||||
#include "util/AllocDebug.h"
|
#include "util/AllocDebug.h"
|
||||||
|
@ -192,6 +193,7 @@ void DXShaderParam::SetFloat4(float x, float y, float z, float w)
|
||||||
DXShader::DXShader()
|
DXShader::DXShader()
|
||||||
{
|
{
|
||||||
//? mD3DEffect = NULL;
|
//? mD3DEffect = NULL;
|
||||||
|
mVertexDef = NULL;
|
||||||
mD3DPixelShader = NULL;
|
mD3DPixelShader = NULL;
|
||||||
mD3DVertexShader = NULL;
|
mD3DVertexShader = NULL;
|
||||||
mD3DLayout = NULL;
|
mD3DLayout = NULL;
|
||||||
|
@ -201,25 +203,235 @@ DXShader::DXShader()
|
||||||
|
|
||||||
DXShader::~DXShader()
|
DXShader::~DXShader()
|
||||||
{
|
{
|
||||||
DXShaderParamMap::iterator itr = mParamsMap.begin();
|
delete mVertexDef;
|
||||||
while (itr != mParamsMap.end())
|
ReleaseNative();
|
||||||
{
|
|
||||||
delete itr->second;
|
|
||||||
++itr;
|
|
||||||
}
|
|
||||||
if (mD3DLayout != NULL)
|
|
||||||
mD3DLayout->Release();
|
|
||||||
if (mD3DVertexShader != NULL)
|
|
||||||
mD3DVertexShader->Release();
|
|
||||||
if (mD3DPixelShader != NULL)
|
|
||||||
mD3DPixelShader->Release();
|
|
||||||
if (mConstBuffer != NULL)
|
|
||||||
mConstBuffer->Release();
|
|
||||||
|
|
||||||
//? if (mD3DEffect != NULL)
|
//? if (mD3DEffect != NULL)
|
||||||
//? mD3DEffect->Release();
|
//? 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)
|
ShaderParam* DXShader::GetShaderParam(const StringImpl& name)
|
||||||
{
|
{
|
||||||
DXShaderParamMap::iterator itr = mParamsMap.find(name);
|
DXShaderParamMap::iterator itr = mParamsMap.find(name);
|
||||||
|
@ -249,7 +461,7 @@ DXTexture::DXTexture()
|
||||||
mRenderDevice = NULL;
|
mRenderDevice = NULL;
|
||||||
mD3DDepthBuffer = NULL;
|
mD3DDepthBuffer = NULL;
|
||||||
mD3DDepthStencilView = NULL;
|
mD3DDepthStencilView = NULL;
|
||||||
mImageData = NULL;
|
mContentBits = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
DXTexture::~DXTexture()
|
DXTexture::~DXTexture()
|
||||||
|
@ -258,7 +470,7 @@ DXTexture::~DXTexture()
|
||||||
((DXRenderDevice*)mRenderDevice)->mTextureMap.Remove(mPath);
|
((DXRenderDevice*)mRenderDevice)->mTextureMap.Remove(mPath);
|
||||||
|
|
||||||
//OutputDebugStrF("DXTexture::~DXTexture %@\n", this);
|
//OutputDebugStrF("DXTexture::~DXTexture %@\n", this);
|
||||||
delete mImageData;
|
delete mContentBits;
|
||||||
if (mD3DResourceView != NULL)
|
if (mD3DResourceView != NULL)
|
||||||
mD3DResourceView->Release();
|
mD3DResourceView->Release();
|
||||||
if (mD3DDepthStencilView != NULL)
|
if (mD3DDepthStencilView != NULL)
|
||||||
|
@ -267,6 +479,8 @@ DXTexture::~DXTexture()
|
||||||
mD3DDepthBuffer->Release();
|
mD3DDepthBuffer->Release();
|
||||||
if (mD3DTexture != NULL)
|
if (mD3DTexture != NULL)
|
||||||
mD3DTexture->Release();
|
mD3DTexture->Release();
|
||||||
|
if (mRenderDevice != NULL)
|
||||||
|
mRenderDevice->mTextures.Remove(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DXTexture::ReleaseNative()
|
void DXTexture::ReleaseNative()
|
||||||
|
@ -297,6 +511,44 @@ void DXTexture::ReleaseNative()
|
||||||
|
|
||||||
void DXTexture::ReinitNative()
|
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()
|
void DXTexture::PhysSetAsTarget()
|
||||||
|
@ -338,12 +590,24 @@ void DXTexture::Blt(ImageData* imageData, int x, int y)
|
||||||
box.front = 0;
|
box.front = 0;
|
||||||
box.back = 1;
|
box.back = 1;
|
||||||
mRenderDevice->mD3DDeviceContext->UpdateSubresource(mD3DTexture, 0, &box, imageData->mBits, imageData->mWidth * sizeof(uint32), 0);
|
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)
|
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 };
|
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);
|
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)
|
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;
|
HRESULT result = NULL;
|
||||||
|
|
||||||
|
if (mMatrix2DBuffer == NULL)
|
||||||
|
{
|
||||||
D3D11_BUFFER_DESC matrixBufferDesc;
|
D3D11_BUFFER_DESC matrixBufferDesc;
|
||||||
matrixBufferDesc.Usage = D3D11_USAGE_DYNAMIC;
|
matrixBufferDesc.Usage = D3D11_USAGE_DYNAMIC;
|
||||||
matrixBufferDesc.ByteWidth = sizeof(float[4]);
|
matrixBufferDesc.ByteWidth = sizeof(float[4]);
|
||||||
|
@ -540,12 +806,8 @@ void DXRenderDevice::PhysSetRenderState(RenderState* renderState)
|
||||||
matrixBufferDesc.MiscFlags = 0;
|
matrixBufferDesc.MiscFlags = 0;
|
||||||
matrixBufferDesc.StructureByteStride = 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.
|
// 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))
|
if (FAILED(result))
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
|
@ -554,7 +816,7 @@ void DXRenderDevice::PhysSetRenderState(RenderState* renderState)
|
||||||
|
|
||||||
// Lock the constant buffer so it can be written to.
|
// Lock the constant buffer so it can be written to.
|
||||||
D3D11_MAPPED_SUBRESOURCE mappedResource;
|
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))
|
if (FAILED(result))
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
|
@ -568,10 +830,10 @@ void DXRenderDevice::PhysSetRenderState(RenderState* renderState)
|
||||||
dataPtr[3] = 0;
|
dataPtr[3] = 0;
|
||||||
|
|
||||||
// Unlock the constant buffer.
|
// Unlock the constant buffer.
|
||||||
mD3DDeviceContext->Unmap(matrixBuffer, 0);
|
mD3DDeviceContext->Unmap(mMatrix2DBuffer, 0);
|
||||||
|
|
||||||
//float params[4] = {mCurRenderTarget->mWidth, mCurRenderTarget->mHeight, 0, 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()
|
void DXRenderState::ReinitNative()
|
||||||
{
|
{
|
||||||
|
ReleaseNative();
|
||||||
}
|
}
|
||||||
|
|
||||||
void DXRenderState::InvalidateRasterizerState()
|
void DXRenderState::InvalidateRasterizerState()
|
||||||
|
@ -1264,6 +1526,8 @@ DXRenderWindow::DXRenderWindow(DXRenderDevice* renderDevice, WinBFWindow* window
|
||||||
mD3DRenderTargetView = NULL;
|
mD3DRenderTargetView = NULL;
|
||||||
mD3DDepthBuffer = NULL;
|
mD3DDepthBuffer = NULL;
|
||||||
mD3DDepthStencilView = NULL;
|
mD3DDepthStencilView = NULL;
|
||||||
|
mRefreshRate = 0;
|
||||||
|
mFrameWaitObject = NULL;
|
||||||
|
|
||||||
mRenderDevice = renderDevice;
|
mRenderDevice = renderDevice;
|
||||||
mDXRenderDevice = renderDevice;
|
mDXRenderDevice = renderDevice;
|
||||||
|
@ -1275,30 +1539,31 @@ DXRenderWindow::DXRenderWindow(DXRenderDevice* renderDevice, WinBFWindow* window
|
||||||
ReinitNative();
|
ReinitNative();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
DXRenderWindow::~DXRenderWindow()
|
DXRenderWindow::~DXRenderWindow()
|
||||||
{
|
{
|
||||||
ReleaseNative();
|
ReleaseNative();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void DXRenderWindow::ReleaseNative()
|
void DXRenderWindow::ReleaseNative()
|
||||||
{
|
{
|
||||||
|
if (mFrameWaitObject != NULL)
|
||||||
|
::CloseHandle(mFrameWaitObject);
|
||||||
|
mFrameWaitObject = NULL;
|
||||||
if (mD3DRenderTargetView != NULL)
|
if (mD3DRenderTargetView != NULL)
|
||||||
{
|
|
||||||
mD3DRenderTargetView->Release();
|
mD3DRenderTargetView->Release();
|
||||||
mD3DRenderTargetView = NULL;
|
mD3DRenderTargetView = NULL;
|
||||||
}
|
|
||||||
if (mD3DBackBuffer != NULL)
|
if (mD3DBackBuffer != NULL)
|
||||||
{
|
|
||||||
mD3DBackBuffer->Release();
|
mD3DBackBuffer->Release();
|
||||||
mD3DBackBuffer = NULL;
|
mD3DBackBuffer = NULL;
|
||||||
}
|
|
||||||
if (mDXSwapChain != NULL)
|
if (mDXSwapChain != NULL)
|
||||||
{
|
|
||||||
mDXSwapChain->Release();
|
mDXSwapChain->Release();
|
||||||
mDXSwapChain = NULL;
|
mDXSwapChain = NULL;
|
||||||
}
|
if (mD3DRenderTargetView != NULL)
|
||||||
|
mD3DRenderTargetView->Release();
|
||||||
|
mD3DRenderTargetView = NULL;
|
||||||
|
if (mD3DDepthStencilView != NULL)
|
||||||
|
mD3DDepthStencilView->Release();
|
||||||
|
mD3DDepthStencilView = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void DXRenderWindow::ReinitNative()
|
void DXRenderWindow::ReinitNative()
|
||||||
|
@ -1314,8 +1579,8 @@ void DXRenderWindow::ReinitNative()
|
||||||
swapChainDesc.SampleDesc.Count = 1;
|
swapChainDesc.SampleDesc.Count = 1;
|
||||||
swapChainDesc.SampleDesc.Quality = 0;
|
swapChainDesc.SampleDesc.Quality = 0;
|
||||||
swapChainDesc.Windowed = mWindowed ? TRUE : FALSE;
|
swapChainDesc.Windowed = mWindowed ? TRUE : FALSE;
|
||||||
swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;
|
swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;// DXGI_SWAP_EFFECT_FLIP_DISCARD;
|
||||||
swapChainDesc.Flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH;
|
swapChainDesc.Flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH /*| DXGI_SWAP_CHAIN_FLAG_FRAME_LATENCY_WAITABLE_OBJECT*/;
|
||||||
|
|
||||||
IDXGIDevice* pDXGIDevice = NULL;
|
IDXGIDevice* pDXGIDevice = NULL;
|
||||||
mDXRenderDevice->mD3DDevice->QueryInterface(__uuidof(IDXGIDevice), (void**)&pDXGIDevice);
|
mDXRenderDevice->mD3DDevice->QueryInterface(__uuidof(IDXGIDevice), (void**)&pDXGIDevice);
|
||||||
|
@ -1324,6 +1589,14 @@ void DXRenderWindow::ReinitNative()
|
||||||
pDXGIDevice->Release();
|
pDXGIDevice->Release();
|
||||||
pDXGIDevice = NULL;
|
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(mDXSwapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), (LPVOID*)&mD3DBackBuffer));
|
||||||
DXCHECK(mDXRenderDevice->mD3DDevice->CreateRenderTargetView(mD3DBackBuffer, NULL, &mD3DRenderTargetView));
|
DXCHECK(mDXRenderDevice->mD3DDevice->CreateRenderTargetView(mD3DBackBuffer, NULL, &mD3DRenderTargetView));
|
||||||
|
|
||||||
|
@ -1406,7 +1679,14 @@ void DXRenderWindow::Resized()
|
||||||
mD3DDepthBuffer->Release();
|
mD3DDepthBuffer->Release();
|
||||||
mD3DRenderTargetView->Release();
|
mD3DRenderTargetView->Release();
|
||||||
mD3DDepthStencilView->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;
|
D3D11_TEXTURE2D_DESC descDepth;
|
||||||
ZeroMemory(&descDepth, sizeof(descDepth));
|
ZeroMemory(&descDepth, sizeof(descDepth));
|
||||||
|
@ -1435,8 +1715,10 @@ void DXRenderWindow::Resized()
|
||||||
|
|
||||||
void DXRenderWindow::Present()
|
void DXRenderWindow::Present()
|
||||||
{
|
{
|
||||||
mDXSwapChain->Present((mWindow->mFlags & BFWINDOW_VSYNC) ? 1 : 0, 0);
|
HRESULT hr = mDXSwapChain->Present((mWindow->mFlags & BFWINDOW_VSYNC) ? 1 : 0, 0);
|
||||||
//DXCHECK();
|
|
||||||
|
if ((hr == DXGI_ERROR_DEVICE_REMOVED) || (hr == DXGI_ERROR_DEVICE_RESET))
|
||||||
|
((DXRenderDevice*)mRenderDevice)->mNeedsReinitNative = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void DXRenderWindow::CopyBitsTo(uint32* dest, int width, int height)
|
void DXRenderWindow::CopyBitsTo(uint32* dest, int width, int height)
|
||||||
|
@ -1476,21 +1758,102 @@ void DXRenderWindow::CopyBitsTo(uint32* dest, int width, int height)
|
||||||
texture->Release();
|
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()
|
DXRenderDevice::DXRenderDevice()
|
||||||
{
|
{
|
||||||
mD3DDevice = NULL;
|
mD3DDevice = NULL;
|
||||||
|
mNeedsReinitNative = false;
|
||||||
|
mMatrix2DBuffer = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
DXRenderDevice::~DXRenderDevice()
|
DXRenderDevice::~DXRenderDevice()
|
||||||
{
|
{
|
||||||
for (auto& kv : mTextureMap)
|
for (auto window : mRenderWindowList)
|
||||||
kv.mValue->mRenderDevice = NULL;
|
((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;
|
delete mDefaultRenderState;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1498,6 +1861,7 @@ bool DXRenderDevice::Init(BFApp* app)
|
||||||
{
|
{
|
||||||
BP_ZONE("DXRenderDevice::Init");
|
BP_ZONE("DXRenderDevice::Init");
|
||||||
|
|
||||||
|
mApp = app;
|
||||||
WinBFApp* winApp = (WinBFApp*) app;
|
WinBFApp* winApp = (WinBFApp*) app;
|
||||||
|
|
||||||
D3D_FEATURE_LEVEL featureLevelArr[] =
|
D3D_FEATURE_LEVEL featureLevelArr[] =
|
||||||
|
@ -1626,6 +1990,9 @@ void DXRenderDevice::ReleaseNative()
|
||||||
{
|
{
|
||||||
mD3DVertexBuffer->Release();
|
mD3DVertexBuffer->Release();
|
||||||
mD3DVertexBuffer = NULL;
|
mD3DVertexBuffer = NULL;
|
||||||
|
if (mMatrix2DBuffer != NULL)
|
||||||
|
mMatrix2DBuffer->Release();
|
||||||
|
mMatrix2DBuffer = NULL;
|
||||||
mD3DIndexBuffer->Release();
|
mD3DIndexBuffer->Release();
|
||||||
mD3DIndexBuffer = NULL;
|
mD3DIndexBuffer = NULL;
|
||||||
mD3DNormalBlendState->Release();
|
mD3DNormalBlendState->Release();
|
||||||
|
@ -1636,20 +2003,37 @@ void DXRenderDevice::ReleaseNative()
|
||||||
mD3DWrapSamplerState = NULL;
|
mD3DWrapSamplerState = NULL;
|
||||||
mD3DDeviceContext->Release();
|
mD3DDeviceContext->Release();
|
||||||
mD3DDeviceContext = NULL;
|
mD3DDeviceContext = NULL;
|
||||||
|
|
||||||
|
// ID3D11Debug* debug = NULL;
|
||||||
|
// mD3DDevice->QueryInterface(__uuidof(ID3D11Debug), (void**)&debug);
|
||||||
|
// if (debug != NULL)
|
||||||
|
// {
|
||||||
|
// debug->ReportLiveDeviceObjects(D3D11_RLDO_DETAIL);
|
||||||
|
// debug->Release();
|
||||||
|
// }
|
||||||
|
|
||||||
mD3DDevice->Release();
|
mD3DDevice->Release();
|
||||||
mD3DDevice = NULL;
|
mD3DDevice = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void DXRenderDevice::ReinitNative()
|
void DXRenderDevice::ReinitNative()
|
||||||
{
|
{
|
||||||
Init(NULL);
|
AutoCrit autoCrit(mApp->mCritSect);
|
||||||
|
|
||||||
|
if (mMatrix2DBuffer != NULL)
|
||||||
|
mMatrix2DBuffer->Release();
|
||||||
|
mMatrix2DBuffer = NULL;
|
||||||
|
|
||||||
|
Init(mApp);
|
||||||
|
|
||||||
for (auto window : mRenderWindowList)
|
for (auto window : mRenderWindowList)
|
||||||
((DXRenderWindow*)window)->ReinitNative();
|
((DXRenderWindow*)window)->ReinitNative();
|
||||||
for (auto kv : mRenderStates)
|
for (auto shader : mShaders)
|
||||||
kv->ReinitNative();
|
shader->ReinitNative();
|
||||||
for (auto kv : mRenderStates)
|
for (auto renderState : mRenderStates)
|
||||||
kv->ReinitNative();
|
renderState->ReinitNative();
|
||||||
|
for (auto tex : mTextures)
|
||||||
|
tex->ReinitNative();
|
||||||
}
|
}
|
||||||
|
|
||||||
void DXRenderDevice::FrameStart()
|
void DXRenderDevice::FrameStart()
|
||||||
|
@ -1918,6 +2302,10 @@ Texture* DXRenderDevice::LoadTexture(ImageData* imageData, int flags)
|
||||||
DXCHECK(mD3DDevice->CreateShaderResourceView(d3DTexture, &srDesc, &d3DShaderResourceView));
|
DXCHECK(mD3DDevice->CreateShaderResourceView(d3DTexture, &srDesc, &d3DShaderResourceView));
|
||||||
|
|
||||||
DXTexture* aTexture = new DXTexture();
|
DXTexture* aTexture = new DXTexture();
|
||||||
|
|
||||||
|
aTexture->mContentBits = new uint32[aWidth * aHeight];
|
||||||
|
memcpy(aTexture->mContentBits, imageData->mBits, aWidth * aHeight * 4);
|
||||||
|
|
||||||
aTexture->mRenderDevice = this;
|
aTexture->mRenderDevice = this;
|
||||||
aTexture->mWidth = aWidth;
|
aTexture->mWidth = aWidth;
|
||||||
aTexture->mHeight = aHeight;
|
aTexture->mHeight = aHeight;
|
||||||
|
@ -1976,203 +2364,20 @@ Texture* DXRenderDevice::CreateDynTexture(int width, int height)
|
||||||
return aTexture;
|
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)
|
Shader* DXRenderDevice::LoadShader(const StringImpl& fileName, VertexDefinition* vertexDefinition)
|
||||||
{
|
{
|
||||||
BP_ZONE("DXRenderDevice::LoadShader");
|
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* dxShader = new DXShader();
|
||||||
|
dxShader->mRenderDevice = this;
|
||||||
dxShader->mVertexSize = 0;
|
dxShader->mSrcPath = fileName;
|
||||||
dxShader->mD3DLayout = NULL;
|
dxShader->mVertexDef = new VertexDefinition(vertexDefinition);
|
||||||
|
if (!dxShader->Load())
|
||||||
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++)
|
|
||||||
{
|
{
|
||||||
VertexDefData* vertexDefData = &vertexDefinition->mElementData[elementIdx];
|
delete dxShader;
|
||||||
|
return NULL;
|
||||||
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];
|
|
||||||
}
|
}
|
||||||
|
mShaders.Add(dxShader);
|
||||||
/* =
|
|
||||||
{
|
|
||||||
{ "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();
|
|
||||||
return dxShader;
|
return dxShader;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -63,7 +63,7 @@ public:
|
||||||
ID3D11RenderTargetView* mD3DRenderTargetView;
|
ID3D11RenderTargetView* mD3DRenderTargetView;
|
||||||
ID3D11Texture2D* mD3DDepthBuffer;
|
ID3D11Texture2D* mD3DDepthBuffer;
|
||||||
ID3D11DepthStencilView* mD3DDepthStencilView;
|
ID3D11DepthStencilView* mD3DDepthStencilView;
|
||||||
ImageData* mImageData;
|
uint32* mContentBits;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
DXTexture();
|
DXTexture();
|
||||||
|
@ -96,6 +96,10 @@ typedef std::map<String, DXShaderParam*> DXShaderParamMap;
|
||||||
class DXShader : public Shader
|
class DXShader : public Shader
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
DXRenderDevice* mRenderDevice;
|
||||||
|
String mSrcPath;
|
||||||
|
VertexDefinition* mVertexDef;
|
||||||
|
|
||||||
ID3D11InputLayout* mD3DLayout;
|
ID3D11InputLayout* mD3DLayout;
|
||||||
ID3D11VertexShader* mD3DVertexShader;
|
ID3D11VertexShader* mD3DVertexShader;
|
||||||
ID3D11PixelShader* mD3DPixelShader;
|
ID3D11PixelShader* mD3DPixelShader;
|
||||||
|
@ -107,6 +111,10 @@ public:
|
||||||
DXShader();
|
DXShader();
|
||||||
~DXShader();
|
~DXShader();
|
||||||
|
|
||||||
|
void ReleaseNative();
|
||||||
|
void ReinitNative();
|
||||||
|
|
||||||
|
bool Load();
|
||||||
virtual ShaderParam* GetShaderParam(const StringImpl& name) override;
|
virtual ShaderParam* GetShaderParam(const StringImpl& name) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -144,6 +152,8 @@ public:
|
||||||
ID3D11RenderTargetView* mD3DRenderTargetView;
|
ID3D11RenderTargetView* mD3DRenderTargetView;
|
||||||
ID3D11Texture2D* mD3DDepthBuffer;
|
ID3D11Texture2D* mD3DDepthBuffer;
|
||||||
ID3D11DepthStencilView* mD3DDepthStencilView;
|
ID3D11DepthStencilView* mD3DDepthStencilView;
|
||||||
|
HANDLE mFrameWaitObject;
|
||||||
|
float mRefreshRate;
|
||||||
bool mResizePending;
|
bool mResizePending;
|
||||||
bool mWindowed;
|
bool mWindowed;
|
||||||
int mPendingWidth;
|
int mPendingWidth;
|
||||||
|
@ -164,6 +174,8 @@ public:
|
||||||
virtual void Present() override;
|
virtual void Present() override;
|
||||||
|
|
||||||
void CopyBitsTo(uint32* dest, int width, int height);
|
void CopyBitsTo(uint32* dest, int width, int height);
|
||||||
|
virtual float GetRefreshRate() override;
|
||||||
|
virtual bool WaitForVBlank() override;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef std::vector<DXDrawBatch*> DXDrawBatchVector;
|
typedef std::vector<DXDrawBatch*> DXDrawBatchVector;
|
||||||
|
@ -285,8 +297,9 @@ public:
|
||||||
ID3D11BlendState* mD3DNormalBlendState;
|
ID3D11BlendState* mD3DNormalBlendState;
|
||||||
ID3D11SamplerState* mD3DDefaultSamplerState;
|
ID3D11SamplerState* mD3DDefaultSamplerState;
|
||||||
ID3D11SamplerState* mD3DWrapSamplerState;
|
ID3D11SamplerState* mD3DWrapSamplerState;
|
||||||
bool mHasVSync;
|
bool mNeedsReinitNative;
|
||||||
|
|
||||||
|
ID3D11Buffer* mMatrix2DBuffer;
|
||||||
ID3D11Buffer* mD3DVertexBuffer;
|
ID3D11Buffer* mD3DVertexBuffer;
|
||||||
ID3D11Buffer* mD3DIndexBuffer;
|
ID3D11Buffer* mD3DIndexBuffer;
|
||||||
int mVtxByteIdx;
|
int mVtxByteIdx;
|
||||||
|
@ -294,6 +307,7 @@ public:
|
||||||
|
|
||||||
HashSet<DXRenderState*> mRenderStates;
|
HashSet<DXRenderState*> mRenderStates;
|
||||||
HashSet<DXTexture*> mTextures;
|
HashSet<DXTexture*> mTextures;
|
||||||
|
HashSet<DXShader*> mShaders;
|
||||||
Dictionary<String, DXTexture*> mTextureMap;
|
Dictionary<String, DXTexture*> mTextureMap;
|
||||||
Dictionary<int, ID3D11Buffer*> mBufferMap;
|
Dictionary<int, ID3D11Buffer*> mBufferMap;
|
||||||
|
|
||||||
|
|
|
@ -600,6 +600,9 @@ LRESULT WinBFWindow::WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lPar
|
||||||
|
|
||||||
switch (uMsg)
|
switch (uMsg)
|
||||||
{
|
{
|
||||||
|
case WM_DISPLAYCHANGE:
|
||||||
|
((DXRenderWindow*)mRenderWindow)->mRefreshRate = 0;
|
||||||
|
break;
|
||||||
case WM_SIZE:
|
case WM_SIZE:
|
||||||
mRenderWindow->Resized();
|
mRenderWindow->Resized();
|
||||||
if (mMovedFunc != NULL)
|
if (mMovedFunc != NULL)
|
||||||
|
@ -986,7 +989,6 @@ LRESULT WinBFWindow::WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lPar
|
||||||
case WM_SYSKEYDOWN:
|
case WM_SYSKEYDOWN:
|
||||||
case WM_KEYDOWN:
|
case WM_KEYDOWN:
|
||||||
{
|
{
|
||||||
|
|
||||||
mIsMenuKeyHandled = false;
|
mIsMenuKeyHandled = false;
|
||||||
int keyCode = (int) wParam;
|
int keyCode = (int) wParam;
|
||||||
if (keyCode == VK_APPS)
|
if (keyCode == VK_APPS)
|
||||||
|
@ -997,6 +999,11 @@ LRESULT WinBFWindow::WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lPar
|
||||||
|
|
||||||
mIsKeyDown[keyCode] = true;
|
mIsKeyDown[keyCode] = true;
|
||||||
|
|
||||||
|
// if ((keyCode == 192) && (mIsKeyDown[VK_MENU]))
|
||||||
|
// {
|
||||||
|
// ((DXRenderDevice*)mRenderWindow->mRenderDevice)->mNeedsReinitNative = true;
|
||||||
|
// }
|
||||||
|
|
||||||
for (auto kv : *menuIDMap)
|
for (auto kv : *menuIDMap)
|
||||||
{
|
{
|
||||||
WinBFMenu* aMenu = kv.mValue;
|
WinBFMenu* aMenu = kv.mValue;
|
||||||
|
@ -1275,10 +1282,71 @@ WinBFApp::WinBFApp()
|
||||||
mInMsgProc = false;
|
mInMsgProc = false;
|
||||||
mDSoundManager = NULL;
|
mDSoundManager = NULL;
|
||||||
mDInputManager = 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()
|
WinBFApp::~WinBFApp()
|
||||||
{
|
{
|
||||||
|
mClosing = true;
|
||||||
|
BfpThread_WaitFor(mVSyncThread, -1);
|
||||||
|
BfpThread_Release(mVSyncThread);
|
||||||
|
|
||||||
delete mRenderDevice;
|
delete mRenderDevice;
|
||||||
delete mDSoundManager;
|
delete mDSoundManager;
|
||||||
delete mDInputManager;
|
delete mDInputManager;
|
||||||
|
@ -1288,6 +1356,8 @@ void WinBFApp::Init()
|
||||||
{
|
{
|
||||||
BP_ZONE("WinBFApp::Init");
|
BP_ZONE("WinBFApp::Init");
|
||||||
|
|
||||||
|
AutoCrit autoCrit(mCritSect);
|
||||||
|
|
||||||
mRunning = true;
|
mRunning = true;
|
||||||
mInMsgProc = false;
|
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()
|
void WinBFApp::Draw()
|
||||||
{
|
{
|
||||||
mRenderDevice->FrameStart();
|
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)
|
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);
|
BFWindow* aWindow = new WinBFWindow(parent, title, x, y, width, height, windowFlags);
|
||||||
mWindowList.push_back(aWindow);
|
mWindowList.push_back(aWindow);
|
||||||
|
|
||||||
|
@ -2025,6 +2110,13 @@ BFSoundManager* WinBFApp::GetSoundManager()
|
||||||
return mDSoundManager;
|
return mDSoundManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
intptr WinBFApp::GetCriticalThreadId(int idx)
|
||||||
|
{
|
||||||
|
if (idx == 0)
|
||||||
|
return mVSyncThreadId;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
void WinBFWindow::ModalsRemoved()
|
void WinBFWindow::ModalsRemoved()
|
||||||
{
|
{
|
||||||
::EnableWindow(mHWnd, TRUE);
|
::EnableWindow(mHWnd, TRUE);
|
||||||
|
|
|
@ -98,8 +98,14 @@ public:
|
||||||
StringToUIntMap mClipboardFormatMap;
|
StringToUIntMap mClipboardFormatMap;
|
||||||
DSoundManager* mDSoundManager;
|
DSoundManager* mDSoundManager;
|
||||||
DInputManager* mDInputManager;
|
DInputManager* mDInputManager;
|
||||||
|
BfpThreadId mVSyncThreadId;
|
||||||
|
BfpThread* mVSyncThread;
|
||||||
|
volatile bool mClosing;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
void VSyncThreadProc();
|
||||||
|
static void BFP_CALLTYPE VSyncThreadProcThunk(void* ptr);
|
||||||
|
|
||||||
virtual void Draw() override;
|
virtual void Draw() override;
|
||||||
virtual void PhysSetCursor() override;
|
virtual void PhysSetCursor() override;
|
||||||
|
|
||||||
|
@ -111,6 +117,7 @@ public:
|
||||||
|
|
||||||
virtual void Init() override;
|
virtual void Init() override;
|
||||||
virtual void Run() override;
|
virtual void Run() override;
|
||||||
|
virtual void Process() override;
|
||||||
|
|
||||||
virtual void GetDesktopResolution(int& width, int& height) override;
|
virtual void GetDesktopResolution(int& width, int& height) override;
|
||||||
virtual void GetWorkspaceRect(int& x, int& y, 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 BFSysBitmap* LoadSysBitmap(const WCHAR* fileName) override;
|
||||||
|
|
||||||
virtual BFSoundManager* GetSoundManager() override;
|
virtual BFSoundManager* GetSoundManager() override;
|
||||||
|
|
||||||
|
virtual intptr GetCriticalThreadId(int idx) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
NS_BF_END;
|
NS_BF_END;
|
||||||
|
|
|
@ -11767,7 +11767,6 @@ namespace IDE
|
||||||
public override void Init()
|
public override void Init()
|
||||||
{
|
{
|
||||||
scope AutoBeefPerf("IDEApp.Init");
|
scope AutoBeefPerf("IDEApp.Init");
|
||||||
|
|
||||||
//int zag = 123;
|
//int zag = 123;
|
||||||
|
|
||||||
if (mVerbosity == .Default)
|
if (mVerbosity == .Default)
|
||||||
|
@ -14203,7 +14202,7 @@ namespace IDE
|
||||||
//mDebugger.InitiateHotResolve(.ActiveMethods | .Allocations);
|
//mDebugger.InitiateHotResolve(.ActiveMethods | .Allocations);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void Draw()
|
public override void Draw(bool forceDraw)
|
||||||
{
|
{
|
||||||
scope AutoBeefPerf("IDEApp.Draw");
|
scope AutoBeefPerf("IDEApp.Draw");
|
||||||
#if CLI
|
#if CLI
|
||||||
|
@ -14213,7 +14212,7 @@ namespace IDE
|
||||||
if (mBfResolveSystem != null)
|
if (mBfResolveSystem != null)
|
||||||
{
|
{
|
||||||
mBfResolveSystem.PerfZoneStart("IDEApp.Draw");
|
mBfResolveSystem.PerfZoneStart("IDEApp.Draw");
|
||||||
base.Draw();
|
base.Draw(forceDraw);
|
||||||
mBfResolveSystem.PerfZoneEnd();
|
mBfResolveSystem.PerfZoneEnd();
|
||||||
if (mBfResolveSystem.mIsTiming)
|
if (mBfResolveSystem.mIsTiming)
|
||||||
{
|
{
|
||||||
|
@ -14222,7 +14221,7 @@ namespace IDE
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
base.Draw();
|
base.Draw(forceDraw);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void DrawSquiggle(Graphics g, float x, float y, float width)
|
public void DrawSquiggle(Graphics g, float x, float y, float width)
|
||||||
|
|
|
@ -3,11 +3,15 @@ using Beefy.gfx;
|
||||||
using System;
|
using System;
|
||||||
using Beefy.events;
|
using Beefy.events;
|
||||||
using Beefy.widgets;
|
using Beefy.widgets;
|
||||||
|
using System.Collections;
|
||||||
|
using System.Diagnostics;
|
||||||
|
|
||||||
namespace IDE.ui
|
namespace IDE.ui
|
||||||
{
|
{
|
||||||
class AboutDialog : IDEDialog
|
class AboutDialog : IDEDialog
|
||||||
{
|
{
|
||||||
|
static AboutDialog gAboutDialog;
|
||||||
|
|
||||||
const int cWidth = 320;
|
const int cWidth = 320;
|
||||||
const int cHeight = 240;
|
const int cHeight = 240;
|
||||||
const int cRandSize = 3777;
|
const int cRandSize = 3777;
|
||||||
|
@ -21,6 +25,14 @@ namespace IDE.ui
|
||||||
uint8[cRandSize] mRand;
|
uint8[cRandSize] mRand;
|
||||||
int mRandIdx;
|
int mRandIdx;
|
||||||
|
|
||||||
|
Stopwatch mStopwatch = new .()..Start() ~ delete _;
|
||||||
|
struct Entry
|
||||||
|
{
|
||||||
|
public double mUpdateCntF;
|
||||||
|
public float mTimeMS;
|
||||||
|
}
|
||||||
|
List<Entry> mEntries = new .() ~ delete _;
|
||||||
|
|
||||||
struct CColor
|
struct CColor
|
||||||
{
|
{
|
||||||
public uint8 r;
|
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));
|
Color colorOut = Color.ToNative(Color.Lerp(mainColors[(int)colorPos], mainColors[(int)colorPos + 1], colorPos - (int)colorPos));
|
||||||
mPalette[i] = colorOut;
|
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()
|
public override void CalcSize()
|
||||||
|
@ -140,12 +168,12 @@ namespace IDE.ui
|
||||||
|
|
||||||
mImage.SetBits(0, 0, cWidth, cHeight, cWidth, newBits);
|
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.SetFont(mBigFont);
|
||||||
g.DrawString("Beef IDE", 0, GS!(20) + (1.0f - Math.Sin(ang))*GS!(300), .Centered, mWidth);
|
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 angMed = Math.Min((float)(mUpdateCntF * 0.0055f), Math.PI_f / 2);
|
||||||
float alpha = Math.Clamp(mUpdateCnt * 0.007f - 1.3f, 0, 1.0f);
|
float alpha = Math.Clamp((float)(mUpdateCntF * 0.007f) - 1.3f, 0, 1.0f);
|
||||||
|
|
||||||
using (g.PushColor(Color.Get(alpha)))
|
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);
|
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()
|
public override void Update()
|
||||||
|
@ -177,6 +232,12 @@ namespace IDE.ui
|
||||||
DoFire();
|
DoFire();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override void UpdateF(float updatePct)
|
||||||
|
{
|
||||||
|
base.UpdateF(updatePct);
|
||||||
|
MarkDirty();
|
||||||
|
}
|
||||||
|
|
||||||
public override void KeyDown(KeyCode keyCode, bool isRepeat)
|
public override void KeyDown(KeyCode keyCode, bool isRepeat)
|
||||||
{
|
{
|
||||||
base.KeyDown(keyCode, isRepeat);
|
base.KeyDown(keyCode, isRepeat);
|
||||||
|
|
|
@ -6508,7 +6508,7 @@ namespace IDE.ui
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void UpdateCollapse()
|
public void UpdateCollapse(float updatePct)
|
||||||
{
|
{
|
||||||
MarkDirty();
|
MarkDirty();
|
||||||
|
|
||||||
|
@ -6564,9 +6564,12 @@ namespace IDE.ui
|
||||||
{
|
{
|
||||||
if (emitEmbed.mIsOpen)
|
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)
|
if (emitEmbed.mOpenPct != 1.0f)
|
||||||
|
{
|
||||||
mCollapseNeedsUpdate = true;
|
mCollapseNeedsUpdate = true;
|
||||||
|
mWidgetWindow.mTempWantsUpdateF = true;
|
||||||
|
}
|
||||||
|
|
||||||
if (emitEmbed.mView == null)
|
if (emitEmbed.mView == null)
|
||||||
{
|
{
|
||||||
|
@ -6577,7 +6580,7 @@ namespace IDE.ui
|
||||||
}
|
}
|
||||||
else
|
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.mOpenPct == 0.0f)
|
||||||
{
|
{
|
||||||
if (emitEmbed.mView != null)
|
if (emitEmbed.mView != null)
|
||||||
|
@ -6587,7 +6590,10 @@ namespace IDE.ui
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
mCollapseNeedsUpdate = true;
|
mCollapseNeedsUpdate = true;
|
||||||
|
mWidgetWindow.mTempWantsUpdateF = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -6664,13 +6670,14 @@ namespace IDE.ui
|
||||||
var entry = mOrderedCollapseEntries[animIdx];
|
var entry = mOrderedCollapseEntries[animIdx];
|
||||||
if ((entry.mIsOpen) && (entry.mOpenPct < 1.0f))
|
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))
|
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)
|
if (entry.mOpenPct == 0.0f)
|
||||||
FinishCollapseClose(animIdx, entry);
|
FinishCollapseClose(animIdx, entry);
|
||||||
}
|
}
|
||||||
|
|
|
@ -639,6 +639,7 @@ namespace IDE.ui
|
||||||
mNavigationBar = new NavigationBar(this);
|
mNavigationBar = new NavigationBar(this);
|
||||||
AddWidget(mNavigationBar);
|
AddWidget(mNavigationBar);
|
||||||
}
|
}
|
||||||
|
mAlwaysUpdateF = true;
|
||||||
}
|
}
|
||||||
public ~this()
|
public ~this()
|
||||||
{
|
{
|
||||||
|
@ -6811,13 +6812,19 @@ namespace IDE.ui
|
||||||
|
|
||||||
UpdateQueuedEmitShowData();
|
UpdateQueuedEmitShowData();
|
||||||
|
|
||||||
if (ewc.mCollapseNeedsUpdate)
|
|
||||||
ewc.UpdateCollapse();
|
|
||||||
|
|
||||||
// Process after mQueuedCollapseData so mCharIdSpan is still valid
|
// Process after mQueuedCollapseData so mCharIdSpan is still valid
|
||||||
ProcessDeferredResolveResults(0);
|
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()
|
public void UpdateQueuedEmitShowData()
|
||||||
{
|
{
|
||||||
var compiler = ResolveCompiler;
|
var compiler = ResolveCompiler;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue