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 ...@@ -11,10 +11,11 @@ namespace angle
const unsigned char *GetTraceCategoryEnabledFlag(const char *name) const unsigned char *GetTraceCategoryEnabledFlag(const char *name)
{ {
angle::Platform *platform = ANGLEPlatformCurrent(); auto *platform = ANGLEPlatformCurrent();
ASSERT(platform); ASSERT(platform);
const unsigned char *categoryEnabledFlag = platform->getTraceCategoryEnabledFlag(name); const unsigned char *categoryEnabledFlag =
platform->getTraceCategoryEnabledFlag(platform, name);
if (categoryEnabledFlag != nullptr) if (categoryEnabledFlag != nullptr)
{ {
return categoryEnabledFlag; return categoryEnabledFlag;
...@@ -24,28 +25,26 @@ const unsigned char *GetTraceCategoryEnabledFlag(const char *name) ...@@ -24,28 +25,26 @@ const unsigned char *GetTraceCategoryEnabledFlag(const char *name)
return &disabled; return &disabled;
} }
Platform::TraceEventHandle AddTraceEvent(char phase, const unsigned char* categoryGroupEnabled, const char* name, unsigned long long id, angle::TraceEventHandle AddTraceEvent(char phase,
int numArgs, const char** argNames, const unsigned char* argTypes, const unsigned char *categoryGroupEnabled,
const unsigned long long* argValues, unsigned char flags) 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); ASSERT(platform);
double timestamp = platform->monotonicallyIncreasingTime(); double timestamp = platform->monotonicallyIncreasingTime(platform);
if (timestamp != 0) if (timestamp != 0)
{ {
angle::Platform::TraceEventHandle handle = angle::TraceEventHandle handle =
platform->addTraceEvent(phase, platform->addTraceEvent(platform, phase, categoryGroupEnabled, name, id, timestamp,
categoryGroupEnabled, numArgs, argNames, argTypes, argValues, flags);
name,
id,
timestamp,
numArgs,
argNames,
argTypes,
argValues,
flags);
ASSERT(handle != 0); ASSERT(handle != 0);
return handle; return handle;
} }
......
...@@ -12,11 +12,15 @@ namespace angle ...@@ -12,11 +12,15 @@ namespace angle
{ {
const unsigned char *GetTraceCategoryEnabledFlag(const char* name); const unsigned char *GetTraceCategoryEnabledFlag(const char* name);
Platform::TraceEventHandle AddTraceEvent(char phase, const unsigned char* categoryGroupEnabled, const char* name, angle::TraceEventHandle AddTraceEvent(char phase,
unsigned long long id, int numArgs, const char** argNames, const unsigned char *categoryGroupEnabled,
const unsigned char* argTypes, const unsigned long long* argValues, const char *name,
unsigned char flags); 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_ #endif // COMMON_EVENT_TRACER_H_
...@@ -15,16 +15,16 @@ namespace angle ...@@ -15,16 +15,16 @@ namespace angle
void LoggingAnnotator::logMessage(const gl::LogMessage &msg) const void LoggingAnnotator::logMessage(const gl::LogMessage &msg) const
{ {
angle::Platform *plat = ANGLEPlatformCurrent(); auto *plat = ANGLEPlatformCurrent();
if (plat != nullptr) if (plat != nullptr)
{ {
switch (msg.getSeverity()) switch (msg.getSeverity())
{ {
case gl::LOG_ERR: case gl::LOG_ERR:
plat->logError(msg.getMessage().c_str()); plat->logError(plat, msg.getMessage().c_str());
break; break;
case gl::LOG_WARN: case gl::LOG_WARN:
plat->logWarning(msg.getMessage().c_str()); plat->logWarning(plat, msg.getMessage().c_str());
break; break;
default: default:
UNREACHABLE(); UNREACHABLE();
......
...@@ -8,28 +8,176 @@ ...@@ -8,28 +8,176 @@
#include <platform/Platform.h> #include <platform/Platform.h>
#include <cstring>
#include "common/debug.h" #include "common/debug.h"
namespace namespace
{ {
angle::Platform *currentPlatform = nullptr; 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 void Class_histogramCustomCounts(angle::PlatformMethods *platform,
angle::Platform *ANGLE_APIENTRY ANGLEPlatformCurrent() 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) void ANGLE_APIENTRY ANGLEPlatformInitialize(angle::Platform *platformImpl)
{ {
ASSERT(platformImpl != nullptr); ASSERT(platformImpl != nullptr);
currentPlatform = platformImpl; 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() void ANGLE_APIENTRY ANGLEPlatformShutdown()
{ {
currentPlatform = nullptr; 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 @@ ...@@ -41,18 +41,19 @@
#define ANGLE_HISTOGRAM_COUNTS_10000(name, sample) \ #define ANGLE_HISTOGRAM_COUNTS_10000(name, sample) \
ANGLE_HISTOGRAM_CUSTOM_COUNTS(name, sample, 1, 10000, 50) ANGLE_HISTOGRAM_CUSTOM_COUNTS(name, sample, 1, 10000, 50)
#define ANGLE_HISTOGRAM_CUSTOM_COUNTS(name, sample, min, max, bucket_count) \ #define ANGLE_HISTOGRAM_CUSTOM_COUNTS(name, sample, min, max, bucket_count) \
ANGLEPlatformCurrent()->histogramCustomCounts(\ ANGLEPlatformCurrent()->histogramCustomCounts(ANGLEPlatformCurrent(), name, sample, min, max, \
name, sample, min, max, bucket_count) bucket_count)
#define ANGLE_HISTOGRAM_PERCENTAGE(name, under_one_hundred) \ #define ANGLE_HISTOGRAM_PERCENTAGE(name, under_one_hundred) \
ANGLE_HISTOGRAM_ENUMERATION(name, under_one_hundred, 101) ANGLE_HISTOGRAM_ENUMERATION(name, under_one_hundred, 101)
#define ANGLE_HISTOGRAM_BOOLEAN(name, sample) \ #define ANGLE_HISTOGRAM_BOOLEAN(name, sample) \
ANGLEPlatformCurrent()->histogramBoolean(name, sample) ANGLEPlatformCurrent()->histogramBoolean(ANGLEPlatformCurrent(), name, sample)
#define ANGLE_HISTOGRAM_ENUMERATION(name, sample, boundary_value) \ #define ANGLE_HISTOGRAM_ENUMERATION(name, sample, boundary_value) \
ANGLEPlatformCurrent()->histogramEnumeration(name, sample, boundary_value) ANGLEPlatformCurrent()->histogramEnumeration(ANGLEPlatformCurrent(), name, sample, \
boundary_value)
#define ANGLE_HISTOGRAM_MEMORY_KB(name, sample) ANGLE_HISTOGRAM_CUSTOM_COUNTS( \ #define ANGLE_HISTOGRAM_MEMORY_KB(name, sample) ANGLE_HISTOGRAM_CUSTOM_COUNTS( \
name, sample, 1000, 500000, 50) name, sample, 1000, 500000, 50)
...@@ -61,7 +62,7 @@ ...@@ -61,7 +62,7 @@
name, sample, 1, 1000, 50) name, sample, 1, 1000, 50)
#define ANGLE_HISTOGRAM_SPARSE_SLOWLY(name, sample) \ #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 // 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 // recommended for when you want a histogram which measures the time it takes
...@@ -79,29 +80,33 @@ ...@@ -79,29 +80,33 @@
#define SCOPED_ANGLE_HISTOGRAM_TIMER_EXPANDER(name, is_long, key) \ #define SCOPED_ANGLE_HISTOGRAM_TIMER_EXPANDER(name, is_long, key) \
SCOPED_ANGLE_HISTOGRAM_TIMER_UNIQUE(name, is_long, key) SCOPED_ANGLE_HISTOGRAM_TIMER_UNIQUE(name, is_long, key)
#define SCOPED_ANGLE_HISTOGRAM_TIMER_UNIQUE(name, is_long, key) \ #define SCOPED_ANGLE_HISTOGRAM_TIMER_UNIQUE(name, is_long, key) \
class ScopedHistogramTimer##key \ class ScopedHistogramTimer##key \
{ \ { \
public: \ public: \
ScopedHistogramTimer##key() : constructed_(ANGLEPlatformCurrent()->currentTime()) {} \ ScopedHistogramTimer##key() \
~ScopedHistogramTimer##key() \ : constructed_(ANGLEPlatformCurrent()->currentTime(ANGLEPlatformCurrent())) \
{ \ { \
if (constructed_ == 0) \ } \
return; \ ~ScopedHistogramTimer##key() \
double elapsed = ANGLEPlatformCurrent()->currentTime() - constructed_; \ { \
int elapsedMS = static_cast<int>(elapsed * 1000.0); \ if (constructed_ == 0) \
if (is_long) \ return; \
{ \ auto *platform = ANGLEPlatformCurrent(); \
ANGLE_HISTOGRAM_LONG_TIMES_100(name, elapsedMS); \ double elapsed = platform->currentTime(platform) - constructed_; \
} \ int elapsedMS = static_cast<int>(elapsed * 1000.0); \
else \ if (is_long) \
{ \ { \
ANGLE_HISTOGRAM_TIMES(name, elapsedMS); \ ANGLE_HISTOGRAM_LONG_TIMES_100(name, elapsedMS); \
} \ } \
} \ else \
\ { \
private: \ ANGLE_HISTOGRAM_TIMES(name, elapsedMS); \
double constructed_; \ } \
} \
\
private: \
double constructed_; \
} scoped_histogram_timer_##key } scoped_histogram_timer_##key
#endif // BASE_METRICS_HISTOGRAM_MACROS_H_ #endif // BASE_METRICS_HISTOGRAM_MACROS_H_
...@@ -387,7 +387,8 @@ Renderer11::Renderer11(egl::Display *display) ...@@ -387,7 +387,8 @@ Renderer11::Renderer11(egl::Display *display)
: RendererD3D(display), : RendererD3D(display),
mStateCache(this), mStateCache(this),
mStateManager(this), mStateManager(this),
mLastHistogramUpdateTime(ANGLEPlatformCurrent()->monotonicallyIncreasingTime()), mLastHistogramUpdateTime(
ANGLEPlatformCurrent()->monotonicallyIncreasingTime(ANGLEPlatformCurrent())),
mDebug(nullptr), mDebug(nullptr),
mScratchMemoryBufferResetCounter(0), mScratchMemoryBufferResetCounter(0),
mAnnotator(nullptr) mAnnotator(nullptr)
...@@ -4294,7 +4295,8 @@ void Renderer11::onSwap() ...@@ -4294,7 +4295,8 @@ void Renderer11::onSwap()
// Send histogram updates every half hour // Send histogram updates every half hour
const double kHistogramUpdateInterval = 30 * 60; const double kHistogramUpdateInterval = 30 * 60;
const double currentTime = ANGLEPlatformCurrent()->monotonicallyIncreasingTime(); auto *platform = ANGLEPlatformCurrent();
const double currentTime = platform->monotonicallyIncreasingTime(platform);
const double timeSinceLastUpdate = currentTime - mLastHistogramUpdateTime; const double timeSinceLastUpdate = currentTime - mLastHistogramUpdateTime;
if (timeSinceLastUpdate > kHistogramUpdateInterval) if (timeSinceLastUpdate > kHistogramUpdateInterval)
......
...@@ -1988,7 +1988,8 @@ angle::WorkaroundsD3D GenerateWorkarounds(const Renderer11DeviceCaps &deviceCaps ...@@ -1988,7 +1988,8 @@ angle::WorkaroundsD3D GenerateWorkarounds(const Renderer11DeviceCaps &deviceCaps
} }
// Call platform hooks for testing overrides. // Call platform hooks for testing overrides.
ANGLEPlatformCurrent()->overrideWorkaroundsD3D(&workarounds); auto *platform = ANGLEPlatformCurrent();
platform->overrideWorkaroundsD3D(platform, &workarounds);
return workarounds; return workarounds;
} }
......
...@@ -654,7 +654,8 @@ angle::WorkaroundsD3D GenerateWorkarounds() ...@@ -654,7 +654,8 @@ angle::WorkaroundsD3D GenerateWorkarounds()
workarounds.expandIntegerPowExpressions = true; workarounds.expandIntegerPowExpressions = true;
// Call platform hooks for testing overrides. // Call platform hooks for testing overrides.
ANGLEPlatformCurrent()->overrideWorkaroundsD3D(&workarounds); auto *platform = ANGLEPlatformCurrent();
platform->overrideWorkaroundsD3D(platform, &workarounds);
return workarounds; return workarounds;
} }
......
...@@ -1773,6 +1773,8 @@ __eglMustCastToProperFunctionPointerType EGLAPIENTRY GetProcAddress(const char * ...@@ -1773,6 +1773,8 @@ __eglMustCastToProperFunctionPointerType EGLAPIENTRY GetProcAddress(const char *
// angle::Platform related entry points // angle::Platform related entry points
INSERT_PROC_ADDRESS_NO_NS("ANGLEPlatformInitialize", ANGLEPlatformInitialize); INSERT_PROC_ADDRESS_NO_NS("ANGLEPlatformInitialize", ANGLEPlatformInitialize);
INSERT_PROC_ADDRESS_NO_NS("ANGLEPlatformShutdown", ANGLEPlatformShutdown); 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
#undef INSERT_PROC_ADDRESS_NO_NS #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