Commit b1eeba1f by Jamie Madill Committed by Commit Bot

Use a C API for the ANGLE platform.

The main purpose of this change is to fix a fuzzer bug where we would trigger undefined behaviour calling between Chrome and ANGLE. It's not specced how virtual function calls work if the shared objects are not directly linked together, and ANGLE and Chrome are not linked. Replace the old class-style API with a C dispatch table. Follow-up work will make the Platform owned by the Display instead of using global variables, but fixing this is a bit tricky. BUG=angleproject:1892 BUG=chromium:678870 Change-Id: Iad188bc2e50f2b5e4a03ce0de233d686f569c705 Reviewed-on: https://chromium-review.googlesource.com/441273 Commit-Queue: Jamie Madill <jmadill@chromium.org> Reviewed-by: 's avatarCorentin Wallez <cwallez@chromium.org>
parent c47e3407
......@@ -11,10 +11,11 @@ namespace angle
const unsigned char *GetTraceCategoryEnabledFlag(const char *name)
{
angle::Platform *platform = ANGLEPlatformCurrent();
auto *platform = ANGLEPlatformCurrent();
ASSERT(platform);
const unsigned char *categoryEnabledFlag = platform->getTraceCategoryEnabledFlag(name);
const unsigned char *categoryEnabledFlag =
platform->getTraceCategoryEnabledFlag(platform, name);
if (categoryEnabledFlag != nullptr)
{
return categoryEnabledFlag;
......@@ -24,28 +25,26 @@ const unsigned char *GetTraceCategoryEnabledFlag(const char *name)
return &disabled;
}
Platform::TraceEventHandle AddTraceEvent(char phase, const unsigned char* categoryGroupEnabled, const char* name, unsigned long long id,
int numArgs, const char** argNames, const unsigned char* argTypes,
const unsigned long long* argValues, unsigned char flags)
angle::TraceEventHandle AddTraceEvent(char phase,
const unsigned char *categoryGroupEnabled,
const char *name,
unsigned long long id,
int numArgs,
const char **argNames,
const unsigned char *argTypes,
const unsigned long long *argValues,
unsigned char flags)
{
angle::Platform *platform = ANGLEPlatformCurrent();
auto *platform = ANGLEPlatformCurrent();
ASSERT(platform);
double timestamp = platform->monotonicallyIncreasingTime();
double timestamp = platform->monotonicallyIncreasingTime(platform);
if (timestamp != 0)
{
angle::Platform::TraceEventHandle handle =
platform->addTraceEvent(phase,
categoryGroupEnabled,
name,
id,
timestamp,
numArgs,
argNames,
argTypes,
argValues,
flags);
angle::TraceEventHandle handle =
platform->addTraceEvent(platform, phase, categoryGroupEnabled, name, id, timestamp,
numArgs, argNames, argTypes, argValues, flags);
ASSERT(handle != 0);
return handle;
}
......
......@@ -12,11 +12,15 @@ namespace angle
{
const unsigned char *GetTraceCategoryEnabledFlag(const char* name);
Platform::TraceEventHandle AddTraceEvent(char phase, const unsigned char* categoryGroupEnabled, const char* name,
unsigned long long id, int numArgs, const char** argNames,
const unsigned char* argTypes, const unsigned long long* argValues,
unsigned char flags);
angle::TraceEventHandle AddTraceEvent(char phase,
const unsigned char *categoryGroupEnabled,
const char *name,
unsigned long long id,
int numArgs,
const char **argNames,
const unsigned char *argTypes,
const unsigned long long *argValues,
unsigned char flags);
}
#endif // COMMON_EVENT_TRACER_H_
......@@ -15,16 +15,16 @@ namespace angle
void LoggingAnnotator::logMessage(const gl::LogMessage &msg) const
{
angle::Platform *plat = ANGLEPlatformCurrent();
auto *plat = ANGLEPlatformCurrent();
if (plat != nullptr)
{
switch (msg.getSeverity())
{
case gl::LOG_ERR:
plat->logError(msg.getMessage().c_str());
plat->logError(plat, msg.getMessage().c_str());
break;
case gl::LOG_WARN:
plat->logWarning(msg.getMessage().c_str());
plat->logWarning(plat, msg.getMessage().c_str());
break;
default:
UNREACHABLE();
......
......@@ -8,28 +8,176 @@
#include <platform/Platform.h>
#include <cstring>
#include "common/debug.h"
namespace
{
angle::Platform *currentPlatform = nullptr;
// TODO(jmadill): Make methods owned by egl::Display.
angle::PlatformMethods g_platformMethods;
// TODO(jmadill): Remove all the Class_ methods once we switch Chromium to the new impl.
double Class_currentTime(angle::PlatformMethods *platform)
{
return currentPlatform->currentTime();
}
double Class_monotonicallyIncreasingTime(angle::PlatformMethods *platform)
{
return currentPlatform->monotonicallyIncreasingTime();
}
void Class_logError(angle::PlatformMethods *platform, const char *errorMessage)
{
currentPlatform->logError(errorMessage);
}
void Class_logWarning(angle::PlatformMethods *platform, const char *warningMessage)
{
currentPlatform->logWarning(warningMessage);
}
void Class_logInfo(angle::PlatformMethods *platform, const char *infoMessage)
{
currentPlatform->logInfo(infoMessage);
}
const unsigned char *Class_getTraceCategoryEnabledFlag(angle::PlatformMethods *platform,
const char *categoryName)
{
return currentPlatform->getTraceCategoryEnabledFlag(categoryName);
}
angle::TraceEventHandle Class_addTraceEvent(angle::PlatformMethods *platform,
char phase,
const unsigned char *categoryEnabledFlag,
const char *name,
unsigned long long id,
double timestamp,
int numArgs,
const char **argNames,
const unsigned char *argTypes,
const unsigned long long *argValues,
unsigned char flags)
{
return currentPlatform->addTraceEvent(phase, categoryEnabledFlag, name, id, timestamp, numArgs,
argNames, argTypes, argValues, flags);
}
void Class_updateTraceEventDuration(angle::PlatformMethods *platform,
const unsigned char *categoryEnabledFlag,
const char *name,
angle::TraceEventHandle eventHandle)
{
currentPlatform->updateTraceEventDuration(categoryEnabledFlag, name, eventHandle);
}
// static
angle::Platform *ANGLE_APIENTRY ANGLEPlatformCurrent()
void Class_histogramCustomCounts(angle::PlatformMethods *platform,
const char *name,
int sample,
int min,
int max,
int bucketCount)
{
return currentPlatform;
currentPlatform->histogramCustomCounts(name, sample, min, max, bucketCount);
}
void Class_histogramEnumeration(angle::PlatformMethods *platform,
const char *name,
int sample,
int boundaryValue)
{
currentPlatform->histogramEnumeration(name, sample, boundaryValue);
}
void Class_histogramSparse(angle::PlatformMethods *platform, const char *name, int sample)
{
currentPlatform->histogramSparse(name, sample);
}
void Class_histogramBoolean(angle::PlatformMethods *platform, const char *name, bool sample)
{
currentPlatform->histogramBoolean(name, sample);
}
void Class_overrideWorkaroundsD3D(angle::PlatformMethods *platform,
angle::WorkaroundsD3D *workaroundsD3D)
{
currentPlatform->overrideWorkaroundsD3D(workaroundsD3D);
}
} // anonymous namespace
angle::PlatformMethods *ANGLEPlatformCurrent()
{
return &g_platformMethods;
}
// static
void ANGLE_APIENTRY ANGLEPlatformInitialize(angle::Platform *platformImpl)
{
ASSERT(platformImpl != nullptr);
currentPlatform = platformImpl;
// TODO(jmadill): Migrate to platform methods.
g_platformMethods.addTraceEvent = Class_addTraceEvent;
g_platformMethods.currentTime = Class_currentTime;
g_platformMethods.getTraceCategoryEnabledFlag = Class_getTraceCategoryEnabledFlag;
g_platformMethods.histogramBoolean = Class_histogramBoolean;
g_platformMethods.histogramCustomCounts = Class_histogramCustomCounts;
g_platformMethods.histogramEnumeration = Class_histogramEnumeration;
g_platformMethods.histogramSparse = Class_histogramSparse;
g_platformMethods.logError = Class_logError;
g_platformMethods.logInfo = Class_logInfo;
g_platformMethods.logWarning = Class_logWarning;
g_platformMethods.monotonicallyIncreasingTime = Class_monotonicallyIncreasingTime;
g_platformMethods.overrideWorkaroundsD3D = Class_overrideWorkaroundsD3D;
g_platformMethods.updateTraceEventDuration = Class_updateTraceEventDuration;
}
// static
void ANGLE_APIENTRY ANGLEPlatformShutdown()
{
currentPlatform = nullptr;
g_platformMethods = angle::PlatformMethods();
}
bool ANGLE_APIENTRY ANGLEGetDisplayPlatform(angle::EGLDisplayType display,
const char *const methodNames[],
unsigned int methodNameCount,
uintptr_t context,
angle::PlatformMethods **platformMethodsOut)
{
// We allow for a lower input count of impl platform methods if the subset is correct.
if (methodNameCount > angle::g_NumPlatformMethods)
{
ERR() << "Invalid platform method count: " << methodNameCount << ", expected "
<< angle::g_NumPlatformMethods << ".";
return false;
}
for (unsigned int nameIndex = 0; nameIndex < methodNameCount; ++nameIndex)
{
const char *expectedName = angle::g_PlatformMethodNames[nameIndex];
const char *actualName = methodNames[nameIndex];
if (strcmp(expectedName, actualName) != 0)
{
ERR() << "Invalid platform method name: " << actualName << ", expected " << expectedName
<< ".";
return false;
}
}
// TODO(jmadill): Store platform methods in display.
g_platformMethods.context = context;
*platformMethodsOut = &g_platformMethods;
return true;
}
void ANGLE_APIENTRY ANGLEResetDisplayPlatform(angle::EGLDisplayType display)
{
// TODO(jmadill): Store platform methods in display.
g_platformMethods = angle::PlatformMethods();
g_platformMethods.context = 0;
}
......@@ -41,18 +41,19 @@
#define ANGLE_HISTOGRAM_COUNTS_10000(name, sample) \
ANGLE_HISTOGRAM_CUSTOM_COUNTS(name, sample, 1, 10000, 50)
#define ANGLE_HISTOGRAM_CUSTOM_COUNTS(name, sample, min, max, bucket_count) \
ANGLEPlatformCurrent()->histogramCustomCounts(\
name, sample, min, max, bucket_count)
#define ANGLE_HISTOGRAM_CUSTOM_COUNTS(name, sample, min, max, bucket_count) \
ANGLEPlatformCurrent()->histogramCustomCounts(ANGLEPlatformCurrent(), name, sample, min, max, \
bucket_count)
#define ANGLE_HISTOGRAM_PERCENTAGE(name, under_one_hundred) \
ANGLE_HISTOGRAM_ENUMERATION(name, under_one_hundred, 101)
#define ANGLE_HISTOGRAM_BOOLEAN(name, sample) \
ANGLEPlatformCurrent()->histogramBoolean(name, sample)
ANGLEPlatformCurrent()->histogramBoolean(ANGLEPlatformCurrent(), name, sample)
#define ANGLE_HISTOGRAM_ENUMERATION(name, sample, boundary_value) \
ANGLEPlatformCurrent()->histogramEnumeration(name, sample, boundary_value)
#define ANGLE_HISTOGRAM_ENUMERATION(name, sample, boundary_value) \
ANGLEPlatformCurrent()->histogramEnumeration(ANGLEPlatformCurrent(), name, sample, \
boundary_value)
#define ANGLE_HISTOGRAM_MEMORY_KB(name, sample) ANGLE_HISTOGRAM_CUSTOM_COUNTS( \
name, sample, 1000, 500000, 50)
......@@ -61,7 +62,7 @@
name, sample, 1, 1000, 50)
#define ANGLE_HISTOGRAM_SPARSE_SLOWLY(name, sample) \
ANGLEPlatformCurrent()->histogramSparse(name, sample)
ANGLEPlatformCurrent()->histogramSparse(ANGLEPlatformCurrent(), name, sample)
// Scoped class which logs its time on this earth as a UMA statistic. This is
// recommended for when you want a histogram which measures the time it takes
......@@ -79,29 +80,33 @@
#define SCOPED_ANGLE_HISTOGRAM_TIMER_EXPANDER(name, is_long, key) \
SCOPED_ANGLE_HISTOGRAM_TIMER_UNIQUE(name, is_long, key)
#define SCOPED_ANGLE_HISTOGRAM_TIMER_UNIQUE(name, is_long, key) \
class ScopedHistogramTimer##key \
{ \
public: \
ScopedHistogramTimer##key() : constructed_(ANGLEPlatformCurrent()->currentTime()) {} \
~ScopedHistogramTimer##key() \
{ \
if (constructed_ == 0) \
return; \
double elapsed = ANGLEPlatformCurrent()->currentTime() - constructed_; \
int elapsedMS = static_cast<int>(elapsed * 1000.0); \
if (is_long) \
{ \
ANGLE_HISTOGRAM_LONG_TIMES_100(name, elapsedMS); \
} \
else \
{ \
ANGLE_HISTOGRAM_TIMES(name, elapsedMS); \
} \
} \
\
private: \
double constructed_; \
#define SCOPED_ANGLE_HISTOGRAM_TIMER_UNIQUE(name, is_long, key) \
class ScopedHistogramTimer##key \
{ \
public: \
ScopedHistogramTimer##key() \
: constructed_(ANGLEPlatformCurrent()->currentTime(ANGLEPlatformCurrent())) \
{ \
} \
~ScopedHistogramTimer##key() \
{ \
if (constructed_ == 0) \
return; \
auto *platform = ANGLEPlatformCurrent(); \
double elapsed = platform->currentTime(platform) - constructed_; \
int elapsedMS = static_cast<int>(elapsed * 1000.0); \
if (is_long) \
{ \
ANGLE_HISTOGRAM_LONG_TIMES_100(name, elapsedMS); \
} \
else \
{ \
ANGLE_HISTOGRAM_TIMES(name, elapsedMS); \
} \
} \
\
private: \
double constructed_; \
} scoped_histogram_timer_##key
#endif // BASE_METRICS_HISTOGRAM_MACROS_H_
......@@ -387,7 +387,8 @@ Renderer11::Renderer11(egl::Display *display)
: RendererD3D(display),
mStateCache(this),
mStateManager(this),
mLastHistogramUpdateTime(ANGLEPlatformCurrent()->monotonicallyIncreasingTime()),
mLastHistogramUpdateTime(
ANGLEPlatformCurrent()->monotonicallyIncreasingTime(ANGLEPlatformCurrent())),
mDebug(nullptr),
mScratchMemoryBufferResetCounter(0),
mAnnotator(nullptr)
......@@ -4294,7 +4295,8 @@ void Renderer11::onSwap()
// Send histogram updates every half hour
const double kHistogramUpdateInterval = 30 * 60;
const double currentTime = ANGLEPlatformCurrent()->monotonicallyIncreasingTime();
auto *platform = ANGLEPlatformCurrent();
const double currentTime = platform->monotonicallyIncreasingTime(platform);
const double timeSinceLastUpdate = currentTime - mLastHistogramUpdateTime;
if (timeSinceLastUpdate > kHistogramUpdateInterval)
......
......@@ -1988,7 +1988,8 @@ angle::WorkaroundsD3D GenerateWorkarounds(const Renderer11DeviceCaps &deviceCaps
}
// Call platform hooks for testing overrides.
ANGLEPlatformCurrent()->overrideWorkaroundsD3D(&workarounds);
auto *platform = ANGLEPlatformCurrent();
platform->overrideWorkaroundsD3D(platform, &workarounds);
return workarounds;
}
......
......@@ -654,7 +654,8 @@ angle::WorkaroundsD3D GenerateWorkarounds()
workarounds.expandIntegerPowExpressions = true;
// Call platform hooks for testing overrides.
ANGLEPlatformCurrent()->overrideWorkaroundsD3D(&workarounds);
auto *platform = ANGLEPlatformCurrent();
platform->overrideWorkaroundsD3D(platform, &workarounds);
return workarounds;
}
......
......@@ -1773,6 +1773,8 @@ __eglMustCastToProperFunctionPointerType EGLAPIENTRY GetProcAddress(const char *
// angle::Platform related entry points
INSERT_PROC_ADDRESS_NO_NS("ANGLEPlatformInitialize", ANGLEPlatformInitialize);
INSERT_PROC_ADDRESS_NO_NS("ANGLEPlatformShutdown", ANGLEPlatformShutdown);
INSERT_PROC_ADDRESS_NO_NS("ANGLEGetDisplayPlatform", ANGLEGetDisplayPlatform);
INSERT_PROC_ADDRESS_NO_NS("ANGLEResetDisplayPlatform", ANGLEResetDisplayPlatform);
#undef INSERT_PROC_ADDRESS
#undef INSERT_PROC_ADDRESS_NO_NS
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment