Index: /trunk/src/VBox/Additions/WINNT/Graphics/Display/wddm/VBoxDispD3D.cpp
===================================================================
--- /trunk/src/VBox/Additions/WINNT/Graphics/Display/wddm/VBoxDispD3D.cpp	(revision 32961)
+++ /trunk/src/VBox/Additions/WINNT/Graphics/Display/wddm/VBoxDispD3D.cpp	(revision 32962)
@@ -29,13 +29,65 @@
 #ifdef VBOX_WDDMDISP_WITH_PROFILE
 #include "VBoxDispProfile.h"
+
+/* uncomment to enable particular logging */
+#define VBOXDISPPROFILE_DDI_STATISTIC_LOGGER_ENABLE
+//#define VBOXDISPPROFILE_DDI_FUNCTION_LOGGER_ENABLE
+
+#ifdef VBOXDISPPROFILE_DDI_FUNCTION_LOGGER_ENABLE
 static VBoxDispProfileSet g_VBoxDispProfileDDI("D3D_DDI");
-//static BOOL g_VBoxDispPrifileDDIDumpAndReset = FALSE;
-#define VBOXDISPPROFILE_FUNCTION_DDI_PROLOGUE() VBOXDISPPROFILE_FUNCTION_PROLOGUE(g_VBoxDispProfileDDI)
+#define VBOXDISPPROFILE_DDI_FUNCTION_LOGGER_PROLOGUE() VBOXDISPPROFILE_FUNCTION_LOGGER_DEFINE(g_VBoxDispProfileDDI)
+#define VBOXDDIROFILE_FUNCTION_LOGGER_DUMP() do {\
+        g_VBoxDispProfileDDI.dump(_pDev); \
+    } while (0)
+#define VBOXDISPPROFILE_DDI_FUNCTION_LOGGER_RESET() do {\
+        g_VBoxDispProfileDDI.resetEntries();\
+    } while (0)
+#define VBOXDISPPROFILE_DDI_FUNCTION_LOGGER_DISABLE_CURRENT() do {\
+        VBOXDISPPROFILE_FUNCTION_LOGGER_DISABLE_CURRENT();\
+    } while (0)
+
+
+#else
+#define VBOXDISPPROFILE_DDI_FUNCTION_LOGGER_PROLOGUE() do {} while(0)
+#define VBOXDISPPROFILE_DDI_FUNCTION_LOGGER_DUMP() do {} while(0)
+#define VBOXDISPPROFILE_DDI_FUNCTION_LOGGER_RESET() do {} while(0)
+#define VBOXDISPPROFILE_DDI_FUNCTION_LOGGER_DISABLE_CURRENT() do {} while (0)
+#endif
+
+#ifdef VBOXDISPPROFILE_DDI_STATISTIC_LOGGER_ENABLE
+static VBoxDispProfileFpsCounter g_VBoxDispFpsDDI(64);
+#define VBOXDISPPROFILE_DDI_STATISTIC_LOGGER_PROLOGUE() VBOXDISPPROFILE_STATISTIC_LOGGER_DEFINE(&g_VBoxDispFpsDDI)
+#define VBOXDISPPROFILE_DDI_STATISTIC_LOGGER_DISABLE_CURRENT() do {\
+        VBOXDISPPROFILE_STATISTIC_LOGGER_DISABLE_CURRENT();\
+    } while (0)
+#define VBOXDISPPROFILE_DDI_STATISTIC_LOGGER_REPORT_FRAME(_pDev) do { \
+        VBOXDISPPROFILE_STATISTIC_LOGGER_LOG_AND_DISABLE_CURRENT(); \
+        g_VBoxDispFpsDDI.ReportFrame(); \
+        if(!(g_VBoxDispFpsDDI.GetNumFrames() % 31)) \
+        { \
+            double fps = g_VBoxDispFpsDDI.GetFps(); \
+            double cps = g_VBoxDispFpsDDI.GetCps(); \
+            double tup = g_VBoxDispFpsDDI.GetTimeProcPercent(); \
+            VBOXDISPPROFILE_DUMP((_pDev, "fps: %f, cps: %.1f, host %.1f%%\n", fps, cps, tup)); \
+        } \
+    } while (0)
+#else
+#define VBOXDISPPROFILE_DDI_STATISTIC_LOGGER_PROLOGUE() do {} while(0)
+#define VBOXDISPPROFILE_DDI_STATISTIC_LOGGER_DISABLE_CURRENT() do {} while (0)
+#define VBOXDISPPROFILE_DDI_STATISTIC_LOGGER_REPORT_FRAME(_pDev) do {} while (0)
+#endif
+
+#define VBOXDISPPROFILE_FUNCTION_DDI_PROLOGUE() \
+        VBOXDISPPROFILE_DDI_FUNCTION_LOGGER_PROLOGUE(); \
+        VBOXDISPPROFILE_DDI_STATISTIC_LOGGER_PROLOGUE();
 
 #define VBOXDISPPROFILE_DDI_DUMPRESET(_pDev) do {\
