blob: ca173c9cfce242d9cee0e2056ab040f2cd95597d [file]
// Copyright 2015 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "ui/gl/angle_platform_impl.h"
#include "base/compiler_specific.h"
#include "base/functional/bind.h"
#include "base/functional/callback.h"
#include "base/metrics/histogram.h"
#include "base/metrics/histogram_functions.h"
#include "base/task/task_traits.h"
#include "base/task/thread_pool.h"
#include "base/task/thread_pool/thread_pool_instance.h"
#include "base/trace_event/trace_event.h"
#include "third_party/angle/include/platform/PlatformMethods.h"
#include "ui/gl/gl_bindings.h"
namespace angle {
namespace {
double ANGLEPlatformImpl_currentTime(PlatformMethods* platform) {
return base::Time::Now().InSecondsFSinceUnixEpoch();
}
double ANGLEPlatformImpl_monotonicallyIncreasingTime(
PlatformMethods* platform) {
return (base::TimeTicks::Now() - base::TimeTicks()).InSecondsF();
}
void ANGLEPlatformImpl_logError(PlatformMethods* platform,
const char* errorMessage) {
LOG(ERROR) << errorMessage;
}
void ANGLEPlatformImpl_logWarning(PlatformMethods* platform,
const char* warningMessage) {
LOG(WARNING) << warningMessage;
}
void ANGLEPlatformImpl_histogramCustomCounts(PlatformMethods* platform,
const char* name,
int sample,
int min,
int max,
int bucket_count) {
// Copied from histogram macro, but without the static variable caching
// the histogram because name is dynamic.
base::HistogramBase* counter = base::Histogram::FactoryGet(
name, min, max, bucket_count,
base::HistogramBase::kUmaTargetedHistogramFlag);
counter->Add(sample);
}
void ANGLEPlatformImpl_histogramEnumeration(PlatformMethods* platform,
const char* name,
int sample,
int boundary_value) {
// Copied from histogram macro, but without the static variable caching
// the histogram because name is dynamic.
base::HistogramBase* counter = base::LinearHistogram::FactoryGet(
name, 1, boundary_value, boundary_value + 1,
base::HistogramBase::kUmaTargetedHistogramFlag);
counter->Add(sample);
}
void ANGLEPlatformImpl_histogramSparse(PlatformMethods* platform,
const char* name,
int sample) {
base::UmaHistogramSparse(name, sample);
}
void ANGLEPlatformImpl_histogramBoolean(PlatformMethods* platform,
const char* name,
bool sample) {
ANGLEPlatformImpl_histogramEnumeration(platform, name, sample ? 1 : 0, 2);
}
NO_SANITIZE("cfi-icall")
void AnglePlatformImpl_runWorkerTask(PostWorkerTaskCallback callback, void* user_data) {
TRACE_EVENT0("toplevel", "ANGLEPlatformImpl::RunWorkerTask");
callback(user_data);
}
void ANGLEPlatformImpl_recordShaderCacheUse(bool in_cache) {
// Metrics were no longer required, we can remove once Angle no longer
// requires the method.
}
} // anonymous namespace
void ANGLEPlatformImpl_postWorkerTask(PlatformMethods* platform,
PostWorkerTaskCallback callback,
void* user_data) {
// Use BLOCK_SHUTDOWN so that worker tasks (e.g. shader compilation) are
// guaranteed to finish before ThreadPool shutdown completes, avoiding hangs
// in ANGLE (https://crbug.com/539435331) while ensuring tasks always run on
// worker threads rather than caller threads to prevent driver crashes
// (https://crbug.com/551704724).
base::ThreadPool::PostTask(
FROM_HERE,
{base::TaskPriority::USER_BLOCKING,
base::TaskShutdownBehavior::BLOCK_SHUTDOWN},
base::BindOnce(&AnglePlatformImpl_runWorkerTask, callback, user_data));
}
NO_SANITIZE("cfi-icall")
bool InitializePlatform(EGLDisplay display,
GLGetProcAddressProc get_proc_address) {
GetDisplayPlatformFunc angle_get_platform =
reinterpret_cast<GetDisplayPlatformFunc>(
get_proc_address("ANGLEGetDisplayPlatform"));
if (!angle_get_platform)
return false;
PlatformMethods* platformMethods = nullptr;
if (!angle_get_platform(static_cast<EGLDisplayType>(display),
g_PlatformMethodNames, g_NumPlatformMethods, nullptr,
&platformMethods))
return false;
platformMethods->currentTime = ANGLEPlatformImpl_currentTime;
platformMethods->histogramBoolean = ANGLEPlatformImpl_histogramBoolean;
platformMethods->histogramCustomCounts =
ANGLEPlatformImpl_histogramCustomCounts;
platformMethods->histogramEnumeration =
ANGLEPlatformImpl_histogramEnumeration;
platformMethods->histogramSparse = ANGLEPlatformImpl_histogramSparse;
platformMethods->logError = ANGLEPlatformImpl_logError;
platformMethods->logWarning = ANGLEPlatformImpl_logWarning;
platformMethods->monotonicallyIncreasingTime =
ANGLEPlatformImpl_monotonicallyIncreasingTime;
platformMethods->recordShaderCacheUse =
ANGLEPlatformImpl_recordShaderCacheUse;
// Initialize the delegate to allow posting tasks in the Chromium thread pool.
// The thread pool is not available in some unittests.
if (base::ThreadPoolInstance::Get())
platformMethods->postWorkerTask = ANGLEPlatformImpl_postWorkerTask;
return true;
}
NO_SANITIZE("cfi-icall")
void ResetPlatform(EGLDisplay display, GLGetProcAddressProc get_proc_address) {
ResetDisplayPlatformFunc angle_reset_platform =
reinterpret_cast<ResetDisplayPlatformFunc>(
get_proc_address("ANGLEResetDisplayPlatform"));
if (!angle_reset_platform) {
return;
}
angle_reset_platform(static_cast<EGLDisplayType>(display));
}
} // namespace angle