mirror of
https://github.com/juce-framework/JUCE.git
synced 2026-01-09 23:34:20 +00:00
This makes Direct2DMetrics and current frameId accessible to implementation subclasses. It also replaces JUCE_WRITE_TRACE_LOG with JUCE_WRITE_TRACE_LOG_VA as intended in original implementation. Co-authored-by: Matt Gonzalez <matt@echoaudio.com>
314 lines
9.1 KiB
C++
314 lines
9.1 KiB
C++
/*
|
|
==============================================================================
|
|
|
|
This file is part of the JUCE framework.
|
|
Copyright (c) Raw Material Software Limited
|
|
|
|
JUCE is an open source framework subject to commercial or open source
|
|
licensing.
|
|
|
|
By downloading, installing, or using the JUCE framework, or combining the
|
|
JUCE framework with any other source code, object code, content or any other
|
|
copyrightable work, you agree to the terms of the JUCE End User Licence
|
|
Agreement, and all incorporated terms including the JUCE Privacy Policy and
|
|
the JUCE Website Terms of Service, as applicable, which will bind you. If you
|
|
do not agree to the terms of these agreements, we will not license the JUCE
|
|
framework to you, and you must discontinue the installation or download
|
|
process and cease use of the JUCE framework.
|
|
|
|
JUCE End User Licence Agreement: https://juce.com/legal/juce-8-licence/
|
|
JUCE Privacy Policy: https://juce.com/juce-privacy-policy
|
|
JUCE Website Terms of Service: https://juce.com/juce-website-terms-of-service/
|
|
|
|
Or:
|
|
|
|
You may also use this code under the terms of the AGPLv3:
|
|
https://www.gnu.org/licenses/agpl-3.0.en.html
|
|
|
|
THE JUCE FRAMEWORK IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL
|
|
WARRANTIES, WHETHER EXPRESSED OR IMPLIED, INCLUDING WARRANTY OF
|
|
MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED.
|
|
|
|
==============================================================================
|
|
*/
|
|
|
|
#pragma once
|
|
|
|
#if JUCE_DIRECT2D_METRICS
|
|
|
|
namespace juce
|
|
{
|
|
|
|
struct Direct2DMetrics : public ReferenceCountedObject
|
|
{
|
|
using Ptr = ReferenceCountedObjectPtr<Direct2DMetrics>;
|
|
|
|
#define DIRECT2D_PAINT_STAT_LIST \
|
|
DIRECT2D_PAINT_STAT (messageThreadPaintDuration) \
|
|
DIRECT2D_PAINT_STAT (swapChainThreadTime) \
|
|
DIRECT2D_PAINT_STAT (frameInterval) \
|
|
DIRECT2D_PAINT_STAT (endDrawDuration) \
|
|
DIRECT2D_PAINT_STAT (present1Duration) \
|
|
DIRECT2D_PAINT_STAT (createGeometryTime) \
|
|
DIRECT2D_PAINT_STAT (drawGeometryTime) \
|
|
DIRECT2D_PAINT_STAT (fillGeometryTime) \
|
|
DIRECT2D_PAINT_STAT (createFilledGRTime) \
|
|
DIRECT2D_PAINT_STAT (createStrokedGRTime) \
|
|
DIRECT2D_PAINT_STAT (drawGRTime) \
|
|
DIRECT2D_PAINT_STAT (createGradientTime) \
|
|
DIRECT2D_PAINT_STAT (pushAliasedAxisAlignedLayerTime) \
|
|
DIRECT2D_PAINT_STAT (pushGeometryLayerTime) \
|
|
DIRECT2D_PAINT_STAT (fillTranslatedRectTime) \
|
|
DIRECT2D_PAINT_STAT (fillAxisAlignedRectTime) \
|
|
DIRECT2D_PAINT_STAT (fillTransformedRectTime) \
|
|
DIRECT2D_PAINT_STAT (fillRectListTime) \
|
|
DIRECT2D_PAINT_STAT (drawImageTime) \
|
|
DIRECT2D_PAINT_STAT (spriteBatchTime) \
|
|
DIRECT2D_PAINT_STAT (spriteBatchSetupTime) \
|
|
DIRECT2D_PAINT_STAT (createSpriteSourceTime) \
|
|
DIRECT2D_PAINT_STAT (setSpritesTime) \
|
|
DIRECT2D_PAINT_STAT (addSpritesTime) \
|
|
DIRECT2D_PAINT_STAT (clearSpritesTime) \
|
|
DIRECT2D_PAINT_STAT (drawSpritesTime) \
|
|
DIRECT2D_PAINT_STAT (drawGlyphRunTime) \
|
|
DIRECT2D_PAINT_STAT (createBitmapTime) \
|
|
DIRECT2D_PAINT_STAT (mapBitmapTime) \
|
|
DIRECT2D_LAST_PAINT_STAT (unmapBitmapTime)
|
|
|
|
#define DIRECT2D_PAINT_STAT(name) name,
|
|
#define DIRECT2D_LAST_PAINT_STAT(name) name
|
|
enum
|
|
{
|
|
DIRECT2D_PAINT_STAT_LIST,
|
|
numStats
|
|
};
|
|
#undef DIRECT2D_PAINT_STAT
|
|
#undef DIRECT2D_LAST_PAINT_STAT
|
|
|
|
#define DIRECT2D_PAINT_STAT(name) #name,
|
|
#define DIRECT2D_LAST_PAINT_STAT(name) #name
|
|
StringArray const accumulatorNames { DIRECT2D_PAINT_STAT_LIST };
|
|
#undef DIRECT2D_PAINT_STAT
|
|
#undef DIRECT2D_LAST_PAINT_STAT
|
|
|
|
CriticalSection& lock;
|
|
String const name;
|
|
void* const windowHandle;
|
|
int64 const creationTime = Time::getMillisecondCounter();
|
|
double const millisecondsPerTick = 1000.0 / (double) Time::getHighResolutionTicksPerSecond();
|
|
int paintCount = 0;
|
|
int presentCount = 0;
|
|
int present1Count = 0;
|
|
int64 lastPaintStartTicks = 0;
|
|
uint64 lockAcquireMaxTicks = 0;
|
|
|
|
Direct2DMetrics (CriticalSection& lockIn, String nameIn, void* windowHandleIn)
|
|
: lock (lockIn),
|
|
name (nameIn),
|
|
windowHandle (windowHandleIn)
|
|
{
|
|
}
|
|
|
|
~Direct2DMetrics() = default;
|
|
|
|
void startFrame()
|
|
{
|
|
ScopedLock locker { lock };
|
|
zerostruct (sums);
|
|
}
|
|
|
|
void finishFrame()
|
|
{
|
|
}
|
|
|
|
void reset()
|
|
{
|
|
ScopedLock locker { lock };
|
|
|
|
for (auto& accumulator : runningAccumulators)
|
|
accumulator.reset();
|
|
|
|
lastPaintStartTicks = 0;
|
|
paintCount = 0;
|
|
present1Count = 0;
|
|
lockAcquireMaxTicks = 0;
|
|
}
|
|
|
|
auto& getAccumulator (size_t index) noexcept
|
|
{
|
|
return runningAccumulators[index];
|
|
}
|
|
|
|
auto getSum (size_t index) const noexcept
|
|
{
|
|
return sums[index];
|
|
}
|
|
|
|
void addValueTicks (size_t index, int64 ticks)
|
|
{
|
|
addValueMsec (index, Time::highResolutionTicksToSeconds (ticks) * 1000.0);
|
|
}
|
|
|
|
void addValueMsec (size_t index, double value)
|
|
{
|
|
ScopedLock locker { lock };
|
|
|
|
auto& accumulator = runningAccumulators[index];
|
|
|
|
switch (index)
|
|
{
|
|
case frameInterval:
|
|
if (accumulator.getCount() > 100)
|
|
{
|
|
accumulator.reset();
|
|
}
|
|
break;
|
|
}
|
|
accumulator.addValue (value);
|
|
|
|
sums[index] += value;
|
|
}
|
|
|
|
private:
|
|
std::array<StatisticsAccumulator<double>, numStats> runningAccumulators;
|
|
std::array<double, numStats> sums;
|
|
};
|
|
|
|
struct Direct2DScopedElapsedTime
|
|
{
|
|
Direct2DScopedElapsedTime (Direct2DMetrics::Ptr metricsIn, size_t accumulatorIndexIn)
|
|
: metrics (metricsIn),
|
|
accumulatorIndex (accumulatorIndexIn)
|
|
{
|
|
}
|
|
|
|
~Direct2DScopedElapsedTime()
|
|
{
|
|
auto finishTicks = Time::getHighResolutionTicks();
|
|
metrics->addValueTicks (accumulatorIndex, finishTicks - startTicks);
|
|
}
|
|
|
|
int64 startTicks = Time::getHighResolutionTicks();
|
|
Direct2DMetrics::Ptr metrics;
|
|
size_t accumulatorIndex;
|
|
};
|
|
|
|
class Direct2DMetricsHub : public DeletedAtShutdown
|
|
{
|
|
public:
|
|
Direct2DMetricsHub()
|
|
{
|
|
imageContextMetrics = new Direct2DMetrics { lock, "Image " + getProcessString(), nullptr };
|
|
add (imageContextMetrics);
|
|
}
|
|
|
|
~Direct2DMetricsHub() override
|
|
{
|
|
clearSingletonInstance();
|
|
}
|
|
|
|
void add (Direct2DMetrics::Ptr metrics)
|
|
{
|
|
metricsArray.insert (0, metrics);
|
|
}
|
|
|
|
void remove (Direct2DMetrics::Ptr metrics)
|
|
{
|
|
metricsArray.removeObject (metrics);
|
|
}
|
|
|
|
Direct2DMetrics::Ptr getMetricsForWindowHandle (void* windowHandle) noexcept
|
|
{
|
|
for (auto& metrics : metricsArray)
|
|
if (metrics->windowHandle == windowHandle)
|
|
return metrics;
|
|
|
|
return nullptr;
|
|
}
|
|
|
|
enum
|
|
{
|
|
getValuesRequest,
|
|
resetValuesRequest
|
|
};
|
|
|
|
struct MetricValues
|
|
{
|
|
size_t count;
|
|
double total;
|
|
double average;
|
|
double minimum;
|
|
double maximum;
|
|
double stdDev;
|
|
};
|
|
|
|
struct GetValuesResponse
|
|
{
|
|
int responseType;
|
|
void* windowHandle;
|
|
MetricValues values[Direct2DMetrics::numStats];
|
|
};
|
|
|
|
CriticalSection lock;
|
|
Direct2DMetrics::Ptr imageContextMetrics;
|
|
|
|
static constexpr int magicNumber = 0xd2d1;
|
|
|
|
JUCE_DECLARE_SINGLETON_INLINE (Direct2DMetricsHub, false)
|
|
|
|
private:
|
|
static String getProcessString() noexcept;
|
|
|
|
void resetAll();
|
|
|
|
struct HubPipeServer : public InterprocessConnection
|
|
{
|
|
explicit HubPipeServer (Direct2DMetricsHub& ownerIn)
|
|
: InterprocessConnection (false, magicNumber),
|
|
owner (ownerIn)
|
|
{
|
|
createPipe ("JUCEDirect2DMetricsHub:" + owner.getProcessString(), -1, true);
|
|
}
|
|
|
|
~HubPipeServer() override
|
|
{
|
|
disconnect();
|
|
}
|
|
|
|
void connectionMade() override
|
|
{
|
|
}
|
|
|
|
void connectionLost() override
|
|
{
|
|
}
|
|
|
|
void messageReceived (const MemoryBlock& message) override;
|
|
|
|
Direct2DMetricsHub& owner;
|
|
};
|
|
|
|
HubPipeServer hubPipeServer { *this };
|
|
ReferenceCountedArray<Direct2DMetrics> metricsArray;
|
|
Direct2DMetrics* lastMetrics = nullptr;
|
|
};
|
|
|
|
} // namespace juce
|
|
|
|
#define JUCE_D2DMETRICS_SCOPED_ELAPSED_TIME(metrics, name) juce::Direct2DScopedElapsedTime scopedElapsedTime_##name { metrics, juce::Direct2DMetrics::name };
|
|
|
|
#else
|
|
|
|
namespace juce
|
|
{
|
|
|
|
struct Direct2DMetrics : public ReferenceCountedObject
|
|
{
|
|
using Ptr = ReferenceCountedObjectPtr<Direct2DMetrics>;
|
|
};
|
|
|
|
} // namespace juce
|
|
|
|
#define JUCE_D2DMETRICS_SCOPED_ELAPSED_TIME(metrics, name)
|
|
|
|
#endif
|