-        AssertRelease(0); \
-        g_VBoxDispProfileDDI.dump(_pDev);\
-        g_VBoxDispProfileDDI.resetEntries();\
-        VBOXDISPPROFILE_FUNCTION_LOGGER_DISABLE_CURRENT();\
+        VBOXDISPPROFILE_DDI_FUNCTION_LOGGER_DUMP(); \
+        VBOXDISPPROFILE_DDI_FUNCTION_LOGGER_RESET(); \
+        VBOXDISPPROFILE_DDI_FUNCTION_LOGGER_DISABLE_CURRENT();\
+    } while (0)
+
+#define VBOXDISPPROFILE_DDI_REPORT_FRAME(_pDev) do {\
+        VBOXDISPPROFILE_DDI_STATISTIC_LOGGER_REPORT_FRAME(_pDev); \
     } while (0)
 
@@ -44,4 +96,5 @@
 #define VBOXDISPPROFILE_FUNCTION_DDI_PROLOGUE() do {} while (0)
 #define VBOXDISPPROFILE_DDI_DUMPRESET(_pDev) do {} while (0)
+#define VBOXDISPPROFILE_DDI_REPORT_FRAME(_pDev) do {} while (0)
 #endif
 
@@ -5495,4 +5548,7 @@
         Assert(hr == S_OK);
     }
+
+    VBOXDISPPROFILE_DDI_REPORT_FRAME(pDevice);
+
     vboxVDbgPrintF(("<== "__FUNCTION__", hDevice(0x%p), hr(0x%x)\n", hDevice, hr));
     return hr;
Index: /trunk/src/VBox/Additions/WINNT/Graphics/Display/wddm/VBoxDispProfile.h
===================================================================
--- /trunk/src/VBox/Additions/WINNT/Graphics/Display/wddm/VBoxDispProfile.h	(revision 32961)
+++ /trunk/src/VBox/Additions/WINNT/Graphics/Display/wddm/VBoxDispProfile.h	(revision 32962)
@@ -114,8 +114,8 @@
 };
 
-class VBoxDispProfileScopeLogger
-{
-public:
-    VBoxDispProfileScopeLogger(VBoxDispProfileEntry *pEntry) :
+template<typename T> class VBoxDispProfileScopeLogger
+{
+public:
+    VBoxDispProfileScopeLogger(T *pEntry) :
         m_pEntry(pEntry),
         m_bDisable(FALSE)
@@ -128,6 +128,5 @@
         if (!m_bDisable)
         {
-            uint64_t cNewTime = VBOXDISPPROFILE_GET_TIME_NANO();
-            m_pEntry->step(cNewTime - m_cTime);
+            logStep();
         }
     }
@@ -137,12 +136,126 @@
         m_bDisable = TRUE;
     }
-private:
-    VBoxDispProfileEntry *m_pEntry;
+
+    void logAndDisable()
+    {
+        logStep();
+        disable();
+    }
+
+private:
+    void logStep()
+    {
+        uint64_t cNewTime = VBOXDISPPROFILE_GET_TIME_NANO();
+        m_pEntry->step(cNewTime - m_cTime);
+    }
+    T *m_pEntry;
     uint64_t m_cTime;
     BOOL m_bDisable;
 };
 
+
+class VBoxDispProfileFpsCounter
+{
+public:
+    VBoxDispProfileFpsCounter(uint32_t cPeriods)
+    {
+        memset(&m_Data, 0, sizeof (m_Data));
+        m_Data.mcPeriods = cPeriods;
+        m_Data.mpaPeriods = (uint64_t *)RTMemAllocZ(sizeof (m_Data.mpaPeriods[0]) * cPeriods);
+        m_Data.mpaCalls = (uint32_t *)RTMemAllocZ(sizeof (m_Data.mpaCalls[0]) * cPeriods);
+        m_Data.mpaTimes = (uint64_t *)RTMemAllocZ(sizeof (m_Data.mpaTimes[0]) * cPeriods);
+    }
+
+    ~VBoxDispProfileFpsCounter()
+    {
+        RTMemFree(m_Data.mpaPeriods);
+        RTMemFree(m_Data.mpaCalls);
+        RTMemFree(m_Data.mpaTimes);
+    }
+
+    void ReportFrame()
+    {
+        uint64_t cur = VBOXDISPPROFILE_GET_TIME_NANO();
+
+        if(m_Data.mPrevTime)
+        {
+            uint64_t curPeriod = cur - m_Data.mPrevTime;
+
+            m_Data.mPeriodSum += curPeriod - m_Data.mpaPeriods[m_Data.miPeriod];
+            m_Data.mpaPeriods[m_Data.miPeriod] = curPeriod;
+
+            m_Data.mCallsSum += m_Data.mCurCalls - m_Data.mpaCalls[m_Data.miPeriod];
+            m_Data.mpaCalls[m_Data.miPeriod] = m_Data.mCurCalls;
+
+            m_Data.mTimeUsedSum += m_Data.mCurTimeUsed - m_Data.mpaTimes[m_Data.miPeriod];
+            m_Data.mpaTimes[m_Data.miPeriod] = m_Data.mCurTimeUsed;
+
+            ++m_Data.miPeriod;
+            m_Data.miPeriod %= m_Data.mcPeriods;
+        }
+        m_Data.mPrevTime = cur;
+        ++m_Data.mcFrames;
+
+        m_Data.mCurTimeUsed = 0;
+        m_Data.mCurCalls = 0;
+    }
+
+    void step(uint64_t Time)
+    {
+        m_Data.mCurTimeUsed += Time;
+        ++m_Data.mCurCalls;
+    }
+
+    uint64_t GetEveragePeriod()
+    {
+        return m_Data.mPeriodSum / m_Data.mcPeriods;
+    }
+
+    double GetFps()
+    {
+        return ((double)1000000000.0) / GetEveragePeriod();
+    }
+
+    double GetCps()
+    {
+        return GetFps() * m_Data.mCallsSum / m_Data.mcPeriods;
+    }
+
+    double GetTimeProcPercent()
+    {
+        return 100.0*m_Data.mTimeUsedSum/m_Data.mPeriodSum;
+    }
+
+    uint64_t GetNumFrames()
+    {
+        return m_Data.mcFrames;
+    }
+private:
+    struct
+    {
+        uint64_t mPeriodSum;
+        uint64_t *mpaPeriods;
+        uint64_t mPrevTime;
+        uint64_t mcFrames;
+        uint32_t mcPeriods;
+        uint32_t miPeriod;
+
+        uint64_t mCallsSum;
+        uint32_t *mpaCalls;
+
+        uint64_t mTimeUsedSum;
+        uint64_t *mpaTimes;
+
+        uint64_t mCurTimeUsed;
+        uint64_t mCurCalls;
+    } m_Data;
+};
+
 #define VBOXDISPPROFILE_FUNCTION_LOGGER_DISABLE_CURRENT() do { \
-        __vboxDispProfileLogger.disable();\
+        __vboxDispProfileFunctionLogger.disable();\
+    } while (0)
+
+#define VBOXDISPPROFILE_FUNCTION_LOGGER_LOG_AND_DISABLE_CURRENT() do { \
+        __vboxDispProfileFunctionLogger.logAndDisable();\
     } while (0)
 
@@ -150,10 +263,20 @@
         static VBoxDispProfileEntry * __pVBoxDispProfileEntry = NULL; \
         if (!__pVBoxDispProfileEntry) { __pVBoxDispProfileEntry = _p.alloc(__FUNCTION__); } \
-        VBoxDispProfileScopeLogger __vboxDispProfileLogger(__pVBoxDispProfileEntry);
-
-
-#define VBOXDISPPROFILE_FUNCTION_PROLOGUE(_p) \
-        VBOXDISPPROFILE_FUNCTION_LOGGER_DEFINE(_p)
-
+        VBoxDispProfileScopeLogger<VBoxDispProfileEntry> __vboxDispProfileFunctionLogger(__pVBoxDispProfileEntry);
+
+#define VBOXDISPPROFILE_STATISTIC_LOGGER_DISABLE_CURRENT() do { \
+        __vboxDispProfileStatisticLogger.disable();\
+    } while (0)
+
+#define VBOXDISPPROFILE_STATISTIC_LOGGER_LOG_AND_DISABLE_CURRENT() do { \
+        __vboxDispProfileStatisticLogger.logAndDisable();\
+    } while (0)
+
+
+#define VBOXDISPPROFILE_STATISTIC_LOGGER_DEFINE(_p)  \
+        VBoxDispProfileScopeLogger<VBoxDispProfileFpsCounter> __vboxDispProfileStatisticLogger(_p);
+
+//#define VBOXDISPPROFILE_FUNCTION_PROLOGUE(_p) \
+//        VBOXDISPPROFILE_FUNCTION_LOGGER_DEFINE(_p)
 
 #endif /* #ifndef ___VBoxDispProfile_h__ */
Index: /trunk/src/VBox/Additions/WINNT/Graphics/Wine/wined3d/context.c
===================================================================
--- /trunk/src/VBox/Additions/WINNT/Graphics/Wine/wined3d/context.c	(revision 32961)
+++ /trunk/src/VBox/Additions/WINNT/Graphics/Wine/wined3d/context.c	(revision 32962)
@@ -1980,4 +1980,11 @@
 #endif
 
+#ifdef VBOX_WITH_WDDM
+    while (device->numContexts)
+    {
+        context_destroy(device, device->contexts[0]);
+    }
+#endif
+
     /* Create a new context for the thread */
     return swapchain_create_context_for_thread(swapchain);
