mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-24 21:31:04 +00:00
Bug 1349799 - Implement WebGLPowerPreference and gl::CreateContextFlags::HIGH_POWER. - r=kvark
Based on patches by :daoshengmu. MozReview-Commit-ID: FSbJV8DLyJ4
This commit is contained in:
parent
45170d1834
commit
3cdbe9fdb9
@ -94,19 +94,27 @@ using namespace mozilla::gl;
|
||||
using namespace mozilla::layers;
|
||||
|
||||
WebGLContextOptions::WebGLContextOptions()
|
||||
: alpha(true)
|
||||
, depth(true)
|
||||
, stencil(false)
|
||||
, premultipliedAlpha(true)
|
||||
, antialias(true)
|
||||
, preserveDrawingBuffer(false)
|
||||
, failIfMajorPerformanceCaveat(false)
|
||||
{
|
||||
// Set default alpha state based on preference.
|
||||
if (gfxPrefs::WebGLDefaultNoAlpha())
|
||||
alpha = false;
|
||||
}
|
||||
|
||||
bool
|
||||
WebGLContextOptions::operator==(const WebGLContextOptions& r) const
|
||||
{
|
||||
bool eq = true;
|
||||
eq &= (alpha == r.alpha);
|
||||
eq &= (depth == r.depth);
|
||||
eq &= (stencil == r.stencil);
|
||||
eq &= (premultipliedAlpha == r.premultipliedAlpha);
|
||||
eq &= (antialias == r.antialias);
|
||||
eq &= (preserveDrawingBuffer == r.preserveDrawingBuffer);
|
||||
eq &= (failIfMajorPerformanceCaveat == r.failIfMajorPerformanceCaveat);
|
||||
eq &= (powerPreference == r.powerPreference);
|
||||
return eq;
|
||||
}
|
||||
|
||||
WebGLContext::WebGLContext()
|
||||
: WebGLContextUnchecked(nullptr)
|
||||
, mMaxPerfWarnings(gfxPrefs::WebGLMaxPerfWarnings())
|
||||
@ -368,6 +376,7 @@ WebGLContext::SetContextOptions(JSContext* cx, JS::Handle<JS::Value> options,
|
||||
newOpts.antialias = attributes.mAntialias;
|
||||
newOpts.preserveDrawingBuffer = attributes.mPreserveDrawingBuffer;
|
||||
newOpts.failIfMajorPerformanceCaveat = attributes.mFailIfMajorPerformanceCaveat;
|
||||
newOpts.powerPreference = attributes.mPowerPreference;
|
||||
|
||||
if (attributes.mAlpha.WasPassed())
|
||||
newOpts.alpha = attributes.mAlpha.Value();
|
||||
@ -386,7 +395,7 @@ WebGLContext::SetContextOptions(JSContext* cx, JS::Handle<JS::Value> options,
|
||||
newOpts.preserveDrawingBuffer ? 1 : 0);
|
||||
#endif
|
||||
|
||||
if (mOptionsFrozen && newOpts != mOptions) {
|
||||
if (mOptionsFrozen && !(newOpts == mOptions)) {
|
||||
// Error if the options are already frozen, and the ones that were asked for
|
||||
// aren't the same as what they were originally.
|
||||
return NS_ERROR_FAILURE;
|
||||
@ -667,6 +676,22 @@ WebGLContext::CreateAndInitGL(bool forceEnabled,
|
||||
flags |= gl::CreateContextFlags::REQUIRE_COMPAT_PROFILE;
|
||||
}
|
||||
|
||||
switch (mOptions.powerPreference) {
|
||||
case dom::WebGLPowerPreference::Low_power:
|
||||
break;
|
||||
|
||||
// Eventually add a heuristic, but for now default to high-performance.
|
||||
// We can even make it dynamic by holding on to a ForceDiscreteGPUHelperCGL iff
|
||||
// we decide it's a high-performance application:
|
||||
// - Non-trivial canvas size
|
||||
// - Many draw calls
|
||||
// - Same origin with root page (try to stem bleeding from WebGL ads/trackers)
|
||||
case dom::WebGLPowerPreference::High_performance:
|
||||
default:
|
||||
flags |= gl::CreateContextFlags::HIGH_POWER;
|
||||
break;
|
||||
}
|
||||
|
||||
#ifdef XP_MACOSX
|
||||
const nsCOMPtr<nsIGfxInfo> gfxInfo = services::GetGfxInfo();
|
||||
nsString vendorID, deviceID;
|
||||
@ -1410,6 +1435,7 @@ WebGLContext::GetContextAttributes(dom::Nullable<dom::WebGLContextAttributes>& r
|
||||
result.mPremultipliedAlpha = mOptions.premultipliedAlpha;
|
||||
result.mPreserveDrawingBuffer = mOptions.preserveDrawingBuffer;
|
||||
result.mFailIfMajorPerformanceCaveat = mOptions.failIfMajorPerformanceCaveat;
|
||||
result.mPowerPreference = mOptions.powerPreference;
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -30,10 +30,6 @@
|
||||
#include "ScopedGLHelpers.h"
|
||||
#include "TexUnpackBlob.h"
|
||||
|
||||
#ifdef XP_MACOSX
|
||||
#include "ForceDiscreteGPUHelperCGL.h"
|
||||
#endif
|
||||
|
||||
// Local
|
||||
#include "CacheMap.h"
|
||||
#include "WebGLContextLossHandler.h"
|
||||
@ -117,30 +113,17 @@ void AssertUintParamCorrect(gl::GLContext* gl, GLenum pname, GLuint shadow);
|
||||
|
||||
struct WebGLContextOptions
|
||||
{
|
||||
// these are defaults
|
||||
bool alpha = true;
|
||||
bool depth = true;
|
||||
bool stencil = false;
|
||||
bool premultipliedAlpha = true;
|
||||
bool antialias = true;
|
||||
bool preserveDrawingBuffer = false;
|
||||
bool failIfMajorPerformanceCaveat = false;
|
||||
dom::WebGLPowerPreference powerPreference = dom::WebGLPowerPreference::Default;
|
||||
|
||||
WebGLContextOptions();
|
||||
|
||||
bool operator==(const WebGLContextOptions& other) const {
|
||||
return
|
||||
alpha == other.alpha &&
|
||||
depth == other.depth &&
|
||||
stencil == other.stencil &&
|
||||
premultipliedAlpha == other.premultipliedAlpha &&
|
||||
antialias == other.antialias &&
|
||||
preserveDrawingBuffer == other.preserveDrawingBuffer;
|
||||
}
|
||||
|
||||
bool operator!=(const WebGLContextOptions& other) const {
|
||||
return !operator==(other);
|
||||
}
|
||||
|
||||
bool alpha;
|
||||
bool depth;
|
||||
bool stencil;
|
||||
bool premultipliedAlpha;
|
||||
bool antialias;
|
||||
bool preserveDrawingBuffer;
|
||||
bool failIfMajorPerformanceCaveat;
|
||||
bool operator==(const WebGLContextOptions&) const;
|
||||
};
|
||||
|
||||
// From WebGLContextUtils
|
||||
@ -2041,16 +2024,6 @@ public:
|
||||
template <typename WebGLObjectType>
|
||||
JSObject* WebGLObjectAsJSObject(JSContext* cx, const WebGLObjectType*,
|
||||
ErrorResult& rv) const;
|
||||
|
||||
#ifdef XP_MACOSX
|
||||
// see bug 713305. This RAII helper guarantees that we're on the discrete GPU, during its lifetime
|
||||
// Debouncing note: we don't want to switch GPUs too frequently, so try to not create and destroy
|
||||
// these objects at high frequency. Having WebGLContext's hold one such object seems fine,
|
||||
// because WebGLContext objects only go away during GC, which shouldn't happen too frequently.
|
||||
// If in the future GC becomes much more frequent, we may have to revisit then (maybe use a timer).
|
||||
ForceDiscreteGPUHelperCGL mForceDiscreteGPUHelper;
|
||||
#endif
|
||||
|
||||
public:
|
||||
// console logging helpers
|
||||
void GenerateWarning(const char* fmt, ...) const MOZ_FORMAT_PRINTF(2, 3);
|
||||
|
@ -206,26 +206,6 @@ static const NSOpenGLPixelFormatAttribute kAttribs_doubleBuffered_accel_webrende
|
||||
0
|
||||
};
|
||||
|
||||
static const NSOpenGLPixelFormatAttribute kAttribs_offscreen[] = {
|
||||
0
|
||||
};
|
||||
|
||||
static const NSOpenGLPixelFormatAttribute kAttribs_offscreen_allow_offline[] = {
|
||||
NSOpenGLPFAAllowOfflineRenderers,
|
||||
0
|
||||
};
|
||||
|
||||
static const NSOpenGLPixelFormatAttribute kAttribs_offscreen_accel[] = {
|
||||
NSOpenGLPFAAccelerated,
|
||||
0
|
||||
};
|
||||
|
||||
static const NSOpenGLPixelFormatAttribute kAttribs_offscreen_coreProfile[] = {
|
||||
NSOpenGLPFAAccelerated,
|
||||
NSOpenGLPFAOpenGLProfile, NSOpenGLProfileVersion3_2Core,
|
||||
0
|
||||
};
|
||||
|
||||
static NSOpenGLContext*
|
||||
CreateWithFormat(const NSOpenGLPixelFormatAttribute* attribs)
|
||||
{
|
||||
@ -307,23 +287,33 @@ CreateOffscreenFBOContext(CreateContextFlags flags)
|
||||
|
||||
NSOpenGLContext* context = nullptr;
|
||||
|
||||
if (!(flags & CreateContextFlags::REQUIRE_COMPAT_PROFILE)) {
|
||||
context = CreateWithFormat(kAttribs_offscreen_coreProfile);
|
||||
}
|
||||
if (!context) {
|
||||
if (flags & CreateContextFlags::ALLOW_OFFLINE_RENDERER) {
|
||||
if (gfxPrefs::RequireHardwareGL())
|
||||
context = CreateWithFormat(kAttribs_singleBuffered);
|
||||
else
|
||||
context = CreateWithFormat(kAttribs_offscreen_allow_offline);
|
||||
std::vector<NSOpenGLPixelFormatAttribute> attribs;
|
||||
|
||||
} else {
|
||||
if (gfxPrefs::RequireHardwareGL())
|
||||
context = CreateWithFormat(kAttribs_offscreen_accel);
|
||||
else
|
||||
context = CreateWithFormat(kAttribs_offscreen);
|
||||
}
|
||||
if (flags & CreateContextFlags::ALLOW_OFFLINE_RENDERER ||
|
||||
!(flags & CreateContextFlags::HIGH_POWER))
|
||||
{
|
||||
// This is really poorly named on Apple's part, but "AllowOfflineRenderers" means
|
||||
// that we want to allow running on the iGPU instead of requiring the dGPU.
|
||||
attribs.push_back(NSOpenGLPFAAllowOfflineRenderers);
|
||||
}
|
||||
|
||||
if (gfxPrefs::RequireHardwareGL()) {
|
||||
attribs.push_back(NSOpenGLPFAAccelerated);
|
||||
}
|
||||
|
||||
if (!(flags & CreateContextFlags::REQUIRE_COMPAT_PROFILE)) {
|
||||
auto coreAttribs = attribs;
|
||||
coreAttribs.push_back(NSOpenGLPFAOpenGLProfile);
|
||||
coreAttribs.push_back(NSOpenGLProfileVersion3_2Core);
|
||||
coreAttribs.push_back(0);
|
||||
context = CreateWithFormat(coreAttribs.data());
|
||||
}
|
||||
|
||||
if (!context) {
|
||||
attribs.push_back(0);
|
||||
context = CreateWithFormat(attribs.data());
|
||||
}
|
||||
|
||||
if (!context) {
|
||||
NS_WARNING("Failed to create NSOpenGLContext.");
|
||||
return nullptr;
|
||||
|
@ -45,7 +45,7 @@ struct GLFormats
|
||||
GLsizei samples;
|
||||
};
|
||||
|
||||
enum class CreateContextFlags : int8_t {
|
||||
enum class CreateContextFlags : uint8_t {
|
||||
NONE = 0,
|
||||
REQUIRE_COMPAT_PROFILE = 1 << 0,
|
||||
// Force the use of hardware backed GL, don't allow software implementations.
|
||||
@ -57,6 +57,8 @@ enum class CreateContextFlags : int8_t {
|
||||
|
||||
NO_VALIDATION = 1 << 4,
|
||||
PREFER_ROBUSTNESS = 1 << 5,
|
||||
|
||||
HIGH_POWER = 1 << 6,
|
||||
};
|
||||
MOZ_MAKE_ENUM_CLASS_BITWISE_OPERATORS(CreateContextFlags)
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user