зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1885447 - Tonemap/color-manage webgl sdr/wcg output into Display profile as pre-compositor post-process. r=gfx-reviewers,webidl,smaug,ahale
Differential Revision: https://phabricator.services.mozilla.com/D207651
This commit is contained in:
Родитель
df99f6fd0f
Коммит
401c6844d9
|
@ -736,6 +736,21 @@ void ClientWebGLContext::GetCanvas(
|
|||
}
|
||||
}
|
||||
|
||||
void ClientWebGLContext::SetDrawingBufferColorSpace(
|
||||
const dom::PredefinedColorSpace val) {
|
||||
mDrawingBufferColorSpace = val;
|
||||
|
||||
// Just in case, update in Options too.
|
||||
// Why not treat our WebGLContextOptions as the source of truth? Well,
|
||||
// mNotLost is lost on context-loss, so we'd lose any setting we had here if
|
||||
// that happens.
|
||||
if (mNotLost) {
|
||||
mNotLost->info.options.colorSpace = mDrawingBufferColorSpace;
|
||||
}
|
||||
|
||||
Run<RPROC(SetDrawingBufferColorSpace)>(mDrawingBufferColorSpace);
|
||||
}
|
||||
|
||||
void ClientWebGLContext::GetContextAttributes(
|
||||
dom::Nullable<dom::WebGLContextAttributes>& retval) {
|
||||
retval.SetNull();
|
||||
|
@ -1058,9 +1073,7 @@ ClientWebGLContext::SetContextOptions(JSContext* cx,
|
|||
if (attributes.mAntialias.WasPassed()) {
|
||||
newOpts.antialias = attributes.mAntialias.Value();
|
||||
}
|
||||
newOpts.ignoreColorSpace = true;
|
||||
if (attributes.mColorSpace.WasPassed()) {
|
||||
newOpts.ignoreColorSpace = false;
|
||||
newOpts.colorSpace = attributes.mColorSpace.Value();
|
||||
}
|
||||
|
||||
|
|
|
@ -1052,6 +1052,20 @@ class ClientWebGLContext final : public nsICanvasRenderingContextInternal,
|
|||
const FuncScope funcScope(*this, "drawingBufferHeight");
|
||||
return AutoAssertCast(DrawingBufferSize().y);
|
||||
}
|
||||
|
||||
// -
|
||||
|
||||
private:
|
||||
dom::PredefinedColorSpace mDrawingBufferColorSpace =
|
||||
dom::PredefinedColorSpace::Srgb;
|
||||
|
||||
public:
|
||||
auto DrawingBufferColorSpace() const { return mDrawingBufferColorSpace; }
|
||||
|
||||
void SetDrawingBufferColorSpace(dom::PredefinedColorSpace);
|
||||
|
||||
// -
|
||||
|
||||
void GetContextAttributes(dom::Nullable<dom::WebGLContextAttributes>& retval);
|
||||
|
||||
private:
|
||||
|
|
|
@ -201,6 +201,9 @@ class HostWebGLContext final : public SupportsWeakPtr {
|
|||
|
||||
// -
|
||||
|
||||
void SetDrawingBufferColorSpace(const dom::PredefinedColorSpace val) const {
|
||||
mContext->SetDrawingBufferColorSpace(val);
|
||||
}
|
||||
void Resize(const uvec2& size) { return mContext->Resize(size); }
|
||||
|
||||
uvec2 DrawingBufferSize() { return mContext->DrawingBufferSize(); }
|
||||
|
|
|
@ -894,63 +894,62 @@ void WebGLContext::BlitBackbufferToCurDriverFB(
|
|||
if (mScissorTestEnabled) {
|
||||
gl->fDisable(LOCAL_GL_SCISSOR_TEST);
|
||||
}
|
||||
|
||||
[&]() {
|
||||
// If a MozFramebuffer is supplied, ensure that a WebGLFramebuffer is not
|
||||
// used since it might not have completeness info, while the MozFramebuffer
|
||||
// can still supply the needed information.
|
||||
MOZ_ASSERT(!(srcAsMozFb && srcAsWebglFb));
|
||||
const auto* mozFb = srcAsMozFb ? srcAsMozFb : mDefaultFB.get();
|
||||
GLuint fbo = 0;
|
||||
gfx::IntSize size;
|
||||
if (srcAsWebglFb) {
|
||||
fbo = srcAsWebglFb->mGLName;
|
||||
const auto* info = srcAsWebglFb->GetCompletenessInfo();
|
||||
MOZ_ASSERT(info);
|
||||
size = gfx::IntSize(info->width, info->height);
|
||||
} else {
|
||||
fbo = mozFb->mFB;
|
||||
size = mozFb->mSize;
|
||||
const auto cleanup = MakeScopeExit([&]() {
|
||||
if (mScissorTestEnabled) {
|
||||
gl->fEnable(LOCAL_GL_SCISSOR_TEST);
|
||||
}
|
||||
});
|
||||
|
||||
// If no format conversion is necessary, then attempt to directly blit
|
||||
// between framebuffers. Otherwise, if we need to convert to RGBA from
|
||||
// the source format, then we will need to use the texture blit path
|
||||
// below.
|
||||
if (!srcIsBGRA) {
|
||||
if (gl->IsSupported(gl::GLFeature::framebuffer_blit)) {
|
||||
gl->fBindFramebuffer(LOCAL_GL_READ_FRAMEBUFFER, fbo);
|
||||
gl->fBlitFramebuffer(0, 0, size.width, size.height, 0, 0, size.width,
|
||||
size.height, LOCAL_GL_COLOR_BUFFER_BIT,
|
||||
LOCAL_GL_NEAREST);
|
||||
return;
|
||||
}
|
||||
if (mDefaultFB->mSamples &&
|
||||
gl->IsExtensionSupported(
|
||||
gl::GLContext::APPLE_framebuffer_multisample)) {
|
||||
gl->fBindFramebuffer(LOCAL_GL_READ_FRAMEBUFFER, fbo);
|
||||
gl->fResolveMultisampleFramebufferAPPLE();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
GLuint colorTex = 0;
|
||||
if (srcAsWebglFb) {
|
||||
const auto& attach = srcAsWebglFb->ColorAttachment0();
|
||||
MOZ_ASSERT(attach.Texture());
|
||||
colorTex = attach.Texture()->mGLName;
|
||||
} else {
|
||||
colorTex = mozFb->ColorTex();
|
||||
}
|
||||
|
||||
// DrawBlit handles ColorMask itself.
|
||||
gl->BlitHelper()->DrawBlitTextureToFramebuffer(
|
||||
colorTex, size, size, LOCAL_GL_TEXTURE_2D, srcIsBGRA);
|
||||
}();
|
||||
|
||||
if (mScissorTestEnabled) {
|
||||
gl->fEnable(LOCAL_GL_SCISSOR_TEST);
|
||||
// If a MozFramebuffer is supplied, ensure that a WebGLFramebuffer is not
|
||||
// used since it might not have completeness info, while the MozFramebuffer
|
||||
// can still supply the needed information.
|
||||
MOZ_ASSERT(!(srcAsMozFb && srcAsWebglFb));
|
||||
const auto* mozFb = srcAsMozFb ? srcAsMozFb : mDefaultFB.get();
|
||||
GLuint fbo = 0;
|
||||
gfx::IntSize size;
|
||||
if (srcAsWebglFb) {
|
||||
fbo = srcAsWebglFb->mGLName;
|
||||
const auto* info = srcAsWebglFb->GetCompletenessInfo();
|
||||
MOZ_ASSERT(info);
|
||||
size = gfx::IntSize(info->width, info->height);
|
||||
} else {
|
||||
fbo = mozFb->mFB;
|
||||
size = mozFb->mSize;
|
||||
}
|
||||
|
||||
// If no format conversion is necessary, then attempt to directly blit
|
||||
// between framebuffers. Otherwise, if we need to convert to RGBA from
|
||||
// the source format, then we will need to use the texture blit path
|
||||
// below.
|
||||
if (!srcIsBGRA) {
|
||||
if (gl->IsSupported(gl::GLFeature::framebuffer_blit)) {
|
||||
gl->fBindFramebuffer(LOCAL_GL_READ_FRAMEBUFFER, fbo);
|
||||
gl->fBlitFramebuffer(0, 0, size.width, size.height, 0, 0, size.width,
|
||||
size.height, LOCAL_GL_COLOR_BUFFER_BIT,
|
||||
LOCAL_GL_NEAREST);
|
||||
return;
|
||||
}
|
||||
if (mDefaultFB->mSamples &&
|
||||
gl->IsExtensionSupported(
|
||||
gl::GLContext::APPLE_framebuffer_multisample)) {
|
||||
gl->fBindFramebuffer(LOCAL_GL_READ_FRAMEBUFFER, fbo);
|
||||
gl->fResolveMultisampleFramebufferAPPLE();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
GLuint colorTex = 0;
|
||||
if (srcAsWebglFb) {
|
||||
const auto& attach = srcAsWebglFb->ColorAttachment0();
|
||||
MOZ_ASSERT(attach.Texture());
|
||||
colorTex = attach.Texture()->mGLName;
|
||||
} else {
|
||||
colorTex = mozFb->ColorTex();
|
||||
}
|
||||
|
||||
// DrawBlit handles ColorMask itself.
|
||||
gl->BlitHelper()->DrawBlitTextureToFramebuffer(
|
||||
colorTex, size, size, LOCAL_GL_TEXTURE_2D, srcIsBGRA);
|
||||
}
|
||||
|
||||
// -
|
||||
|
@ -960,19 +959,34 @@ constexpr auto MakeArray(Args... args) -> std::array<T, sizeof...(Args)> {
|
|||
return {{static_cast<T>(args)...}};
|
||||
}
|
||||
|
||||
inline gfx::ColorSpace2 ToColorSpace2(const WebGLContextOptions& options) {
|
||||
auto ret = gfx::ColorSpace2::UNKNOWN;
|
||||
if (true) {
|
||||
ret = gfx::ColorSpace2::SRGB;
|
||||
inline gfx::ColorSpace2 ToColorSpace2ForOutput(
|
||||
const std::optional<dom::PredefinedColorSpace> chosenCspace) {
|
||||
const auto cmsMode = GfxColorManagementMode();
|
||||
switch (cmsMode) {
|
||||
case CMSMode::Off:
|
||||
return gfx::ColorSpace2::Display;
|
||||
case CMSMode::TaggedOnly:
|
||||
if (!chosenCspace) {
|
||||
return gfx::ColorSpace2::Display;
|
||||
}
|
||||
break;
|
||||
case CMSMode::All:
|
||||
if (!chosenCspace) {
|
||||
return gfx::ColorSpace2::SRGB;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (!options.ignoreColorSpace) {
|
||||
ret = gfx::ToColorSpace2(options.colorSpace);
|
||||
}
|
||||
return ret;
|
||||
return gfx::ToColorSpace2(*chosenCspace);
|
||||
}
|
||||
|
||||
// -
|
||||
|
||||
template <class T>
|
||||
GLuint GLNameOrZero(const T& t) {
|
||||
if (t) return t->mGLName;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// For an overview of how WebGL compositing works, see:
|
||||
// https://wiki.mozilla.org/Platform/GFX/WebGL/Compositing
|
||||
bool WebGLContext::PresentInto(gl::SwapChain& swapChain) {
|
||||
|
@ -980,46 +994,100 @@ bool WebGLContext::PresentInto(gl::SwapChain& swapChain) {
|
|||
|
||||
if (!ValidateAndInitFB(nullptr)) return false;
|
||||
|
||||
{
|
||||
const auto colorSpace = ToColorSpace2(mOptions);
|
||||
auto presenter = swapChain.Acquire(mDefaultFB->mSize, colorSpace);
|
||||
const auto size = mDefaultFB->mSize;
|
||||
|
||||
const auto error = [&]() -> std::optional<std::string> {
|
||||
const auto canvasCspace = ToColorSpace2ForOutput(mOptions.colorSpace);
|
||||
auto presenter = swapChain.Acquire(size, canvasCspace);
|
||||
if (!presenter) {
|
||||
GenerateWarning("Swap chain surface creation failed.");
|
||||
LoseContext();
|
||||
return false;
|
||||
return "Swap chain surface creation failed.";
|
||||
}
|
||||
|
||||
const auto outputCspace = presenter->BackBuffer()->mDesc.colorSpace;
|
||||
const auto destFb = presenter->Fb();
|
||||
gl->fBindFramebuffer(LOCAL_GL_FRAMEBUFFER, destFb);
|
||||
|
||||
BlitBackbufferToCurDriverFB();
|
||||
// -
|
||||
|
||||
if (!mOptions.preserveDrawingBuffer) {
|
||||
if (gl->IsSupported(gl::GLFeature::invalidate_framebuffer)) {
|
||||
gl->fBindFramebuffer(LOCAL_GL_READ_FRAMEBUFFER, mDefaultFB->mFB);
|
||||
constexpr auto attachments = MakeArray<GLenum>(
|
||||
LOCAL_GL_COLOR_ATTACHMENT0, LOCAL_GL_DEPTH_STENCIL_ATTACHMENT);
|
||||
gl->fInvalidateFramebuffer(LOCAL_GL_READ_FRAMEBUFFER,
|
||||
attachments.size(), attachments.data());
|
||||
}
|
||||
mDefaultFB_IsInvalid = true;
|
||||
bool colorManage = (canvasCspace != gfx::ColorSpace2::Display);
|
||||
if (canvasCspace == outputCspace) {
|
||||
colorManage = false;
|
||||
}
|
||||
if (!gl->IsSupported(gl::GLFeature::texture_3D)) {
|
||||
NS_WARNING("Missing GLFeature::texture_3D => colorManage = false.");
|
||||
colorManage = false;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
if (!mOptions.alpha) {
|
||||
gl->fBindFramebuffer(LOCAL_GL_FRAMEBUFFER, destFb);
|
||||
gl->fPixelStorei(LOCAL_GL_PACK_ALIGNMENT, 4);
|
||||
if (IsWebGL2()) {
|
||||
gl->fPixelStorei(LOCAL_GL_PACK_ROW_LENGTH, 0);
|
||||
gl->fPixelStorei(LOCAL_GL_PACK_SKIP_PIXELS, 0);
|
||||
gl->fPixelStorei(LOCAL_GL_PACK_SKIP_ROWS, 0);
|
||||
auto colorLut = std::shared_ptr<gl::Texture>{};
|
||||
if (colorManage) {
|
||||
MOZ_ASSERT(canvasCspace != gfx::ColorSpace2::Display);
|
||||
colorLut = gl->BlitHelper()->GetColorLutTex(gl::GLBlitHelper::ColorLutKey{
|
||||
.src = canvasCspace, .dst = outputCspace});
|
||||
if (!colorLut) {
|
||||
NS_WARNING("GetColorLutTex() -> nullptr => colorManage = false.");
|
||||
colorManage = false;
|
||||
}
|
||||
uint32_t pixel = 0xffbadbad;
|
||||
gl->fReadPixels(0, 0, 1, 1, LOCAL_GL_RGBA, LOCAL_GL_UNSIGNED_BYTE,
|
||||
&pixel);
|
||||
MOZ_ASSERT((pixel & 0xff000000) == 0xff000000);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!colorManage) {
|
||||
gl->fBindFramebuffer(LOCAL_GL_DRAW_FRAMEBUFFER, destFb);
|
||||
BlitBackbufferToCurDriverFB();
|
||||
return {};
|
||||
}
|
||||
|
||||
// -
|
||||
|
||||
const auto canvasFb = GetDefaultFBForRead({.endOfFrame = true});
|
||||
if (!canvasFb) {
|
||||
return "[WebGLContext::PresentInto] BindDefaultFBForRead failed.";
|
||||
}
|
||||
|
||||
const auto& blitter = gl->BlitHelper()->GetDrawBlitProg({
|
||||
.fragHeader = gl::kFragHeader_Tex2D,
|
||||
.fragParts = {gl::kFragSample_OnePlane, gl::kFragConvert_ColorLut3d},
|
||||
});
|
||||
|
||||
constexpr uint8_t texUnit_src = 0;
|
||||
constexpr uint8_t texUnit_lut = 1;
|
||||
gl->BindSamplerTexture(texUnit_src, SamplerLinear(), LOCAL_GL_TEXTURE_2D,
|
||||
canvasFb->ColorTex());
|
||||
gl->BindSamplerTexture(texUnit_lut, SamplerLinear(), LOCAL_GL_TEXTURE_3D,
|
||||
colorLut->name);
|
||||
const auto texCleanup = MakeScopeExit([&]() {
|
||||
gl->BindSamplerTexture(
|
||||
texUnit_src, GLNameOrZero(mBoundSamplers[texUnit_src]),
|
||||
LOCAL_GL_TEXTURE_2D, GLNameOrZero(mBound2DTextures[texUnit_src]));
|
||||
gl->BindSamplerTexture(
|
||||
texUnit_lut, GLNameOrZero(mBoundSamplers[texUnit_lut]),
|
||||
LOCAL_GL_TEXTURE_3D, GLNameOrZero(mBound3DTextures[texUnit_lut]));
|
||||
gl->fActiveTexture(LOCAL_GL_TEXTURE0 + mActiveTexture);
|
||||
});
|
||||
|
||||
gl->fBindFramebuffer(LOCAL_GL_DRAW_FRAMEBUFFER, destFb);
|
||||
|
||||
gl->fUseProgram(blitter.mProg);
|
||||
const auto cleanupProg = MakeScopeExit(
|
||||
[&]() { gl->fUseProgram(GLNameOrZero(mCurrentProgram)); });
|
||||
|
||||
gl->fUniform1i(blitter.mLoc_uColorLut, texUnit_lut);
|
||||
|
||||
blitter.Draw({
|
||||
.texMatrix0 = gl::Mat3::I(),
|
||||
.yFlip = false,
|
||||
.destSize = size,
|
||||
.destRect = {},
|
||||
});
|
||||
|
||||
gl->fBindFramebuffer(LOCAL_GL_READ_FRAMEBUFFER, canvasFb->mFB);
|
||||
return {};
|
||||
}();
|
||||
if (error) {
|
||||
GenerateWarning("%s", error->c_str());
|
||||
LoseContext();
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!mOptions.preserveDrawingBuffer) {
|
||||
gl->InvalidateFramebuffer(LOCAL_GL_READ_FRAMEBUFFER);
|
||||
mDefaultFB_IsInvalid = true;
|
||||
}
|
||||
|
||||
return true;
|
||||
|
@ -1029,7 +1097,7 @@ bool WebGLContext::PresentIntoXR(gl::SwapChain& swapChain,
|
|||
const gl::MozFramebuffer& fb) {
|
||||
OnEndOfFrame();
|
||||
|
||||
const auto colorSpace = ToColorSpace2(mOptions);
|
||||
const auto colorSpace = ToColorSpace2ForOutput(mOptions.colorSpace);
|
||||
auto presenter = swapChain.Acquire(fb.mSize, colorSpace);
|
||||
if (!presenter) {
|
||||
GenerateWarning("Swap chain surface creation failed.");
|
||||
|
@ -1153,7 +1221,7 @@ bool WebGLContext::CopyToSwapChain(
|
|||
|
||||
{
|
||||
// ColorSpace will need to be part of SwapChainOptions for DTWebgl.
|
||||
const auto colorSpace = ToColorSpace2(mOptions);
|
||||
const auto colorSpace = ToColorSpace2ForOutput(mOptions.colorSpace);
|
||||
auto presenter = srcFb->mSwapChain.Acquire(size, colorSpace);
|
||||
if (!presenter) {
|
||||
GenerateWarning("Swap chain surface creation failed.");
|
||||
|
@ -1697,12 +1765,12 @@ bool WebGLContext::BindCurFBForColorRead(
|
|||
return true;
|
||||
}
|
||||
|
||||
bool WebGLContext::BindDefaultFBForRead() {
|
||||
if (!ValidateAndInitFB(nullptr)) return false;
|
||||
const gl::MozFramebuffer* WebGLContext::GetDefaultFBForRead(
|
||||
const GetDefaultFBForReadDesc& desc) {
|
||||
if (!ValidateAndInitFB(nullptr)) return nullptr;
|
||||
|
||||
if (!mDefaultFB->mSamples) {
|
||||
gl->fBindFramebuffer(LOCAL_GL_FRAMEBUFFER, mDefaultFB->mFB);
|
||||
return true;
|
||||
return mDefaultFB.get();
|
||||
}
|
||||
|
||||
if (!mResolvedDefaultFB) {
|
||||
|
@ -1710,14 +1778,24 @@ bool WebGLContext::BindDefaultFBForRead() {
|
|||
gl::MozFramebuffer::Create(gl, mDefaultFB->mSize, 0, false);
|
||||
if (!mResolvedDefaultFB) {
|
||||
gfxCriticalNote << FuncName() << ": Failed to create mResolvedDefaultFB.";
|
||||
return false;
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
gl->fBindFramebuffer(LOCAL_GL_FRAMEBUFFER, mResolvedDefaultFB->mFB);
|
||||
gl->fBindFramebuffer(LOCAL_GL_DRAW_FRAMEBUFFER, mResolvedDefaultFB->mFB);
|
||||
BlitBackbufferToCurDriverFB();
|
||||
|
||||
gl->fBindFramebuffer(LOCAL_GL_FRAMEBUFFER, mResolvedDefaultFB->mFB);
|
||||
if (desc.endOfFrame && !mOptions.preserveDrawingBuffer) {
|
||||
gl->InvalidateFramebuffer(LOCAL_GL_READ_FRAMEBUFFER);
|
||||
}
|
||||
|
||||
return mResolvedDefaultFB.get();
|
||||
}
|
||||
|
||||
bool WebGLContext::BindDefaultFBForRead() {
|
||||
const auto fb = GetDefaultFBForRead();
|
||||
if (!fb) return false;
|
||||
gl->fBindFramebuffer(LOCAL_GL_READ_FRAMEBUFFER, fb->mFB);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -2661,4 +2739,21 @@ webgl::ExplicitPixelPackingState::ForUseWith(
|
|||
return {{state, metrics}};
|
||||
}
|
||||
|
||||
GLuint WebGLContext::SamplerLinear() const {
|
||||
if (!mSamplerLinear) {
|
||||
mSamplerLinear = std::make_unique<gl::Sampler>(*gl);
|
||||
gl->fSamplerParameteri(mSamplerLinear->name, LOCAL_GL_TEXTURE_MAG_FILTER,
|
||||
LOCAL_GL_LINEAR);
|
||||
gl->fSamplerParameteri(mSamplerLinear->name, LOCAL_GL_TEXTURE_MIN_FILTER,
|
||||
LOCAL_GL_LINEAR);
|
||||
gl->fSamplerParameteri(mSamplerLinear->name, LOCAL_GL_TEXTURE_WRAP_S,
|
||||
LOCAL_GL_CLAMP_TO_EDGE);
|
||||
gl->fSamplerParameteri(mSamplerLinear->name, LOCAL_GL_TEXTURE_WRAP_T,
|
||||
LOCAL_GL_CLAMP_TO_EDGE);
|
||||
gl->fSamplerParameteri(mSamplerLinear->name, LOCAL_GL_TEXTURE_WRAP_R,
|
||||
LOCAL_GL_CLAMP_TO_EDGE);
|
||||
}
|
||||
return mSamplerLinear->name;
|
||||
}
|
||||
|
||||
} // namespace mozilla
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
#include <memory>
|
||||
#include <stdarg.h>
|
||||
|
||||
#include "Colorspaces.h"
|
||||
#include "GLContextTypes.h"
|
||||
#include "GLDefs.h"
|
||||
#include "GLScreenBuffer.h"
|
||||
|
@ -96,6 +97,7 @@ namespace gl {
|
|||
class GLScreenBuffer;
|
||||
class MozFramebuffer;
|
||||
class SharedSurface;
|
||||
class Sampler;
|
||||
class Texture;
|
||||
} // namespace gl
|
||||
|
||||
|
@ -536,6 +538,12 @@ class WebGLContext : public VRefCounted, public SupportsWeakPtr {
|
|||
Maybe<layers::SurfaceDescriptor> GetFrontBuffer(WebGLFramebuffer*,
|
||||
const bool webvr);
|
||||
|
||||
std::optional<color::ColorProfileDesc> mDisplayProfile;
|
||||
|
||||
void SetDrawingBufferColorSpace(const dom::PredefinedColorSpace val) {
|
||||
mOptions.colorSpace = val;
|
||||
}
|
||||
|
||||
void ClearVRSwapChain();
|
||||
|
||||
void RunContextLossTimer();
|
||||
|
@ -1156,6 +1164,10 @@ class WebGLContext : public VRefCounted, public SupportsWeakPtr {
|
|||
nsTArray<RefPtr<WebGLTexture>> mBound2DArrayTextures;
|
||||
nsTArray<RefPtr<WebGLSampler>> mBoundSamplers;
|
||||
|
||||
mutable std::unique_ptr<gl::Sampler> mSamplerLinear;
|
||||
|
||||
GLuint SamplerLinear() const;
|
||||
|
||||
void ResolveTexturesForDraw() const;
|
||||
|
||||
RefPtr<WebGLProgram> mCurrentProgram;
|
||||
|
@ -1265,6 +1277,10 @@ class WebGLContext : public VRefCounted, public SupportsWeakPtr {
|
|||
mutable bool mDefaultFB_IsInvalid = false;
|
||||
mutable UniquePtr<gl::MozFramebuffer> mResolvedDefaultFB;
|
||||
|
||||
mutable std::unordered_map<std::tuple<gfx::ColorSpace2, gfx::ColorSpace2>,
|
||||
std::shared_ptr<gl::Texture>>
|
||||
mLutTexByColorMapping;
|
||||
|
||||
gl::SwapChain mSwapChain;
|
||||
gl::SwapChain mWebVRSwapChain;
|
||||
|
||||
|
@ -1303,6 +1319,15 @@ class WebGLContext : public VRefCounted, public SupportsWeakPtr {
|
|||
WebGLFramebuffer* const srcAsWebglFb = nullptr,
|
||||
const gl::MozFramebuffer* const srcAsMozFb = nullptr,
|
||||
bool srcIsBGRA = false) const;
|
||||
|
||||
struct GetDefaultFBForReadDesc {
|
||||
bool endOfFrame = false;
|
||||
};
|
||||
const gl::MozFramebuffer* GetDefaultFBForRead(const GetDefaultFBForReadDesc&);
|
||||
const gl::MozFramebuffer* GetDefaultFBForRead() {
|
||||
return GetDefaultFBForRead({});
|
||||
}
|
||||
|
||||
bool BindDefaultFBForRead();
|
||||
|
||||
// --
|
||||
|
|
|
@ -96,7 +96,7 @@ void WebGLContext::BindTexture(GLenum rawTarget, WebGLTexture* newTex) {
|
|||
return;
|
||||
}
|
||||
|
||||
const TexTarget texTarget(rawTarget);
|
||||
const auto texTarget = TexTarget(rawTarget);
|
||||
if (newTex) {
|
||||
if (!newTex->BindTexture(texTarget)) return;
|
||||
} else {
|
||||
|
|
|
@ -18,6 +18,8 @@
|
|||
#include "TupleUtils.h"
|
||||
#include "WebGLTypes.h"
|
||||
|
||||
#include <memory>
|
||||
|
||||
namespace mozilla {
|
||||
namespace webgl {
|
||||
|
||||
|
@ -652,6 +654,32 @@ struct ParamTraits<mozilla::avec3<U>> final {
|
|||
}
|
||||
};
|
||||
|
||||
// -
|
||||
|
||||
template <class U>
|
||||
struct ParamTraits<std::optional<U>> final {
|
||||
using T = std::optional<U>;
|
||||
|
||||
static void Write(MessageWriter* const writer, const T& in) {
|
||||
WriteParam(writer, bool{in});
|
||||
if (in) {
|
||||
WriteParam(writer, *in);
|
||||
}
|
||||
}
|
||||
|
||||
static bool Read(MessageReader* const reader, T* const out) {
|
||||
bool isSome;
|
||||
if (!ReadParam(reader, &isSome)) return false;
|
||||
|
||||
if (!isSome) {
|
||||
out->reset();
|
||||
return true;
|
||||
}
|
||||
out->emplace();
|
||||
return ReadParam(reader, &**out);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace IPC
|
||||
|
||||
#endif
|
||||
|
|
|
@ -93,6 +93,7 @@ DEFINE_ASYNC(HostWebGLContext::ProvokingVertex)
|
|||
DEFINE_ASYNC(HostWebGLContext::Present)
|
||||
DEFINE_ASYNC(HostWebGLContext::SampleCoverage)
|
||||
DEFINE_ASYNC(HostWebGLContext::Scissor)
|
||||
DEFINE_ASYNC(HostWebGLContext::SetDrawingBufferColorSpace)
|
||||
DEFINE_ASYNC(HostWebGLContext::ShaderSource)
|
||||
DEFINE_ASYNC(HostWebGLContext::StencilFuncSeparate)
|
||||
DEFINE_ASYNC(HostWebGLContext::StencilMaskSeparate)
|
||||
|
|
|
@ -61,25 +61,6 @@ struct QueueParamTraits<avec3<T>> : QueueParamTraits_TiedFields<avec3<T>> {};
|
|||
// ---------------------------------------------------------------------
|
||||
// Enums!
|
||||
|
||||
inline constexpr bool IsEnumCase(const dom::WebGLPowerPreference raw) {
|
||||
switch (raw) {
|
||||
case dom::WebGLPowerPreference::Default:
|
||||
case dom::WebGLPowerPreference::Low_power:
|
||||
case dom::WebGLPowerPreference::High_performance:
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
inline constexpr bool IsEnumCase(const dom::PredefinedColorSpace raw) {
|
||||
switch (raw) {
|
||||
case dom::PredefinedColorSpace::Srgb:
|
||||
case dom::PredefinedColorSpace::Display_p3:
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
inline constexpr bool IsEnumCase(const webgl::AttribBaseType raw) {
|
||||
switch (raw) {
|
||||
case webgl::AttribBaseType::Boolean:
|
||||
|
@ -91,16 +72,14 @@ inline constexpr bool IsEnumCase(const webgl::AttribBaseType raw) {
|
|||
return false;
|
||||
}
|
||||
|
||||
static_assert(IsEnumCase(dom::WebGLPowerPreference(2)));
|
||||
static_assert(!IsEnumCase(dom::WebGLPowerPreference(3)));
|
||||
static_assert(!IsEnumCase(dom::WebGLPowerPreference(5)));
|
||||
static_assert(IsEnumCase(webgl::AttribBaseType(3)));
|
||||
static_assert(!IsEnumCase(webgl::AttribBaseType(4)));
|
||||
static_assert(!IsEnumCase(webgl::AttribBaseType(5)));
|
||||
|
||||
#define USE_IS_ENUM_CASE(T) \
|
||||
template <> \
|
||||
struct QueueParamTraits<T> : QueueParamTraits_IsEnumCase<T> {};
|
||||
|
||||
USE_IS_ENUM_CASE(dom::WebGLPowerPreference)
|
||||
USE_IS_ENUM_CASE(dom::PredefinedColorSpace)
|
||||
USE_IS_ENUM_CASE(webgl::AttribBaseType)
|
||||
USE_IS_ENUM_CASE(webgl::ProvokingVertex)
|
||||
|
||||
|
@ -283,6 +262,20 @@ struct QueueParamTraits<gfxAlphaType>
|
|||
: public ContiguousEnumSerializerInclusive<
|
||||
gfxAlphaType, gfxAlphaType::Opaque, gfxAlphaType::NonPremult> {};
|
||||
|
||||
// -
|
||||
|
||||
template <class Enum>
|
||||
using WebIDLEnumQueueSerializer =
|
||||
ContiguousEnumSerializerInclusive<Enum, ContiguousEnumValues<Enum>::min,
|
||||
ContiguousEnumValues<Enum>::max>;
|
||||
|
||||
template <>
|
||||
struct QueueParamTraits<dom::WebGLPowerPreference>
|
||||
: public WebIDLEnumQueueSerializer<dom::WebGLPowerPreference> {};
|
||||
template <>
|
||||
struct QueueParamTraits<dom::PredefinedColorSpace>
|
||||
: public WebIDLEnumQueueSerializer<dom::PredefinedColorSpace> {};
|
||||
|
||||
} // namespace webgl
|
||||
} // namespace mozilla
|
||||
|
||||
|
|
|
@ -362,8 +362,7 @@ struct WebGLContextOptions final {
|
|||
|
||||
dom::WebGLPowerPreference powerPreference =
|
||||
dom::WebGLPowerPreference::Default;
|
||||
bool ignoreColorSpace = true;
|
||||
dom::PredefinedColorSpace colorSpace = dom::PredefinedColorSpace::Srgb;
|
||||
std::optional<dom::PredefinedColorSpace> colorSpace;
|
||||
bool shouldResistFingerprinting = true;
|
||||
|
||||
bool enableDebugRendererInfo = false;
|
||||
|
@ -383,7 +382,6 @@ struct WebGLContextOptions final {
|
|||
|
||||
powerPreference,
|
||||
colorSpace,
|
||||
ignoreColorSpace,
|
||||
shouldResistFingerprinting,
|
||||
|
||||
enableDebugRendererInfo);
|
||||
|
|
|
@ -17,160 +17,217 @@ defaults pref(webgl.colorspaces.prototype,true)
|
|||
|
||||
### Generated, do not edit. ###
|
||||
# -
|
||||
skip-if(!cocoaWidget) == color_canvas.html?e_context=webgl&e_webgl_format=RGBA8&e_cspace=srgb&e_color=color(srgb,0.000,0.000,0.000) color_canvas.html?e_context=css&e_color=color(srgb,0.000,0.000,0.000)
|
||||
skip-if(cocoaWidget) == color_canvas.html?e_context=webgl&e_webgl_format=RGBA8&e_cspace=srgb&e_color=color(srgb,0.000,0.000,0.000) color_canvas.html?e_context=css&e_color=color(srgb,0.000,0.000,0.000)
|
||||
skip-if(!cocoaWidget) == color_canvas.html?e_context=webgl&e_webgl_format=RGBA8&e_cspace=srgb&e_color=color(srgb,0.200,0.200,0.200) color_canvas.html?e_context=css&e_color=color(srgb,0.200,0.200,0.200)
|
||||
skip-if(cocoaWidget) == color_canvas.html?e_context=webgl&e_webgl_format=RGBA8&e_cspace=srgb&e_color=color(srgb,0.200,0.200,0.200) color_canvas.html?e_context=css&e_color=color(srgb,0.200,0.200,0.200)
|
||||
skip-if(!cocoaWidget) == color_canvas.html?e_context=webgl&e_webgl_format=RGBA8&e_cspace=srgb&e_color=color(srgb,0.000,0.000,0.000) color_canvas.html?e_context=css&e_color=color(srgb,0.000,0.000,0.000)
|
||||
skip-if(cocoaWidget) == color_canvas.html?e_context=webgl&e_webgl_format=RGBA8&e_cspace=srgb&e_color=color(srgb,0.000,0.000,0.000) color_canvas.html?e_context=css&e_color=color(srgb,0.000,0.000,0.000)
|
||||
skip-if(!cocoaWidget) == color_canvas.html?e_context=webgl&e_webgl_format=RGBA8&e_cspace=srgb&e_color=color(srgb,0.200,0.200,0.200) color_canvas.html?e_context=css&e_color=color(srgb,0.200,0.200,0.200)
|
||||
skip-if(cocoaWidget) == color_canvas.html?e_context=webgl&e_webgl_format=RGBA8&e_cspace=srgb&e_color=color(srgb,0.200,0.200,0.200) color_canvas.html?e_context=css&e_color=color(srgb,0.200,0.200,0.200)
|
||||
### Generated, do not edit. ###
|
||||
skip-if(!cocoaWidget) == color_canvas.html?e_context=webgl&e_webgl_format=RGBA8&e_cspace=srgb&e_color=color(srgb,0.200,0.000,0.000) color_canvas.html?e_context=css&e_color=color(srgb,0.200,0.000,0.000)
|
||||
skip-if(cocoaWidget) == color_canvas.html?e_context=webgl&e_webgl_format=RGBA8&e_cspace=srgb&e_color=color(srgb,0.200,0.000,0.000) color_canvas.html?e_context=css&e_color=color(srgb,0.200,0.000,0.000)
|
||||
skip-if(!cocoaWidget) == color_canvas.html?e_context=webgl&e_webgl_format=RGBA8&e_cspace=srgb&e_color=color(srgb,0.000,0.200,0.000) color_canvas.html?e_context=css&e_color=color(srgb,0.000,0.200,0.000)
|
||||
skip-if(cocoaWidget) == color_canvas.html?e_context=webgl&e_webgl_format=RGBA8&e_cspace=srgb&e_color=color(srgb,0.000,0.200,0.000) color_canvas.html?e_context=css&e_color=color(srgb,0.000,0.200,0.000)
|
||||
skip-if(!cocoaWidget) == color_canvas.html?e_context=webgl&e_webgl_format=RGBA8&e_cspace=srgb&e_color=color(srgb,0.200,0.000,0.000) color_canvas.html?e_context=css&e_color=color(srgb,0.200,0.000,0.000)
|
||||
skip-if(cocoaWidget) == color_canvas.html?e_context=webgl&e_webgl_format=RGBA8&e_cspace=srgb&e_color=color(srgb,0.200,0.000,0.000) color_canvas.html?e_context=css&e_color=color(srgb,0.200,0.000,0.000)
|
||||
skip-if(!cocoaWidget) == color_canvas.html?e_context=webgl&e_webgl_format=RGBA8&e_cspace=srgb&e_color=color(srgb,0.000,0.200,0.000) color_canvas.html?e_context=css&e_color=color(srgb,0.000,0.200,0.000)
|
||||
skip-if(cocoaWidget) == color_canvas.html?e_context=webgl&e_webgl_format=RGBA8&e_cspace=srgb&e_color=color(srgb,0.000,0.200,0.000) color_canvas.html?e_context=css&e_color=color(srgb,0.000,0.200,0.000)
|
||||
### Generated, do not edit. ###
|
||||
skip-if(!cocoaWidget) == color_canvas.html?e_context=webgl&e_webgl_format=RGBA8&e_cspace=srgb&e_color=color(srgb,0.000,0.000,0.200) color_canvas.html?e_context=css&e_color=color(srgb,0.000,0.000,0.200)
|
||||
skip-if(cocoaWidget) == color_canvas.html?e_context=webgl&e_webgl_format=RGBA8&e_cspace=srgb&e_color=color(srgb,0.000,0.000,0.200) color_canvas.html?e_context=css&e_color=color(srgb,0.000,0.000,0.200)
|
||||
skip-if(!cocoaWidget) == color_canvas.html?e_context=webgl&e_webgl_format=RGBA8&e_cspace=srgb&e_color=color(srgb,0.502,0.502,0.502) color_canvas.html?e_context=css&e_color=color(srgb,0.502,0.502,0.502)
|
||||
skip-if(cocoaWidget) == color_canvas.html?e_context=webgl&e_webgl_format=RGBA8&e_cspace=srgb&e_color=color(srgb,0.502,0.502,0.502) color_canvas.html?e_context=css&e_color=color(srgb,0.502,0.502,0.502)
|
||||
skip-if(!cocoaWidget) == color_canvas.html?e_context=webgl&e_webgl_format=RGBA8&e_cspace=srgb&e_color=color(srgb,0.000,0.000,0.200) color_canvas.html?e_context=css&e_color=color(srgb,0.000,0.000,0.200)
|
||||
skip-if(cocoaWidget) == color_canvas.html?e_context=webgl&e_webgl_format=RGBA8&e_cspace=srgb&e_color=color(srgb,0.000,0.000,0.200) color_canvas.html?e_context=css&e_color=color(srgb,0.000,0.000,0.200)
|
||||
skip-if(!cocoaWidget) == color_canvas.html?e_context=webgl&e_webgl_format=RGBA8&e_cspace=srgb&e_color=color(srgb,0.502,0.502,0.502) color_canvas.html?e_context=css&e_color=color(srgb,0.502,0.502,0.502)
|
||||
skip-if(cocoaWidget) == color_canvas.html?e_context=webgl&e_webgl_format=RGBA8&e_cspace=srgb&e_color=color(srgb,0.502,0.502,0.502) color_canvas.html?e_context=css&e_color=color(srgb,0.502,0.502,0.502)
|
||||
### Generated, do not edit. ###
|
||||
skip-if(!cocoaWidget) == color_canvas.html?e_context=webgl&e_webgl_format=RGBA8&e_cspace=srgb&e_color=color(srgb,0.502,0.000,0.000) color_canvas.html?e_context=css&e_color=color(srgb,0.502,0.000,0.000)
|
||||
skip-if(cocoaWidget) == color_canvas.html?e_context=webgl&e_webgl_format=RGBA8&e_cspace=srgb&e_color=color(srgb,0.502,0.000,0.000) color_canvas.html?e_context=css&e_color=color(srgb,0.502,0.000,0.000)
|
||||
skip-if(!cocoaWidget) == color_canvas.html?e_context=webgl&e_webgl_format=RGBA8&e_cspace=srgb&e_color=color(srgb,0.000,0.502,0.000) color_canvas.html?e_context=css&e_color=color(srgb,0.000,0.502,0.000)
|
||||
skip-if(cocoaWidget) == color_canvas.html?e_context=webgl&e_webgl_format=RGBA8&e_cspace=srgb&e_color=color(srgb,0.000,0.502,0.000) color_canvas.html?e_context=css&e_color=color(srgb,0.000,0.502,0.000)
|
||||
skip-if(!cocoaWidget) == color_canvas.html?e_context=webgl&e_webgl_format=RGBA8&e_cspace=srgb&e_color=color(srgb,0.502,0.000,0.000) color_canvas.html?e_context=css&e_color=color(srgb,0.502,0.000,0.000)
|
||||
skip-if(cocoaWidget) == color_canvas.html?e_context=webgl&e_webgl_format=RGBA8&e_cspace=srgb&e_color=color(srgb,0.502,0.000,0.000) color_canvas.html?e_context=css&e_color=color(srgb,0.502,0.000,0.000)
|
||||
skip-if(!cocoaWidget) == color_canvas.html?e_context=webgl&e_webgl_format=RGBA8&e_cspace=srgb&e_color=color(srgb,0.000,0.502,0.000) color_canvas.html?e_context=css&e_color=color(srgb,0.000,0.502,0.000)
|
||||
skip-if(cocoaWidget) == color_canvas.html?e_context=webgl&e_webgl_format=RGBA8&e_cspace=srgb&e_color=color(srgb,0.000,0.502,0.000) color_canvas.html?e_context=css&e_color=color(srgb,0.000,0.502,0.000)
|
||||
### Generated, do not edit. ###
|
||||
skip-if(!cocoaWidget) == color_canvas.html?e_context=webgl&e_webgl_format=RGBA8&e_cspace=srgb&e_color=color(srgb,0.000,0.000,0.502) color_canvas.html?e_context=css&e_color=color(srgb,0.000,0.000,0.502)
|
||||
skip-if(cocoaWidget) == color_canvas.html?e_context=webgl&e_webgl_format=RGBA8&e_cspace=srgb&e_color=color(srgb,0.000,0.000,0.502) color_canvas.html?e_context=css&e_color=color(srgb,0.000,0.000,0.502)
|
||||
skip-if(!cocoaWidget) == color_canvas.html?e_context=webgl&e_webgl_format=RGBA8&e_cspace=srgb&e_color=color(srgb,1.000,1.000,1.000) color_canvas.html?e_context=css&e_color=color(srgb,1.000,1.000,1.000)
|
||||
skip-if(cocoaWidget) == color_canvas.html?e_context=webgl&e_webgl_format=RGBA8&e_cspace=srgb&e_color=color(srgb,1.000,1.000,1.000) color_canvas.html?e_context=css&e_color=color(srgb,1.000,1.000,1.000)
|
||||
skip-if(!cocoaWidget) == color_canvas.html?e_context=webgl&e_webgl_format=RGBA8&e_cspace=srgb&e_color=color(srgb,0.000,0.000,0.502) color_canvas.html?e_context=css&e_color=color(srgb,0.000,0.000,0.502)
|
||||
skip-if(cocoaWidget) == color_canvas.html?e_context=webgl&e_webgl_format=RGBA8&e_cspace=srgb&e_color=color(srgb,0.000,0.000,0.502) color_canvas.html?e_context=css&e_color=color(srgb,0.000,0.000,0.502)
|
||||
skip-if(!cocoaWidget) == color_canvas.html?e_context=webgl&e_webgl_format=RGBA8&e_cspace=srgb&e_color=color(srgb,1.000,1.000,1.000) color_canvas.html?e_context=css&e_color=color(srgb,1.000,1.000,1.000)
|
||||
skip-if(cocoaWidget) == color_canvas.html?e_context=webgl&e_webgl_format=RGBA8&e_cspace=srgb&e_color=color(srgb,1.000,1.000,1.000) color_canvas.html?e_context=css&e_color=color(srgb,1.000,1.000,1.000)
|
||||
### Generated, do not edit. ###
|
||||
skip-if(!cocoaWidget) == color_canvas.html?e_context=webgl&e_webgl_format=RGBA8&e_cspace=display-p3&e_color=color(srgb,0.000,0.000,0.000) color_canvas.html?e_context=css&e_color=color(display-p3,0.000,0.000,0.000)
|
||||
skip-if(cocoaWidget) == color_canvas.html?e_context=webgl&e_webgl_format=RGBA8&e_cspace=display-p3&e_color=color(srgb,0.000,0.000,0.000) color_canvas.html?e_context=css&e_color=color(display-p3,0.000,0.000,0.000)
|
||||
skip-if(!cocoaWidget) == color_canvas.html?e_context=webgl&e_webgl_format=RGBA8&e_cspace=display-p3&e_color=color(srgb,0.200,0.200,0.200) color_canvas.html?e_context=css&e_color=color(display-p3,0.200,0.200,0.200)
|
||||
skip-if(cocoaWidget) == color_canvas.html?e_context=webgl&e_webgl_format=RGBA8&e_cspace=display-p3&e_color=color(srgb,0.200,0.200,0.200) color_canvas.html?e_context=css&e_color=color(display-p3,0.200,0.200,0.200)
|
||||
skip-if(!cocoaWidget) == color_canvas.html?e_context=webgl&e_webgl_format=RGBA8&e_cspace=display-p3&e_color=color(srgb,0.000,0.000,0.000) color_canvas.html?e_context=css&e_color=color(display-p3,0.000,0.000,0.000)
|
||||
skip-if(cocoaWidget) == color_canvas.html?e_context=webgl&e_webgl_format=RGBA8&e_cspace=display-p3&e_color=color(srgb,0.000,0.000,0.000) color_canvas.html?e_context=css&e_color=color(display-p3,0.000,0.000,0.000)
|
||||
skip-if(!cocoaWidget) == color_canvas.html?e_context=webgl&e_webgl_format=RGBA8&e_cspace=display-p3&e_color=color(srgb,0.200,0.200,0.200) color_canvas.html?e_context=css&e_color=color(display-p3,0.200,0.200,0.200)
|
||||
skip-if(cocoaWidget) == color_canvas.html?e_context=webgl&e_webgl_format=RGBA8&e_cspace=display-p3&e_color=color(srgb,0.200,0.200,0.200) color_canvas.html?e_context=css&e_color=color(display-p3,0.200,0.200,0.200)
|
||||
### Generated, do not edit. ###
|
||||
skip-if(!cocoaWidget) == color_canvas.html?e_context=webgl&e_webgl_format=RGBA8&e_cspace=display-p3&e_color=color(srgb,0.200,0.000,0.000) color_canvas.html?e_context=css&e_color=color(display-p3,0.200,0.000,0.000)
|
||||
skip-if(cocoaWidget) fails == color_canvas.html?e_context=webgl&e_webgl_format=RGBA8&e_cspace=display-p3&e_color=color(srgb,0.200,0.000,0.000) color_canvas.html?e_context=css&e_color=color(display-p3,0.200,0.000,0.000)
|
||||
skip-if(cocoaWidget) == color_canvas.html?e_context=webgl&e_webgl_format=RGBA8&e_cspace=display-p3&e_color=color(srgb,0.200,0.000,0.000) color_canvas.html?e_context=css&e_color=color(srgb,0.200,0.000,0.000)
|
||||
skip-if(!cocoaWidget) == color_canvas.html?e_context=webgl&e_webgl_format=RGBA8&e_cspace=display-p3&e_color=color(srgb,0.000,0.200,0.000) color_canvas.html?e_context=css&e_color=color(display-p3,0.000,0.200,0.000)
|
||||
skip-if(!cocoaWidget) == color_canvas.html?e_context=webgl&e_webgl_format=RGBA8&e_cspace=display-p3&e_color=color(srgb,0.200,0.000,0.000) color_canvas.html?e_context=css&e_color=color(display-p3,0.200,0.000,0.000)
|
||||
skip-if(cocoaWidget) fails == color_canvas.html?e_context=webgl&e_webgl_format=RGBA8&e_cspace=display-p3&e_color=color(srgb,0.200,0.000,0.000) color_canvas.html?e_context=css&e_color=color(display-p3,0.200,0.000,0.000)
|
||||
skip-if(cocoaWidget) == color_canvas.html?e_context=webgl&e_webgl_format=RGBA8&e_cspace=display-p3&e_color=color(srgb,0.200,0.000,0.000) color_canvas.html?e_context=css&e_color=color(srgb,0.200,0.000,0.000)
|
||||
skip-if(!cocoaWidget) == color_canvas.html?e_context=webgl&e_webgl_format=RGBA8&e_cspace=display-p3&e_color=color(srgb,0.000,0.200,0.000) color_canvas.html?e_context=css&e_color=color(display-p3,0.000,0.200,0.000)
|
||||
### Generated, do not edit. ###
|
||||
skip-if(cocoaWidget) fails-if(!Android) == color_canvas.html?e_context=webgl&e_webgl_format=RGBA8&e_cspace=display-p3&e_color=color(srgb,0.000,0.200,0.000) color_canvas.html?e_context=css&e_color=color(display-p3,0.000,0.200,0.000)
|
||||
skip-if(cocoaWidget) == color_canvas.html?e_context=webgl&e_webgl_format=RGBA8&e_cspace=display-p3&e_color=color(srgb,0.000,0.200,0.000) color_canvas.html?e_context=css&e_color=color(srgb,0.000,0.200,0.000)
|
||||
skip-if(!cocoaWidget) == color_canvas.html?e_context=webgl&e_webgl_format=RGBA8&e_cspace=display-p3&e_color=color(srgb,0.000,0.000,0.200) color_canvas.html?e_context=css&e_color=color(display-p3,0.000,0.000,0.200)
|
||||
skip-if(cocoaWidget) fails == color_canvas.html?e_context=webgl&e_webgl_format=RGBA8&e_cspace=display-p3&e_color=color(srgb,0.000,0.000,0.200) color_canvas.html?e_context=css&e_color=color(display-p3,0.000,0.000,0.200)
|
||||
skip-if(cocoaWidget) fails-if(!Android) == color_canvas.html?e_context=webgl&e_webgl_format=RGBA8&e_cspace=display-p3&e_color=color(srgb,0.000,0.200,0.000) color_canvas.html?e_context=css&e_color=color(display-p3,0.000,0.200,0.000)
|
||||
skip-if(cocoaWidget) == color_canvas.html?e_context=webgl&e_webgl_format=RGBA8&e_cspace=display-p3&e_color=color(srgb,0.000,0.200,0.000) color_canvas.html?e_context=css&e_color=color(srgb,0.000,0.200,0.000)
|
||||
skip-if(!cocoaWidget) == color_canvas.html?e_context=webgl&e_webgl_format=RGBA8&e_cspace=display-p3&e_color=color(srgb,0.000,0.000,0.200) color_canvas.html?e_context=css&e_color=color(display-p3,0.000,0.000,0.200)
|
||||
skip-if(cocoaWidget) fails == color_canvas.html?e_context=webgl&e_webgl_format=RGBA8&e_cspace=display-p3&e_color=color(srgb,0.000,0.000,0.200) color_canvas.html?e_context=css&e_color=color(display-p3,0.000,0.000,0.200)
|
||||
### Generated, do not edit. ###
|
||||
skip-if(cocoaWidget) == color_canvas.html?e_context=webgl&e_webgl_format=RGBA8&e_cspace=display-p3&e_color=color(srgb,0.000,0.000,0.200) color_canvas.html?e_context=css&e_color=color(srgb,0.000,0.000,0.200)
|
||||
skip-if(!cocoaWidget) == color_canvas.html?e_context=webgl&e_webgl_format=RGBA8&e_cspace=display-p3&e_color=color(srgb,0.502,0.502,0.502) color_canvas.html?e_context=css&e_color=color(display-p3,0.502,0.502,0.502)
|
||||
skip-if(cocoaWidget) == color_canvas.html?e_context=webgl&e_webgl_format=RGBA8&e_cspace=display-p3&e_color=color(srgb,0.502,0.502,0.502) color_canvas.html?e_context=css&e_color=color(display-p3,0.502,0.502,0.502)
|
||||
skip-if(!cocoaWidget) == color_canvas.html?e_context=webgl&e_webgl_format=RGBA8&e_cspace=display-p3&e_color=color(srgb,0.502,0.000,0.000) color_canvas.html?e_context=css&e_color=color(display-p3,0.502,0.000,0.000)
|
||||
skip-if(cocoaWidget) == color_canvas.html?e_context=webgl&e_webgl_format=RGBA8&e_cspace=display-p3&e_color=color(srgb,0.000,0.000,0.200) color_canvas.html?e_context=css&e_color=color(srgb,0.000,0.000,0.200)
|
||||
skip-if(!cocoaWidget) == color_canvas.html?e_context=webgl&e_webgl_format=RGBA8&e_cspace=display-p3&e_color=color(srgb,0.502,0.502,0.502) color_canvas.html?e_context=css&e_color=color(display-p3,0.502,0.502,0.502)
|
||||
skip-if(cocoaWidget) == color_canvas.html?e_context=webgl&e_webgl_format=RGBA8&e_cspace=display-p3&e_color=color(srgb,0.502,0.502,0.502) color_canvas.html?e_context=css&e_color=color(display-p3,0.502,0.502,0.502)
|
||||
skip-if(!cocoaWidget) fuzzy(0-1,0-10000) == color_canvas.html?e_context=webgl&e_webgl_format=RGBA8&e_cspace=display-p3&e_color=color(srgb,0.502,0.000,0.000) color_canvas.html?e_context=css&e_color=color(display-p3,0.502,0.000,0.000)
|
||||
### Generated, do not edit. ###
|
||||
skip-if(cocoaWidget) fails == color_canvas.html?e_context=webgl&e_webgl_format=RGBA8&e_cspace=display-p3&e_color=color(srgb,0.502,0.000,0.000) color_canvas.html?e_context=css&e_color=color(display-p3,0.502,0.000,0.000)
|
||||
skip-if(cocoaWidget) == color_canvas.html?e_context=webgl&e_webgl_format=RGBA8&e_cspace=display-p3&e_color=color(srgb,0.502,0.000,0.000) color_canvas.html?e_context=css&e_color=color(srgb,0.502,0.000,0.000)
|
||||
skip-if(!cocoaWidget) == color_canvas.html?e_context=webgl&e_webgl_format=RGBA8&e_cspace=display-p3&e_color=color(srgb,0.000,0.502,0.000) color_canvas.html?e_context=css&e_color=color(display-p3,0.000,0.502,0.000)
|
||||
skip-if(cocoaWidget) fails-if(!Android) == color_canvas.html?e_context=webgl&e_webgl_format=RGBA8&e_cspace=display-p3&e_color=color(srgb,0.000,0.502,0.000) color_canvas.html?e_context=css&e_color=color(display-p3,0.000,0.502,0.000)
|
||||
skip-if(cocoaWidget) fuzzy(0-1,0-10000) fails == color_canvas.html?e_context=webgl&e_webgl_format=RGBA8&e_cspace=display-p3&e_color=color(srgb,0.502,0.000,0.000) color_canvas.html?e_context=css&e_color=color(display-p3,0.502,0.000,0.000)
|
||||
skip-if(cocoaWidget) fuzzy(0-1,0-10000) == color_canvas.html?e_context=webgl&e_webgl_format=RGBA8&e_cspace=display-p3&e_color=color(srgb,0.502,0.000,0.000) color_canvas.html?e_context=css&e_color=color(srgb,0.502,0.000,0.000)
|
||||
skip-if(!cocoaWidget) == color_canvas.html?e_context=webgl&e_webgl_format=RGBA8&e_cspace=display-p3&e_color=color(srgb,0.000,0.502,0.000) color_canvas.html?e_context=css&e_color=color(display-p3,0.000,0.502,0.000)
|
||||
skip-if(cocoaWidget) fails-if(!Android) == color_canvas.html?e_context=webgl&e_webgl_format=RGBA8&e_cspace=display-p3&e_color=color(srgb,0.000,0.502,0.000) color_canvas.html?e_context=css&e_color=color(display-p3,0.000,0.502,0.000)
|
||||
### Generated, do not edit. ###
|
||||
skip-if(cocoaWidget) == color_canvas.html?e_context=webgl&e_webgl_format=RGBA8&e_cspace=display-p3&e_color=color(srgb,0.000,0.502,0.000) color_canvas.html?e_context=css&e_color=color(srgb,0.000,0.502,0.000)
|
||||
skip-if(!cocoaWidget) == color_canvas.html?e_context=webgl&e_webgl_format=RGBA8&e_cspace=display-p3&e_color=color(srgb,0.000,0.000,0.502) color_canvas.html?e_context=css&e_color=color(display-p3,0.000,0.000,0.502)
|
||||
skip-if(cocoaWidget) fails == color_canvas.html?e_context=webgl&e_webgl_format=RGBA8&e_cspace=display-p3&e_color=color(srgb,0.000,0.000,0.502) color_canvas.html?e_context=css&e_color=color(display-p3,0.000,0.000,0.502)
|
||||
skip-if(cocoaWidget) == color_canvas.html?e_context=webgl&e_webgl_format=RGBA8&e_cspace=display-p3&e_color=color(srgb,0.000,0.000,0.502) color_canvas.html?e_context=css&e_color=color(srgb,0.000,0.000,0.502)
|
||||
skip-if(cocoaWidget) == color_canvas.html?e_context=webgl&e_webgl_format=RGBA8&e_cspace=display-p3&e_color=color(srgb,0.000,0.502,0.000) color_canvas.html?e_context=css&e_color=color(srgb,0.000,0.502,0.000)
|
||||
skip-if(!cocoaWidget) == color_canvas.html?e_context=webgl&e_webgl_format=RGBA8&e_cspace=display-p3&e_color=color(srgb,0.000,0.000,0.502) color_canvas.html?e_context=css&e_color=color(display-p3,0.000,0.000,0.502)
|
||||
skip-if(cocoaWidget) fails == color_canvas.html?e_context=webgl&e_webgl_format=RGBA8&e_cspace=display-p3&e_color=color(srgb,0.000,0.000,0.502) color_canvas.html?e_context=css&e_color=color(display-p3,0.000,0.000,0.502)
|
||||
skip-if(cocoaWidget) == color_canvas.html?e_context=webgl&e_webgl_format=RGBA8&e_cspace=display-p3&e_color=color(srgb,0.000,0.000,0.502) color_canvas.html?e_context=css&e_color=color(srgb,0.000,0.000,0.502)
|
||||
### Generated, do not edit. ###
|
||||
skip-if(!cocoaWidget) == color_canvas.html?e_context=webgl&e_webgl_format=RGBA8&e_cspace=display-p3&e_color=color(srgb,1.000,1.000,1.000) color_canvas.html?e_context=css&e_color=color(display-p3,1.000,1.000,1.000)
|
||||
skip-if(cocoaWidget) == color_canvas.html?e_context=webgl&e_webgl_format=RGBA8&e_cspace=display-p3&e_color=color(srgb,1.000,1.000,1.000) color_canvas.html?e_context=css&e_color=color(display-p3,1.000,1.000,1.000)
|
||||
== color_canvas.html?e_context=2d&e_options={"willReadFrequently":"true"}&e_cspace=srgb&e_color=color(srgb,0.000,0.000,0.000) color_canvas.html?e_context=css&e_color=color(srgb,0.000,0.000,0.000)
|
||||
== color_canvas.html?e_context=2d&e_options={"willReadFrequently":"true"}&e_cspace=srgb&e_color=color(srgb,0.200,0.200,0.200) color_canvas.html?e_context=css&e_color=color(srgb,0.200,0.200,0.200)
|
||||
skip-if(!cocoaWidget) == color_canvas.html?e_context=webgl&e_webgl_format=RGBA8&e_cspace=display-p3&e_color=color(srgb,1.000,1.000,1.000) color_canvas.html?e_context=css&e_color=color(display-p3,1.000,1.000,1.000)
|
||||
skip-if(cocoaWidget) == color_canvas.html?e_context=webgl&e_webgl_format=RGBA8&e_cspace=display-p3&e_color=color(srgb,1.000,1.000,1.000) color_canvas.html?e_context=css&e_color=color(display-p3,1.000,1.000,1.000)
|
||||
skip-if(!cocoaWidget&&!winWidget) == color_canvas.html?e_context=webgl2&e_webgl_format=RGBA8&e_cspace=srgb&e_color=color(srgb,0.000,0.000,0.000) color_canvas.html?e_context=css&e_color=color(srgb,0.000,0.000,0.000)
|
||||
skip-if(cocoaWidget||winWidget) == color_canvas.html?e_context=webgl2&e_webgl_format=RGBA8&e_cspace=srgb&e_color=color(srgb,0.000,0.000,0.000) color_canvas.html?e_context=css&e_color=color(srgb,0.000,0.000,0.000)
|
||||
### Generated, do not edit. ###
|
||||
== color_canvas.html?e_context=2d&e_options={"willReadFrequently":"true"}&e_cspace=srgb&e_color=color(srgb,0.200,0.000,0.000) color_canvas.html?e_context=css&e_color=color(srgb,0.200,0.000,0.000)
|
||||
== color_canvas.html?e_context=2d&e_options={"willReadFrequently":"true"}&e_cspace=srgb&e_color=color(srgb,0.000,0.200,0.000) color_canvas.html?e_context=css&e_color=color(srgb,0.000,0.200,0.000)
|
||||
== color_canvas.html?e_context=2d&e_options={"willReadFrequently":"true"}&e_cspace=srgb&e_color=color(srgb,0.000,0.000,0.200) color_canvas.html?e_context=css&e_color=color(srgb,0.000,0.000,0.200)
|
||||
== color_canvas.html?e_context=2d&e_options={"willReadFrequently":"true"}&e_cspace=srgb&e_color=color(srgb,0.502,0.502,0.502) color_canvas.html?e_context=css&e_color=color(srgb,0.502,0.502,0.502)
|
||||
skip-if(!cocoaWidget&&!winWidget) == color_canvas.html?e_context=webgl2&e_webgl_format=RGBA8&e_cspace=srgb&e_color=color(srgb,0.200,0.200,0.200) color_canvas.html?e_context=css&e_color=color(srgb,0.200,0.200,0.200)
|
||||
skip-if(cocoaWidget||winWidget) == color_canvas.html?e_context=webgl2&e_webgl_format=RGBA8&e_cspace=srgb&e_color=color(srgb,0.200,0.200,0.200) color_canvas.html?e_context=css&e_color=color(srgb,0.200,0.200,0.200)
|
||||
skip-if(!cocoaWidget&&!winWidget) == color_canvas.html?e_context=webgl2&e_webgl_format=RGBA8&e_cspace=srgb&e_color=color(srgb,0.200,0.000,0.000) color_canvas.html?e_context=css&e_color=color(srgb,0.200,0.000,0.000)
|
||||
skip-if(cocoaWidget||winWidget) == color_canvas.html?e_context=webgl2&e_webgl_format=RGBA8&e_cspace=srgb&e_color=color(srgb,0.200,0.000,0.000) color_canvas.html?e_context=css&e_color=color(srgb,0.200,0.000,0.000)
|
||||
### Generated, do not edit. ###
|
||||
== color_canvas.html?e_context=2d&e_options={"willReadFrequently":"true"}&e_cspace=srgb&e_color=color(srgb,0.502,0.000,0.000) color_canvas.html?e_context=css&e_color=color(srgb,0.502,0.000,0.000)
|
||||
== color_canvas.html?e_context=2d&e_options={"willReadFrequently":"true"}&e_cspace=srgb&e_color=color(srgb,0.000,0.502,0.000) color_canvas.html?e_context=css&e_color=color(srgb,0.000,0.502,0.000)
|
||||
== color_canvas.html?e_context=2d&e_options={"willReadFrequently":"true"}&e_cspace=srgb&e_color=color(srgb,0.000,0.000,0.502) color_canvas.html?e_context=css&e_color=color(srgb,0.000,0.000,0.502)
|
||||
== color_canvas.html?e_context=2d&e_options={"willReadFrequently":"true"}&e_cspace=srgb&e_color=color(srgb,1.000,1.000,1.000) color_canvas.html?e_context=css&e_color=color(srgb,1.000,1.000,1.000)
|
||||
skip-if(!cocoaWidget&&!winWidget) == color_canvas.html?e_context=webgl2&e_webgl_format=RGBA8&e_cspace=srgb&e_color=color(srgb,0.000,0.200,0.000) color_canvas.html?e_context=css&e_color=color(srgb,0.000,0.200,0.000)
|
||||
skip-if(cocoaWidget||winWidget) == color_canvas.html?e_context=webgl2&e_webgl_format=RGBA8&e_cspace=srgb&e_color=color(srgb,0.000,0.200,0.000) color_canvas.html?e_context=css&e_color=color(srgb,0.000,0.200,0.000)
|
||||
skip-if(!cocoaWidget&&!winWidget) == color_canvas.html?e_context=webgl2&e_webgl_format=RGBA8&e_cspace=srgb&e_color=color(srgb,0.000,0.000,0.200) color_canvas.html?e_context=css&e_color=color(srgb,0.000,0.000,0.200)
|
||||
skip-if(cocoaWidget||winWidget) == color_canvas.html?e_context=webgl2&e_webgl_format=RGBA8&e_cspace=srgb&e_color=color(srgb,0.000,0.000,0.200) color_canvas.html?e_context=css&e_color=color(srgb,0.000,0.000,0.200)
|
||||
### Generated, do not edit. ###
|
||||
== color_canvas.html?e_context=2d&e_options={"willReadFrequently":"true"}&e_cspace=srgb&e_color=color(display-p3,0.000,0.000,0.000) color_canvas.html?e_context=css&e_color=color(display-p3,0.000,0.000,0.000)
|
||||
== color_canvas.html?e_context=2d&e_options={"willReadFrequently":"true"}&e_cspace=srgb&e_color=color(display-p3,0.200,0.200,0.200) color_canvas.html?e_context=css&e_color=color(display-p3,0.200,0.200,0.200)
|
||||
== color_canvas.html?e_context=2d&e_options={"willReadFrequently":"true"}&e_cspace=srgb&e_color=color(display-p3,0.200,0.000,0.000) color_canvas.html?e_context=css&e_color=color(display-p3,0.200,0.000,0.000)
|
||||
== color_canvas.html?e_context=2d&e_options={"willReadFrequently":"true"}&e_cspace=srgb&e_color=color(display-p3,0.000,0.200,0.000) color_canvas.html?e_context=css&e_color=color(display-p3,0.000,0.200,0.000)
|
||||
skip-if(!cocoaWidget&&!winWidget) == color_canvas.html?e_context=webgl2&e_webgl_format=RGBA8&e_cspace=srgb&e_color=color(srgb,0.502,0.502,0.502) color_canvas.html?e_context=css&e_color=color(srgb,0.502,0.502,0.502)
|
||||
skip-if(cocoaWidget||winWidget) == color_canvas.html?e_context=webgl2&e_webgl_format=RGBA8&e_cspace=srgb&e_color=color(srgb,0.502,0.502,0.502) color_canvas.html?e_context=css&e_color=color(srgb,0.502,0.502,0.502)
|
||||
skip-if(!cocoaWidget&&!winWidget) == color_canvas.html?e_context=webgl2&e_webgl_format=RGBA8&e_cspace=srgb&e_color=color(srgb,0.502,0.000,0.000) color_canvas.html?e_context=css&e_color=color(srgb,0.502,0.000,0.000)
|
||||
skip-if(cocoaWidget||winWidget) == color_canvas.html?e_context=webgl2&e_webgl_format=RGBA8&e_cspace=srgb&e_color=color(srgb,0.502,0.000,0.000) color_canvas.html?e_context=css&e_color=color(srgb,0.502,0.000,0.000)
|
||||
### Generated, do not edit. ###
|
||||
== color_canvas.html?e_context=2d&e_options={"willReadFrequently":"true"}&e_cspace=srgb&e_color=color(display-p3,0.000,0.000,0.200) color_canvas.html?e_context=css&e_color=color(display-p3,0.000,0.000,0.200)
|
||||
== color_canvas.html?e_context=2d&e_options={"willReadFrequently":"true"}&e_cspace=srgb&e_color=color(display-p3,0.502,0.502,0.502) color_canvas.html?e_context=css&e_color=color(display-p3,0.502,0.502,0.502)
|
||||
== color_canvas.html?e_context=2d&e_options={"willReadFrequently":"true"}&e_cspace=srgb&e_color=color(display-p3,0.502,0.000,0.000) color_canvas.html?e_context=css&e_color=color(display-p3,0.502,0.000,0.000)
|
||||
== color_canvas.html?e_context=2d&e_options={"willReadFrequently":"true"}&e_cspace=srgb&e_color=color(display-p3,0.000,0.502,0.000) color_canvas.html?e_context=css&e_color=color(display-p3,0.000,0.502,0.000)
|
||||
skip-if(!cocoaWidget&&!winWidget) == color_canvas.html?e_context=webgl2&e_webgl_format=RGBA8&e_cspace=srgb&e_color=color(srgb,0.000,0.502,0.000) color_canvas.html?e_context=css&e_color=color(srgb,0.000,0.502,0.000)
|
||||
skip-if(cocoaWidget||winWidget) == color_canvas.html?e_context=webgl2&e_webgl_format=RGBA8&e_cspace=srgb&e_color=color(srgb,0.000,0.502,0.000) color_canvas.html?e_context=css&e_color=color(srgb,0.000,0.502,0.000)
|
||||
skip-if(!cocoaWidget&&!winWidget) == color_canvas.html?e_context=webgl2&e_webgl_format=RGBA8&e_cspace=srgb&e_color=color(srgb,0.000,0.000,0.502) color_canvas.html?e_context=css&e_color=color(srgb,0.000,0.000,0.502)
|
||||
skip-if(cocoaWidget||winWidget) == color_canvas.html?e_context=webgl2&e_webgl_format=RGBA8&e_cspace=srgb&e_color=color(srgb,0.000,0.000,0.502) color_canvas.html?e_context=css&e_color=color(srgb,0.000,0.000,0.502)
|
||||
### Generated, do not edit. ###
|
||||
== color_canvas.html?e_context=2d&e_options={"willReadFrequently":"true"}&e_cspace=srgb&e_color=color(display-p3,0.000,0.000,0.502) color_canvas.html?e_context=css&e_color=color(display-p3,0.000,0.000,0.502)
|
||||
== color_canvas.html?e_context=2d&e_options={"willReadFrequently":"true"}&e_cspace=srgb&e_color=color(display-p3,1.000,1.000,1.000) color_canvas.html?e_context=css&e_color=color(display-p3,1.000,1.000,1.000)
|
||||
== color_canvas.html?e_context=2d&e_options={"willReadFrequently":"true"}&e_cspace=display-p3&e_color=color(srgb,0.000,0.000,0.000) color_canvas.html?e_context=css&e_color=color(srgb,0.000,0.000,0.000)
|
||||
== color_canvas.html?e_context=2d&e_options={"willReadFrequently":"true"}&e_cspace=display-p3&e_color=color(srgb,0.200,0.200,0.200) color_canvas.html?e_context=css&e_color=color(srgb,0.200,0.200,0.200)
|
||||
skip-if(!cocoaWidget&&!winWidget) == color_canvas.html?e_context=webgl2&e_webgl_format=RGBA8&e_cspace=srgb&e_color=color(srgb,1.000,1.000,1.000) color_canvas.html?e_context=css&e_color=color(srgb,1.000,1.000,1.000)
|
||||
skip-if(cocoaWidget||winWidget) == color_canvas.html?e_context=webgl2&e_webgl_format=RGBA8&e_cspace=srgb&e_color=color(srgb,1.000,1.000,1.000) color_canvas.html?e_context=css&e_color=color(srgb,1.000,1.000,1.000)
|
||||
skip-if(!cocoaWidget&&!winWidget) == color_canvas.html?e_context=webgl2&e_webgl_format=RGBA8&e_cspace=display-p3&e_color=color(srgb,0.000,0.000,0.000) color_canvas.html?e_context=css&e_color=color(display-p3,0.000,0.000,0.000)
|
||||
skip-if(cocoaWidget||winWidget) == color_canvas.html?e_context=webgl2&e_webgl_format=RGBA8&e_cspace=display-p3&e_color=color(srgb,0.000,0.000,0.000) color_canvas.html?e_context=css&e_color=color(display-p3,0.000,0.000,0.000)
|
||||
### Generated, do not edit. ###
|
||||
== color_canvas.html?e_context=2d&e_options={"willReadFrequently":"true"}&e_cspace=display-p3&e_color=color(srgb,0.200,0.000,0.000) color_canvas.html?e_context=css&e_color=color(srgb,0.200,0.000,0.000)
|
||||
== color_canvas.html?e_context=2d&e_options={"willReadFrequently":"true"}&e_cspace=display-p3&e_color=color(srgb,0.000,0.200,0.000) color_canvas.html?e_context=css&e_color=color(srgb,0.000,0.200,0.000)
|
||||
== color_canvas.html?e_context=2d&e_options={"willReadFrequently":"true"}&e_cspace=display-p3&e_color=color(srgb,0.000,0.000,0.200) color_canvas.html?e_context=css&e_color=color(srgb,0.000,0.000,0.200)
|
||||
== color_canvas.html?e_context=2d&e_options={"willReadFrequently":"true"}&e_cspace=display-p3&e_color=color(srgb,0.502,0.502,0.502) color_canvas.html?e_context=css&e_color=color(srgb,0.502,0.502,0.502)
|
||||
skip-if(!cocoaWidget&&!winWidget) == color_canvas.html?e_context=webgl2&e_webgl_format=RGBA8&e_cspace=display-p3&e_color=color(srgb,0.200,0.200,0.200) color_canvas.html?e_context=css&e_color=color(display-p3,0.200,0.200,0.200)
|
||||
skip-if(cocoaWidget||winWidget) == color_canvas.html?e_context=webgl2&e_webgl_format=RGBA8&e_cspace=display-p3&e_color=color(srgb,0.200,0.200,0.200) color_canvas.html?e_context=css&e_color=color(display-p3,0.200,0.200,0.200)
|
||||
skip-if(!cocoaWidget&&!winWidget) == color_canvas.html?e_context=webgl2&e_webgl_format=RGBA8&e_cspace=display-p3&e_color=color(srgb,0.200,0.000,0.000) color_canvas.html?e_context=css&e_color=color(display-p3,0.200,0.000,0.000)
|
||||
skip-if(cocoaWidget||winWidget) fails == color_canvas.html?e_context=webgl2&e_webgl_format=RGBA8&e_cspace=display-p3&e_color=color(srgb,0.200,0.000,0.000) color_canvas.html?e_context=css&e_color=color(display-p3,0.200,0.000,0.000)
|
||||
### Generated, do not edit. ###
|
||||
== color_canvas.html?e_context=2d&e_options={"willReadFrequently":"true"}&e_cspace=display-p3&e_color=color(srgb,0.502,0.000,0.000) color_canvas.html?e_context=css&e_color=color(srgb,0.502,0.000,0.000)
|
||||
== color_canvas.html?e_context=2d&e_options={"willReadFrequently":"true"}&e_cspace=display-p3&e_color=color(srgb,0.000,0.502,0.000) color_canvas.html?e_context=css&e_color=color(srgb,0.000,0.502,0.000)
|
||||
== color_canvas.html?e_context=2d&e_options={"willReadFrequently":"true"}&e_cspace=display-p3&e_color=color(srgb,0.000,0.000,0.502) color_canvas.html?e_context=css&e_color=color(srgb,0.000,0.000,0.502)
|
||||
== color_canvas.html?e_context=2d&e_options={"willReadFrequently":"true"}&e_cspace=display-p3&e_color=color(srgb,1.000,1.000,1.000) color_canvas.html?e_context=css&e_color=color(srgb,1.000,1.000,1.000)
|
||||
skip-if(cocoaWidget||winWidget) == color_canvas.html?e_context=webgl2&e_webgl_format=RGBA8&e_cspace=display-p3&e_color=color(srgb,0.200,0.000,0.000) color_canvas.html?e_context=css&e_color=color(srgb,0.200,0.000,0.000)
|
||||
skip-if(!cocoaWidget&&!winWidget) == color_canvas.html?e_context=webgl2&e_webgl_format=RGBA8&e_cspace=display-p3&e_color=color(srgb,0.000,0.200,0.000) color_canvas.html?e_context=css&e_color=color(display-p3,0.000,0.200,0.000)
|
||||
skip-if(cocoaWidget||winWidget) fails-if(!Android) == color_canvas.html?e_context=webgl2&e_webgl_format=RGBA8&e_cspace=display-p3&e_color=color(srgb,0.000,0.200,0.000) color_canvas.html?e_context=css&e_color=color(display-p3,0.000,0.200,0.000)
|
||||
skip-if(cocoaWidget||winWidget) == color_canvas.html?e_context=webgl2&e_webgl_format=RGBA8&e_cspace=display-p3&e_color=color(srgb,0.000,0.200,0.000) color_canvas.html?e_context=css&e_color=color(srgb,0.000,0.200,0.000)
|
||||
### Generated, do not edit. ###
|
||||
== color_canvas.html?e_context=2d&e_options={"willReadFrequently":"true"}&e_cspace=display-p3&e_color=color(display-p3,0.000,0.000,0.000) color_canvas.html?e_context=css&e_color=color(display-p3,0.000,0.000,0.000)
|
||||
== color_canvas.html?e_context=2d&e_options={"willReadFrequently":"true"}&e_cspace=display-p3&e_color=color(display-p3,0.200,0.200,0.200) color_canvas.html?e_context=css&e_color=color(display-p3,0.200,0.200,0.200)
|
||||
== color_canvas.html?e_context=2d&e_options={"willReadFrequently":"true"}&e_cspace=display-p3&e_color=color(display-p3,0.200,0.000,0.000) color_canvas.html?e_context=css&e_color=color(display-p3,0.200,0.000,0.000)
|
||||
== color_canvas.html?e_context=2d&e_options={"willReadFrequently":"true"}&e_cspace=display-p3&e_color=color(display-p3,0.000,0.200,0.000) color_canvas.html?e_context=css&e_color=color(display-p3,0.000,0.200,0.000)
|
||||
skip-if(!cocoaWidget&&!winWidget) == color_canvas.html?e_context=webgl2&e_webgl_format=RGBA8&e_cspace=display-p3&e_color=color(srgb,0.000,0.000,0.200) color_canvas.html?e_context=css&e_color=color(display-p3,0.000,0.000,0.200)
|
||||
skip-if(cocoaWidget||winWidget) fails == color_canvas.html?e_context=webgl2&e_webgl_format=RGBA8&e_cspace=display-p3&e_color=color(srgb,0.000,0.000,0.200) color_canvas.html?e_context=css&e_color=color(display-p3,0.000,0.000,0.200)
|
||||
skip-if(cocoaWidget||winWidget) == color_canvas.html?e_context=webgl2&e_webgl_format=RGBA8&e_cspace=display-p3&e_color=color(srgb,0.000,0.000,0.200) color_canvas.html?e_context=css&e_color=color(srgb,0.000,0.000,0.200)
|
||||
skip-if(!cocoaWidget&&!winWidget) == color_canvas.html?e_context=webgl2&e_webgl_format=RGBA8&e_cspace=display-p3&e_color=color(srgb,0.502,0.502,0.502) color_canvas.html?e_context=css&e_color=color(display-p3,0.502,0.502,0.502)
|
||||
### Generated, do not edit. ###
|
||||
== color_canvas.html?e_context=2d&e_options={"willReadFrequently":"true"}&e_cspace=display-p3&e_color=color(display-p3,0.000,0.000,0.200) color_canvas.html?e_context=css&e_color=color(display-p3,0.000,0.000,0.200)
|
||||
== color_canvas.html?e_context=2d&e_options={"willReadFrequently":"true"}&e_cspace=display-p3&e_color=color(display-p3,0.502,0.502,0.502) color_canvas.html?e_context=css&e_color=color(display-p3,0.502,0.502,0.502)
|
||||
== color_canvas.html?e_context=2d&e_options={"willReadFrequently":"true"}&e_cspace=display-p3&e_color=color(display-p3,0.502,0.000,0.000) color_canvas.html?e_context=css&e_color=color(display-p3,0.502,0.000,0.000)
|
||||
== color_canvas.html?e_context=2d&e_options={"willReadFrequently":"true"}&e_cspace=display-p3&e_color=color(display-p3,0.000,0.502,0.000) color_canvas.html?e_context=css&e_color=color(display-p3,0.000,0.502,0.000)
|
||||
skip-if(cocoaWidget||winWidget) == color_canvas.html?e_context=webgl2&e_webgl_format=RGBA8&e_cspace=display-p3&e_color=color(srgb,0.502,0.502,0.502) color_canvas.html?e_context=css&e_color=color(display-p3,0.502,0.502,0.502)
|
||||
skip-if(!cocoaWidget&&!winWidget) fuzzy(0-1,0-10000) == color_canvas.html?e_context=webgl2&e_webgl_format=RGBA8&e_cspace=display-p3&e_color=color(srgb,0.502,0.000,0.000) color_canvas.html?e_context=css&e_color=color(display-p3,0.502,0.000,0.000)
|
||||
skip-if(cocoaWidget||winWidget) fuzzy(0-1,0-10000) fails == color_canvas.html?e_context=webgl2&e_webgl_format=RGBA8&e_cspace=display-p3&e_color=color(srgb,0.502,0.000,0.000) color_canvas.html?e_context=css&e_color=color(display-p3,0.502,0.000,0.000)
|
||||
skip-if(cocoaWidget||winWidget) fuzzy(0-1,0-10000) == color_canvas.html?e_context=webgl2&e_webgl_format=RGBA8&e_cspace=display-p3&e_color=color(srgb,0.502,0.000,0.000) color_canvas.html?e_context=css&e_color=color(srgb,0.502,0.000,0.000)
|
||||
### Generated, do not edit. ###
|
||||
== color_canvas.html?e_context=2d&e_options={"willReadFrequently":"true"}&e_cspace=display-p3&e_color=color(display-p3,0.000,0.000,0.502) color_canvas.html?e_context=css&e_color=color(display-p3,0.000,0.000,0.502)
|
||||
== color_canvas.html?e_context=2d&e_options={"willReadFrequently":"true"}&e_cspace=display-p3&e_color=color(display-p3,1.000,1.000,1.000) color_canvas.html?e_context=css&e_color=color(display-p3,1.000,1.000,1.000)
|
||||
== color_canvas.html?e_context=2d&e_options={"willReadFrequently":"false"}&e_cspace=srgb&e_color=color(srgb,0.000,0.000,0.000) color_canvas.html?e_context=css&e_color=color(srgb,0.000,0.000,0.000)
|
||||
== color_canvas.html?e_context=2d&e_options={"willReadFrequently":"false"}&e_cspace=srgb&e_color=color(srgb,0.200,0.200,0.200) color_canvas.html?e_context=css&e_color=color(srgb,0.200,0.200,0.200)
|
||||
skip-if(!cocoaWidget&&!winWidget) == color_canvas.html?e_context=webgl2&e_webgl_format=RGBA8&e_cspace=display-p3&e_color=color(srgb,0.000,0.502,0.000) color_canvas.html?e_context=css&e_color=color(display-p3,0.000,0.502,0.000)
|
||||
skip-if(cocoaWidget||winWidget) fails-if(!Android) == color_canvas.html?e_context=webgl2&e_webgl_format=RGBA8&e_cspace=display-p3&e_color=color(srgb,0.000,0.502,0.000) color_canvas.html?e_context=css&e_color=color(display-p3,0.000,0.502,0.000)
|
||||
skip-if(cocoaWidget||winWidget) == color_canvas.html?e_context=webgl2&e_webgl_format=RGBA8&e_cspace=display-p3&e_color=color(srgb,0.000,0.502,0.000) color_canvas.html?e_context=css&e_color=color(srgb,0.000,0.502,0.000)
|
||||
skip-if(!cocoaWidget&&!winWidget) == color_canvas.html?e_context=webgl2&e_webgl_format=RGBA8&e_cspace=display-p3&e_color=color(srgb,0.000,0.000,0.502) color_canvas.html?e_context=css&e_color=color(display-p3,0.000,0.000,0.502)
|
||||
### Generated, do not edit. ###
|
||||
== color_canvas.html?e_context=2d&e_options={"willReadFrequently":"false"}&e_cspace=srgb&e_color=color(srgb,0.200,0.000,0.000) color_canvas.html?e_context=css&e_color=color(srgb,0.200,0.000,0.000)
|
||||
== color_canvas.html?e_context=2d&e_options={"willReadFrequently":"false"}&e_cspace=srgb&e_color=color(srgb,0.000,0.200,0.000) color_canvas.html?e_context=css&e_color=color(srgb,0.000,0.200,0.000)
|
||||
== color_canvas.html?e_context=2d&e_options={"willReadFrequently":"false"}&e_cspace=srgb&e_color=color(srgb,0.000,0.000,0.200) color_canvas.html?e_context=css&e_color=color(srgb,0.000,0.000,0.200)
|
||||
== color_canvas.html?e_context=2d&e_options={"willReadFrequently":"false"}&e_cspace=srgb&e_color=color(srgb,0.502,0.502,0.502) color_canvas.html?e_context=css&e_color=color(srgb,0.502,0.502,0.502)
|
||||
skip-if(cocoaWidget||winWidget) fails == color_canvas.html?e_context=webgl2&e_webgl_format=RGBA8&e_cspace=display-p3&e_color=color(srgb,0.000,0.000,0.502) color_canvas.html?e_context=css&e_color=color(display-p3,0.000,0.000,0.502)
|
||||
skip-if(cocoaWidget||winWidget) == color_canvas.html?e_context=webgl2&e_webgl_format=RGBA8&e_cspace=display-p3&e_color=color(srgb,0.000,0.000,0.502) color_canvas.html?e_context=css&e_color=color(srgb,0.000,0.000,0.502)
|
||||
skip-if(!cocoaWidget&&!winWidget) == color_canvas.html?e_context=webgl2&e_webgl_format=RGBA8&e_cspace=display-p3&e_color=color(srgb,1.000,1.000,1.000) color_canvas.html?e_context=css&e_color=color(display-p3,1.000,1.000,1.000)
|
||||
skip-if(cocoaWidget||winWidget) == color_canvas.html?e_context=webgl2&e_webgl_format=RGBA8&e_cspace=display-p3&e_color=color(srgb,1.000,1.000,1.000) color_canvas.html?e_context=css&e_color=color(display-p3,1.000,1.000,1.000)
|
||||
### Generated, do not edit. ###
|
||||
== color_canvas.html?e_context=2d&e_options={"willReadFrequently":"false"}&e_cspace=srgb&e_color=color(srgb,0.502,0.000,0.000) color_canvas.html?e_context=css&e_color=color(srgb,0.502,0.000,0.000)
|
||||
== color_canvas.html?e_context=2d&e_options={"willReadFrequently":"false"}&e_cspace=srgb&e_color=color(srgb,0.000,0.502,0.000) color_canvas.html?e_context=css&e_color=color(srgb,0.000,0.502,0.000)
|
||||
== color_canvas.html?e_context=2d&e_options={"willReadFrequently":"false"}&e_cspace=srgb&e_color=color(srgb,0.000,0.000,0.502) color_canvas.html?e_context=css&e_color=color(srgb,0.000,0.000,0.502)
|
||||
== color_canvas.html?e_context=2d&e_options={"willReadFrequently":"false"}&e_cspace=srgb&e_color=color(srgb,1.000,1.000,1.000) color_canvas.html?e_context=css&e_color=color(srgb,1.000,1.000,1.000)
|
||||
== color_canvas.html?e_context=2d&e_options={"willReadFrequently":"true"}&e_cspace=srgb&e_color=color(srgb,0.000,0.000,0.000) color_canvas.html?e_context=css&e_color=color(srgb,0.000,0.000,0.000)
|
||||
== color_canvas.html?e_context=2d&e_options={"willReadFrequently":"true"}&e_cspace=srgb&e_color=color(srgb,0.200,0.200,0.200) color_canvas.html?e_context=css&e_color=color(srgb,0.200,0.200,0.200)
|
||||
== color_canvas.html?e_context=2d&e_options={"willReadFrequently":"true"}&e_cspace=srgb&e_color=color(srgb,0.200,0.000,0.000) color_canvas.html?e_context=css&e_color=color(srgb,0.200,0.000,0.000)
|
||||
== color_canvas.html?e_context=2d&e_options={"willReadFrequently":"true"}&e_cspace=srgb&e_color=color(srgb,0.000,0.200,0.000) color_canvas.html?e_context=css&e_color=color(srgb,0.000,0.200,0.000)
|
||||
### Generated, do not edit. ###
|
||||
== color_canvas.html?e_context=2d&e_options={"willReadFrequently":"false"}&e_cspace=srgb&e_color=color(display-p3,0.000,0.000,0.000) color_canvas.html?e_context=css&e_color=color(display-p3,0.000,0.000,0.000)
|
||||
== color_canvas.html?e_context=2d&e_options={"willReadFrequently":"false"}&e_cspace=srgb&e_color=color(display-p3,0.200,0.200,0.200) color_canvas.html?e_context=css&e_color=color(display-p3,0.200,0.200,0.200)
|
||||
== color_canvas.html?e_context=2d&e_options={"willReadFrequently":"false"}&e_cspace=srgb&e_color=color(display-p3,0.200,0.000,0.000) color_canvas.html?e_context=css&e_color=color(display-p3,0.200,0.000,0.000)
|
||||
== color_canvas.html?e_context=2d&e_options={"willReadFrequently":"false"}&e_cspace=srgb&e_color=color(display-p3,0.000,0.200,0.000) color_canvas.html?e_context=css&e_color=color(display-p3,0.000,0.200,0.000)
|
||||
== color_canvas.html?e_context=2d&e_options={"willReadFrequently":"true"}&e_cspace=srgb&e_color=color(srgb,0.000,0.000,0.200) color_canvas.html?e_context=css&e_color=color(srgb,0.000,0.000,0.200)
|
||||
== color_canvas.html?e_context=2d&e_options={"willReadFrequently":"true"}&e_cspace=srgb&e_color=color(srgb,0.502,0.502,0.502) color_canvas.html?e_context=css&e_color=color(srgb,0.502,0.502,0.502)
|
||||
== color_canvas.html?e_context=2d&e_options={"willReadFrequently":"true"}&e_cspace=srgb&e_color=color(srgb,0.502,0.000,0.000) color_canvas.html?e_context=css&e_color=color(srgb,0.502,0.000,0.000)
|
||||
== color_canvas.html?e_context=2d&e_options={"willReadFrequently":"true"}&e_cspace=srgb&e_color=color(srgb,0.000,0.502,0.000) color_canvas.html?e_context=css&e_color=color(srgb,0.000,0.502,0.000)
|
||||
### Generated, do not edit. ###
|
||||
== color_canvas.html?e_context=2d&e_options={"willReadFrequently":"false"}&e_cspace=srgb&e_color=color(display-p3,0.000,0.000,0.200) color_canvas.html?e_context=css&e_color=color(display-p3,0.000,0.000,0.200)
|
||||
== color_canvas.html?e_context=2d&e_options={"willReadFrequently":"false"}&e_cspace=srgb&e_color=color(display-p3,0.502,0.502,0.502) color_canvas.html?e_context=css&e_color=color(display-p3,0.502,0.502,0.502)
|
||||
== color_canvas.html?e_context=2d&e_options={"willReadFrequently":"false"}&e_cspace=srgb&e_color=color(display-p3,0.502,0.000,0.000) color_canvas.html?e_context=css&e_color=color(display-p3,0.502,0.000,0.000)
|
||||
== color_canvas.html?e_context=2d&e_options={"willReadFrequently":"false"}&e_cspace=srgb&e_color=color(display-p3,0.000,0.502,0.000) color_canvas.html?e_context=css&e_color=color(display-p3,0.000,0.502,0.000)
|
||||
== color_canvas.html?e_context=2d&e_options={"willReadFrequently":"true"}&e_cspace=srgb&e_color=color(srgb,0.000,0.000,0.502) color_canvas.html?e_context=css&e_color=color(srgb,0.000,0.000,0.502)
|
||||
== color_canvas.html?e_context=2d&e_options={"willReadFrequently":"true"}&e_cspace=srgb&e_color=color(srgb,1.000,1.000,1.000) color_canvas.html?e_context=css&e_color=color(srgb,1.000,1.000,1.000)
|
||||
== color_canvas.html?e_context=2d&e_options={"willReadFrequently":"true"}&e_cspace=srgb&e_color=color(display-p3,0.000,0.000,0.000) color_canvas.html?e_context=css&e_color=color(display-p3,0.000,0.000,0.000)
|
||||
== color_canvas.html?e_context=2d&e_options={"willReadFrequently":"true"}&e_cspace=srgb&e_color=color(display-p3,0.200,0.200,0.200) color_canvas.html?e_context=css&e_color=color(display-p3,0.200,0.200,0.200)
|
||||
### Generated, do not edit. ###
|
||||
== color_canvas.html?e_context=2d&e_options={"willReadFrequently":"false"}&e_cspace=srgb&e_color=color(display-p3,0.000,0.000,0.502) color_canvas.html?e_context=css&e_color=color(display-p3,0.000,0.000,0.502)
|
||||
== color_canvas.html?e_context=2d&e_options={"willReadFrequently":"false"}&e_cspace=srgb&e_color=color(display-p3,1.000,1.000,1.000) color_canvas.html?e_context=css&e_color=color(display-p3,1.000,1.000,1.000)
|
||||
== color_canvas.html?e_context=2d&e_options={"willReadFrequently":"false"}&e_cspace=display-p3&e_color=color(srgb,0.000,0.000,0.000) color_canvas.html?e_context=css&e_color=color(srgb,0.000,0.000,0.000)
|
||||
== color_canvas.html?e_context=2d&e_options={"willReadFrequently":"false"}&e_cspace=display-p3&e_color=color(srgb,0.200,0.200,0.200) color_canvas.html?e_context=css&e_color=color(srgb,0.200,0.200,0.200)
|
||||
== color_canvas.html?e_context=2d&e_options={"willReadFrequently":"true"}&e_cspace=srgb&e_color=color(display-p3,0.200,0.000,0.000) color_canvas.html?e_context=css&e_color=color(display-p3,0.200,0.000,0.000)
|
||||
== color_canvas.html?e_context=2d&e_options={"willReadFrequently":"true"}&e_cspace=srgb&e_color=color(display-p3,0.000,0.200,0.000) color_canvas.html?e_context=css&e_color=color(display-p3,0.000,0.200,0.000)
|
||||
== color_canvas.html?e_context=2d&e_options={"willReadFrequently":"true"}&e_cspace=srgb&e_color=color(display-p3,0.000,0.000,0.200) color_canvas.html?e_context=css&e_color=color(display-p3,0.000,0.000,0.200)
|
||||
== color_canvas.html?e_context=2d&e_options={"willReadFrequently":"true"}&e_cspace=srgb&e_color=color(display-p3,0.502,0.502,0.502) color_canvas.html?e_context=css&e_color=color(display-p3,0.502,0.502,0.502)
|
||||
### Generated, do not edit. ###
|
||||
== color_canvas.html?e_context=2d&e_options={"willReadFrequently":"false"}&e_cspace=display-p3&e_color=color(srgb,0.200,0.000,0.000) color_canvas.html?e_context=css&e_color=color(srgb,0.200,0.000,0.000)
|
||||
== color_canvas.html?e_context=2d&e_options={"willReadFrequently":"false"}&e_cspace=display-p3&e_color=color(srgb,0.000,0.200,0.000) color_canvas.html?e_context=css&e_color=color(srgb,0.000,0.200,0.000)
|
||||
== color_canvas.html?e_context=2d&e_options={"willReadFrequently":"false"}&e_cspace=display-p3&e_color=color(srgb,0.000,0.000,0.200) color_canvas.html?e_context=css&e_color=color(srgb,0.000,0.000,0.200)
|
||||
== color_canvas.html?e_context=2d&e_options={"willReadFrequently":"false"}&e_cspace=display-p3&e_color=color(srgb,0.502,0.502,0.502) color_canvas.html?e_context=css&e_color=color(srgb,0.502,0.502,0.502)
|
||||
== color_canvas.html?e_context=2d&e_options={"willReadFrequently":"true"}&e_cspace=srgb&e_color=color(display-p3,0.502,0.000,0.000) color_canvas.html?e_context=css&e_color=color(display-p3,0.502,0.000,0.000)
|
||||
== color_canvas.html?e_context=2d&e_options={"willReadFrequently":"true"}&e_cspace=srgb&e_color=color(display-p3,0.000,0.502,0.000) color_canvas.html?e_context=css&e_color=color(display-p3,0.000,0.502,0.000)
|
||||
== color_canvas.html?e_context=2d&e_options={"willReadFrequently":"true"}&e_cspace=srgb&e_color=color(display-p3,0.000,0.000,0.502) color_canvas.html?e_context=css&e_color=color(display-p3,0.000,0.000,0.502)
|
||||
== color_canvas.html?e_context=2d&e_options={"willReadFrequently":"true"}&e_cspace=srgb&e_color=color(display-p3,1.000,1.000,1.000) color_canvas.html?e_context=css&e_color=color(display-p3,1.000,1.000,1.000)
|
||||
### Generated, do not edit. ###
|
||||
== color_canvas.html?e_context=2d&e_options={"willReadFrequently":"false"}&e_cspace=display-p3&e_color=color(srgb,0.502,0.000,0.000) color_canvas.html?e_context=css&e_color=color(srgb,0.502,0.000,0.000)
|
||||
== color_canvas.html?e_context=2d&e_options={"willReadFrequently":"false"}&e_cspace=display-p3&e_color=color(srgb,0.000,0.502,0.000) color_canvas.html?e_context=css&e_color=color(srgb,0.000,0.502,0.000)
|
||||
== color_canvas.html?e_context=2d&e_options={"willReadFrequently":"false"}&e_cspace=display-p3&e_color=color(srgb,0.000,0.000,0.502) color_canvas.html?e_context=css&e_color=color(srgb,0.000,0.000,0.502)
|
||||
== color_canvas.html?e_context=2d&e_options={"willReadFrequently":"false"}&e_cspace=display-p3&e_color=color(srgb,1.000,1.000,1.000) color_canvas.html?e_context=css&e_color=color(srgb,1.000,1.000,1.000)
|
||||
== color_canvas.html?e_context=2d&e_options={"willReadFrequently":"true"}&e_cspace=display-p3&e_color=color(srgb,0.000,0.000,0.000) color_canvas.html?e_context=css&e_color=color(srgb,0.000,0.000,0.000)
|
||||
== color_canvas.html?e_context=2d&e_options={"willReadFrequently":"true"}&e_cspace=display-p3&e_color=color(srgb,0.200,0.200,0.200) color_canvas.html?e_context=css&e_color=color(srgb,0.200,0.200,0.200)
|
||||
== color_canvas.html?e_context=2d&e_options={"willReadFrequently":"true"}&e_cspace=display-p3&e_color=color(srgb,0.200,0.000,0.000) color_canvas.html?e_context=css&e_color=color(srgb,0.200,0.000,0.000)
|
||||
== color_canvas.html?e_context=2d&e_options={"willReadFrequently":"true"}&e_cspace=display-p3&e_color=color(srgb,0.000,0.200,0.000) color_canvas.html?e_context=css&e_color=color(srgb,0.000,0.200,0.000)
|
||||
### Generated, do not edit. ###
|
||||
== color_canvas.html?e_context=2d&e_options={"willReadFrequently":"false"}&e_cspace=display-p3&e_color=color(display-p3,0.000,0.000,0.000) color_canvas.html?e_context=css&e_color=color(display-p3,0.000,0.000,0.000)
|
||||
== color_canvas.html?e_context=2d&e_options={"willReadFrequently":"false"}&e_cspace=display-p3&e_color=color(display-p3,0.200,0.200,0.200) color_canvas.html?e_context=css&e_color=color(display-p3,0.200,0.200,0.200)
|
||||
== color_canvas.html?e_context=2d&e_options={"willReadFrequently":"false"}&e_cspace=display-p3&e_color=color(display-p3,0.200,0.000,0.000) color_canvas.html?e_context=css&e_color=color(display-p3,0.200,0.000,0.000)
|
||||
== color_canvas.html?e_context=2d&e_options={"willReadFrequently":"false"}&e_cspace=display-p3&e_color=color(display-p3,0.000,0.200,0.000) color_canvas.html?e_context=css&e_color=color(display-p3,0.000,0.200,0.000)
|
||||
== color_canvas.html?e_context=2d&e_options={"willReadFrequently":"true"}&e_cspace=display-p3&e_color=color(srgb,0.000,0.000,0.200) color_canvas.html?e_context=css&e_color=color(srgb,0.000,0.000,0.200)
|
||||
== color_canvas.html?e_context=2d&e_options={"willReadFrequently":"true"}&e_cspace=display-p3&e_color=color(srgb,0.502,0.502,0.502) color_canvas.html?e_context=css&e_color=color(srgb,0.502,0.502,0.502)
|
||||
== color_canvas.html?e_context=2d&e_options={"willReadFrequently":"true"}&e_cspace=display-p3&e_color=color(srgb,0.502,0.000,0.000) color_canvas.html?e_context=css&e_color=color(srgb,0.502,0.000,0.000)
|
||||
== color_canvas.html?e_context=2d&e_options={"willReadFrequently":"true"}&e_cspace=display-p3&e_color=color(srgb,0.000,0.502,0.000) color_canvas.html?e_context=css&e_color=color(srgb,0.000,0.502,0.000)
|
||||
### Generated, do not edit. ###
|
||||
== color_canvas.html?e_context=2d&e_options={"willReadFrequently":"false"}&e_cspace=display-p3&e_color=color(display-p3,0.000,0.000,0.200) color_canvas.html?e_context=css&e_color=color(display-p3,0.000,0.000,0.200)
|
||||
== color_canvas.html?e_context=2d&e_options={"willReadFrequently":"false"}&e_cspace=display-p3&e_color=color(display-p3,0.502,0.502,0.502) color_canvas.html?e_context=css&e_color=color(display-p3,0.502,0.502,0.502)
|
||||
== color_canvas.html?e_context=2d&e_options={"willReadFrequently":"false"}&e_cspace=display-p3&e_color=color(display-p3,0.502,0.000,0.000) color_canvas.html?e_context=css&e_color=color(display-p3,0.502,0.000,0.000)
|
||||
== color_canvas.html?e_context=2d&e_options={"willReadFrequently":"false"}&e_cspace=display-p3&e_color=color(display-p3,0.000,0.502,0.000) color_canvas.html?e_context=css&e_color=color(display-p3,0.000,0.502,0.000)
|
||||
== color_canvas.html?e_context=2d&e_options={"willReadFrequently":"true"}&e_cspace=display-p3&e_color=color(srgb,0.000,0.000,0.502) color_canvas.html?e_context=css&e_color=color(srgb,0.000,0.000,0.502)
|
||||
== color_canvas.html?e_context=2d&e_options={"willReadFrequently":"true"}&e_cspace=display-p3&e_color=color(srgb,1.000,1.000,1.000) color_canvas.html?e_context=css&e_color=color(srgb,1.000,1.000,1.000)
|
||||
== color_canvas.html?e_context=2d&e_options={"willReadFrequently":"true"}&e_cspace=display-p3&e_color=color(display-p3,0.000,0.000,0.000) color_canvas.html?e_context=css&e_color=color(display-p3,0.000,0.000,0.000)
|
||||
== color_canvas.html?e_context=2d&e_options={"willReadFrequently":"true"}&e_cspace=display-p3&e_color=color(display-p3,0.200,0.200,0.200) color_canvas.html?e_context=css&e_color=color(display-p3,0.200,0.200,0.200)
|
||||
### Generated, do not edit. ###
|
||||
== color_canvas.html?e_context=2d&e_options={"willReadFrequently":"false"}&e_cspace=display-p3&e_color=color(display-p3,0.000,0.000,0.502) color_canvas.html?e_context=css&e_color=color(display-p3,0.000,0.000,0.502)
|
||||
== color_canvas.html?e_context=2d&e_options={"willReadFrequently":"false"}&e_cspace=display-p3&e_color=color(display-p3,1.000,1.000,1.000) color_canvas.html?e_context=css&e_color=color(display-p3,1.000,1.000,1.000)
|
||||
== color_canvas.html?e_context=2d&e_options={"willReadFrequently":"true"}&e_cspace=display-p3&e_color=color(display-p3,0.200,0.000,0.000) color_canvas.html?e_context=css&e_color=color(display-p3,0.200,0.000,0.000)
|
||||
== color_canvas.html?e_context=2d&e_options={"willReadFrequently":"true"}&e_cspace=display-p3&e_color=color(display-p3,0.000,0.200,0.000) color_canvas.html?e_context=css&e_color=color(display-p3,0.000,0.200,0.000)
|
||||
== color_canvas.html?e_context=2d&e_options={"willReadFrequently":"true"}&e_cspace=display-p3&e_color=color(display-p3,0.000,0.000,0.200) color_canvas.html?e_context=css&e_color=color(display-p3,0.000,0.000,0.200)
|
||||
== color_canvas.html?e_context=2d&e_options={"willReadFrequently":"true"}&e_cspace=display-p3&e_color=color(display-p3,0.502,0.502,0.502) color_canvas.html?e_context=css&e_color=color(display-p3,0.502,0.502,0.502)
|
||||
### Generated, do not edit. ###
|
||||
== color_canvas.html?e_context=2d&e_options={"willReadFrequently":"true"}&e_cspace=display-p3&e_color=color(display-p3,0.502,0.000,0.000) color_canvas.html?e_context=css&e_color=color(display-p3,0.502,0.000,0.000)
|
||||
== color_canvas.html?e_context=2d&e_options={"willReadFrequently":"true"}&e_cspace=display-p3&e_color=color(display-p3,0.000,0.502,0.000) color_canvas.html?e_context=css&e_color=color(display-p3,0.000,0.502,0.000)
|
||||
== color_canvas.html?e_context=2d&e_options={"willReadFrequently":"true"}&e_cspace=display-p3&e_color=color(display-p3,0.000,0.000,0.502) color_canvas.html?e_context=css&e_color=color(display-p3,0.000,0.000,0.502)
|
||||
== color_canvas.html?e_context=2d&e_options={"willReadFrequently":"true"}&e_cspace=display-p3&e_color=color(display-p3,1.000,1.000,1.000) color_canvas.html?e_context=css&e_color=color(display-p3,1.000,1.000,1.000)
|
||||
### Generated, do not edit. ###
|
||||
== color_canvas.html?e_context=2d&e_options={"willReadFrequently":"false"}&e_cspace=srgb&e_color=color(srgb,0.000,0.000,0.000) color_canvas.html?e_context=css&e_color=color(srgb,0.000,0.000,0.000)
|
||||
== color_canvas.html?e_context=2d&e_options={"willReadFrequently":"false"}&e_cspace=srgb&e_color=color(srgb,0.200,0.200,0.200) color_canvas.html?e_context=css&e_color=color(srgb,0.200,0.200,0.200)
|
||||
== color_canvas.html?e_context=2d&e_options={"willReadFrequently":"false"}&e_cspace=srgb&e_color=color(srgb,0.200,0.000,0.000) color_canvas.html?e_context=css&e_color=color(srgb,0.200,0.000,0.000)
|
||||
== color_canvas.html?e_context=2d&e_options={"willReadFrequently":"false"}&e_cspace=srgb&e_color=color(srgb,0.000,0.200,0.000) color_canvas.html?e_context=css&e_color=color(srgb,0.000,0.200,0.000)
|
||||
### Generated, do not edit. ###
|
||||
== color_canvas.html?e_context=2d&e_options={"willReadFrequently":"false"}&e_cspace=srgb&e_color=color(srgb,0.000,0.000,0.200) color_canvas.html?e_context=css&e_color=color(srgb,0.000,0.000,0.200)
|
||||
== color_canvas.html?e_context=2d&e_options={"willReadFrequently":"false"}&e_cspace=srgb&e_color=color(srgb,0.502,0.502,0.502) color_canvas.html?e_context=css&e_color=color(srgb,0.502,0.502,0.502)
|
||||
== color_canvas.html?e_context=2d&e_options={"willReadFrequently":"false"}&e_cspace=srgb&e_color=color(srgb,0.502,0.000,0.000) color_canvas.html?e_context=css&e_color=color(srgb,0.502,0.000,0.000)
|
||||
== color_canvas.html?e_context=2d&e_options={"willReadFrequently":"false"}&e_cspace=srgb&e_color=color(srgb,0.000,0.502,0.000) color_canvas.html?e_context=css&e_color=color(srgb,0.000,0.502,0.000)
|
||||
### Generated, do not edit. ###
|
||||
== color_canvas.html?e_context=2d&e_options={"willReadFrequently":"false"}&e_cspace=srgb&e_color=color(srgb,0.000,0.000,0.502) color_canvas.html?e_context=css&e_color=color(srgb,0.000,0.000,0.502)
|
||||
== color_canvas.html?e_context=2d&e_options={"willReadFrequently":"false"}&e_cspace=srgb&e_color=color(srgb,1.000,1.000,1.000) color_canvas.html?e_context=css&e_color=color(srgb,1.000,1.000,1.000)
|
||||
== color_canvas.html?e_context=2d&e_options={"willReadFrequently":"false"}&e_cspace=srgb&e_color=color(display-p3,0.000,0.000,0.000) color_canvas.html?e_context=css&e_color=color(display-p3,0.000,0.000,0.000)
|
||||
== color_canvas.html?e_context=2d&e_options={"willReadFrequently":"false"}&e_cspace=srgb&e_color=color(display-p3,0.200,0.200,0.200) color_canvas.html?e_context=css&e_color=color(display-p3,0.200,0.200,0.200)
|
||||
### Generated, do not edit. ###
|
||||
== color_canvas.html?e_context=2d&e_options={"willReadFrequently":"false"}&e_cspace=srgb&e_color=color(display-p3,0.200,0.000,0.000) color_canvas.html?e_context=css&e_color=color(display-p3,0.200,0.000,0.000)
|
||||
== color_canvas.html?e_context=2d&e_options={"willReadFrequently":"false"}&e_cspace=srgb&e_color=color(display-p3,0.000,0.200,0.000) color_canvas.html?e_context=css&e_color=color(display-p3,0.000,0.200,0.000)
|
||||
== color_canvas.html?e_context=2d&e_options={"willReadFrequently":"false"}&e_cspace=srgb&e_color=color(display-p3,0.000,0.000,0.200) color_canvas.html?e_context=css&e_color=color(display-p3,0.000,0.000,0.200)
|
||||
== color_canvas.html?e_context=2d&e_options={"willReadFrequently":"false"}&e_cspace=srgb&e_color=color(display-p3,0.502,0.502,0.502) color_canvas.html?e_context=css&e_color=color(display-p3,0.502,0.502,0.502)
|
||||
### Generated, do not edit. ###
|
||||
== color_canvas.html?e_context=2d&e_options={"willReadFrequently":"false"}&e_cspace=srgb&e_color=color(display-p3,0.502,0.000,0.000) color_canvas.html?e_context=css&e_color=color(display-p3,0.502,0.000,0.000)
|
||||
== color_canvas.html?e_context=2d&e_options={"willReadFrequently":"false"}&e_cspace=srgb&e_color=color(display-p3,0.000,0.502,0.000) color_canvas.html?e_context=css&e_color=color(display-p3,0.000,0.502,0.000)
|
||||
== color_canvas.html?e_context=2d&e_options={"willReadFrequently":"false"}&e_cspace=srgb&e_color=color(display-p3,0.000,0.000,0.502) color_canvas.html?e_context=css&e_color=color(display-p3,0.000,0.000,0.502)
|
||||
== color_canvas.html?e_context=2d&e_options={"willReadFrequently":"false"}&e_cspace=srgb&e_color=color(display-p3,1.000,1.000,1.000) color_canvas.html?e_context=css&e_color=color(display-p3,1.000,1.000,1.000)
|
||||
### Generated, do not edit. ###
|
||||
== color_canvas.html?e_context=2d&e_options={"willReadFrequently":"false"}&e_cspace=display-p3&e_color=color(srgb,0.000,0.000,0.000) color_canvas.html?e_context=css&e_color=color(srgb,0.000,0.000,0.000)
|
||||
== color_canvas.html?e_context=2d&e_options={"willReadFrequently":"false"}&e_cspace=display-p3&e_color=color(srgb,0.200,0.200,0.200) color_canvas.html?e_context=css&e_color=color(srgb,0.200,0.200,0.200)
|
||||
== color_canvas.html?e_context=2d&e_options={"willReadFrequently":"false"}&e_cspace=display-p3&e_color=color(srgb,0.200,0.000,0.000) color_canvas.html?e_context=css&e_color=color(srgb,0.200,0.000,0.000)
|
||||
== color_canvas.html?e_context=2d&e_options={"willReadFrequently":"false"}&e_cspace=display-p3&e_color=color(srgb,0.000,0.200,0.000) color_canvas.html?e_context=css&e_color=color(srgb,0.000,0.200,0.000)
|
||||
### Generated, do not edit. ###
|
||||
== color_canvas.html?e_context=2d&e_options={"willReadFrequently":"false"}&e_cspace=display-p3&e_color=color(srgb,0.000,0.000,0.200) color_canvas.html?e_context=css&e_color=color(srgb,0.000,0.000,0.200)
|
||||
== color_canvas.html?e_context=2d&e_options={"willReadFrequently":"false"}&e_cspace=display-p3&e_color=color(srgb,0.502,0.502,0.502) color_canvas.html?e_context=css&e_color=color(srgb,0.502,0.502,0.502)
|
||||
== color_canvas.html?e_context=2d&e_options={"willReadFrequently":"false"}&e_cspace=display-p3&e_color=color(srgb,0.502,0.000,0.000) color_canvas.html?e_context=css&e_color=color(srgb,0.502,0.000,0.000)
|
||||
== color_canvas.html?e_context=2d&e_options={"willReadFrequently":"false"}&e_cspace=display-p3&e_color=color(srgb,0.000,0.502,0.000) color_canvas.html?e_context=css&e_color=color(srgb,0.000,0.502,0.000)
|
||||
### Generated, do not edit. ###
|
||||
== color_canvas.html?e_context=2d&e_options={"willReadFrequently":"false"}&e_cspace=display-p3&e_color=color(srgb,0.000,0.000,0.502) color_canvas.html?e_context=css&e_color=color(srgb,0.000,0.000,0.502)
|
||||
== color_canvas.html?e_context=2d&e_options={"willReadFrequently":"false"}&e_cspace=display-p3&e_color=color(srgb,1.000,1.000,1.000) color_canvas.html?e_context=css&e_color=color(srgb,1.000,1.000,1.000)
|
||||
== color_canvas.html?e_context=2d&e_options={"willReadFrequently":"false"}&e_cspace=display-p3&e_color=color(display-p3,0.000,0.000,0.000) color_canvas.html?e_context=css&e_color=color(display-p3,0.000,0.000,0.000)
|
||||
== color_canvas.html?e_context=2d&e_options={"willReadFrequently":"false"}&e_cspace=display-p3&e_color=color(display-p3,0.200,0.200,0.200) color_canvas.html?e_context=css&e_color=color(display-p3,0.200,0.200,0.200)
|
||||
### Generated, do not edit. ###
|
||||
== color_canvas.html?e_context=2d&e_options={"willReadFrequently":"false"}&e_cspace=display-p3&e_color=color(display-p3,0.200,0.000,0.000) color_canvas.html?e_context=css&e_color=color(display-p3,0.200,0.000,0.000)
|
||||
== color_canvas.html?e_context=2d&e_options={"willReadFrequently":"false"}&e_cspace=display-p3&e_color=color(display-p3,0.000,0.200,0.000) color_canvas.html?e_context=css&e_color=color(display-p3,0.000,0.200,0.000)
|
||||
== color_canvas.html?e_context=2d&e_options={"willReadFrequently":"false"}&e_cspace=display-p3&e_color=color(display-p3,0.000,0.000,0.200) color_canvas.html?e_context=css&e_color=color(display-p3,0.000,0.000,0.200)
|
||||
== color_canvas.html?e_context=2d&e_options={"willReadFrequently":"false"}&e_cspace=display-p3&e_color=color(display-p3,0.502,0.502,0.502) color_canvas.html?e_context=css&e_color=color(display-p3,0.502,0.502,0.502)
|
||||
### Generated, do not edit. ###
|
||||
== color_canvas.html?e_context=2d&e_options={"willReadFrequently":"false"}&e_cspace=display-p3&e_color=color(display-p3,0.502,0.000,0.000) color_canvas.html?e_context=css&e_color=color(display-p3,0.502,0.000,0.000)
|
||||
== color_canvas.html?e_context=2d&e_options={"willReadFrequently":"false"}&e_cspace=display-p3&e_color=color(display-p3,0.000,0.502,0.000) color_canvas.html?e_context=css&e_color=color(display-p3,0.000,0.502,0.000)
|
||||
== color_canvas.html?e_context=2d&e_options={"willReadFrequently":"false"}&e_cspace=display-p3&e_color=color(display-p3,0.000,0.000,0.502) color_canvas.html?e_context=css&e_color=color(display-p3,0.000,0.000,0.502)
|
||||
== color_canvas.html?e_context=2d&e_options={"willReadFrequently":"false"}&e_cspace=display-p3&e_color=color(display-p3,1.000,1.000,1.000) color_canvas.html?e_context=css&e_color=color(display-p3,1.000,1.000,1.000)
|
||||
|
|
|
@ -29,6 +29,7 @@
|
|||
<option value=css selected>css</option>
|
||||
<option value=2d>2d</option>
|
||||
<option value=webgl>webgl</option>
|
||||
<option value=webgl2>webgl2</option>
|
||||
</select>
|
||||
<br>
|
||||
Options: <input id=e_options type=text value={}>
|
||||
|
|
|
@ -120,9 +120,8 @@ WEBGL_FORMATS = keyed_alternatives(
|
|||
#'RGBA16F',
|
||||
],
|
||||
)
|
||||
WEBGL = cross_combine(
|
||||
[{"e_context": "webgl"}], WEBGL_FORMATS, CANVAS_CSPACES, WEBGL_COLORS
|
||||
)
|
||||
WEBGL_VERSIONS = keyed_alternatives("e_context", ["webgl", "webgl2"])
|
||||
WEBGL = cross_combine(WEBGL_VERSIONS, WEBGL_FORMATS, CANVAS_CSPACES, WEBGL_COLORS)
|
||||
|
||||
# -
|
||||
|
||||
|
@ -212,7 +211,7 @@ def correct_color_from_test_config(test_config: Config) -> CssColor:
|
|||
canvas_cspace = "srgb"
|
||||
|
||||
correct_color = parse_css_color(test_config["e_color"])
|
||||
if test_config["e_context"] == "webgl":
|
||||
if test_config["e_context"].startswith("webgl"):
|
||||
# Webgl ignores the color's cspace, because webgl has no concept of
|
||||
# source colorspace for clears/draws to the backbuffer.
|
||||
# This (correct) behavior is as if the color's cspace were overwritten by the
|
||||
|
@ -231,12 +230,12 @@ def correct_color_from_test_config(test_config: Config) -> CssColor:
|
|||
def reftests_from_config(test_config: Config) -> Iterable[ColorReftest]:
|
||||
correct_color = correct_color_from_test_config(test_config)
|
||||
|
||||
if test_config["e_context"] == "2d":
|
||||
if test_config["e_context"] in ["2d"]:
|
||||
# Canvas2d generally has the same behavior as css, so expect all passing.
|
||||
yield ColorReftest([], test_config, correct_color)
|
||||
return
|
||||
|
||||
assert test_config["e_context"] == "webgl", test_config["e_context"]
|
||||
assert test_config["e_context"].startswith("webgl"), test_config["e_context"]
|
||||
|
||||
# -
|
||||
|
||||
|
@ -249,6 +248,11 @@ def reftests_from_config(test_config: Config) -> Iterable[ColorReftest]:
|
|||
# If we fix an error, we'll see one unexpected-pass and one unexpected-fail.
|
||||
# If we get a new wrong answer, we'll see one unexpected-fail.
|
||||
|
||||
if correct_color.is_same_color(
|
||||
parse_css_color("color(display-p3 0.502 0.000 0.000)")
|
||||
):
|
||||
notes += ["fuzzy(0-1,0-10000)"]
|
||||
|
||||
if not expected_color.is_same_color(correct_color):
|
||||
yield ColorReftest(notes + ["fails"], test_config, correct_color)
|
||||
yield ColorReftest(notes, test_config, expected_color)
|
||||
|
@ -261,12 +265,26 @@ def reftests_from_config(test_config: Config) -> Iterable[ColorReftest]:
|
|||
# right now. This is the same as "srgb".
|
||||
|
||||
expected_color_srgb = CssColor("srgb", correct_color.rgb)
|
||||
# Mac
|
||||
yield from reftests_from_expected_color(["skip-if(!cocoaWidget)"], correct_color)
|
||||
# Win, Lin, Android
|
||||
yield from reftests_from_expected_color(
|
||||
["skip-if(cocoaWidget) "], expected_color_srgb
|
||||
)
|
||||
if test_config["e_context"] == "webgl2":
|
||||
# Win, Mac
|
||||
yield from reftests_from_expected_color(
|
||||
["skip-if(!cocoaWidget&&!winWidget)"], correct_color
|
||||
)
|
||||
# Lin, Android
|
||||
yield from reftests_from_expected_color(
|
||||
["skip-if(cocoaWidget||winWidget) "], expected_color_srgb
|
||||
)
|
||||
elif test_config["e_context"] == "webgl":
|
||||
# Mac
|
||||
yield from reftests_from_expected_color(
|
||||
["skip-if(!cocoaWidget)"], correct_color
|
||||
)
|
||||
# Win, Lin, Android
|
||||
yield from reftests_from_expected_color(
|
||||
["skip-if(cocoaWidget) "], expected_color_srgb
|
||||
)
|
||||
else:
|
||||
assert False, test_config["e_context"]
|
||||
|
||||
|
||||
# -
|
||||
|
@ -279,7 +297,7 @@ def amended_notes_from_reftest(reftest: ColorReftest) -> list[str]:
|
|||
is_green_only = ref_rgb_vals == (0, ref_rgb_vals[1], 0)
|
||||
if (
|
||||
"fails" in reftest.notes
|
||||
and reftest.test_config["e_context"] == "webgl"
|
||||
and reftest.test_config["e_context"].startswith("webgl")
|
||||
and reftest.test_config["e_cspace"] == "display-p3"
|
||||
and is_green_only
|
||||
):
|
||||
|
|
|
@ -546,6 +546,11 @@ interface mixin WebGLRenderingContextBase {
|
|||
readonly attribute GLsizei drawingBufferWidth;
|
||||
readonly attribute GLsizei drawingBufferHeight;
|
||||
|
||||
/* Upon context creation, drawingBufferColorSpace and unpackColorSpace both
|
||||
default to the value "srgb". */
|
||||
attribute PredefinedColorSpace drawingBufferColorSpace;
|
||||
//attribute PredefinedColorSpace unpackColorSpace;
|
||||
|
||||
[WebGLHandlesContextLoss] WebGLContextAttributes? getContextAttributes();
|
||||
[WebGLHandlesContextLoss] boolean isContextLost();
|
||||
|
||||
|
|
|
@ -8,38 +8,13 @@
|
|||
// Here be dragons.
|
||||
|
||||
#include <functional>
|
||||
#include <tuple>
|
||||
|
||||
namespace mozilla::gfx {
|
||||
namespace mozilla {
|
||||
|
||||
template <class T>
|
||||
size_t Hash(const T&);
|
||||
|
||||
template <class T>
|
||||
struct StaticStdHasher {
|
||||
static auto HashImpl(const T& v) { return std::hash<T>()(v); }
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct StaticHasher {
|
||||
static auto HashImpl(const T& v) { return v.hash(); }
|
||||
};
|
||||
template <class T>
|
||||
struct StaticHasher<std::optional<T>> {
|
||||
static size_t HashImpl(const std::optional<T>& v) {
|
||||
if (!v) return 0;
|
||||
return Hash(*v);
|
||||
}
|
||||
};
|
||||
template <>
|
||||
struct StaticHasher<int> : public StaticStdHasher<int> {};
|
||||
template <>
|
||||
struct StaticHasher<bool> : public StaticStdHasher<bool> {};
|
||||
template <>
|
||||
struct StaticHasher<float> : public StaticStdHasher<float> {};
|
||||
|
||||
template <class T>
|
||||
size_t Hash(const T& v) {
|
||||
return StaticHasher<T>::HashImpl(v);
|
||||
size_t StdHash(const T& t) {
|
||||
return std::hash<T>()(t);
|
||||
}
|
||||
|
||||
//-
|
||||
|
@ -52,97 +27,59 @@ inline size_t HashCombine(size_t seed, const size_t hash) {
|
|||
}
|
||||
|
||||
// -
|
||||
// See
|
||||
// https://codereview.stackexchange.com/questions/136770/hashing-a-tuple-in-c17
|
||||
|
||||
namespace detail {
|
||||
template <class... Args, size_t... Ids>
|
||||
size_t HashTupleN(const std::tuple<Args...>& tup,
|
||||
const std::index_sequence<Ids...>&) {
|
||||
size_t StdHashTupleN(const std::tuple<Args...>& tup,
|
||||
const std::index_sequence<Ids...>&) {
|
||||
size_t seed = 0;
|
||||
for (const auto& hash : {Hash(std::get<Ids>(tup))...}) {
|
||||
for (const auto& hash : {StdHash(std::get<Ids>(tup))...}) {
|
||||
seed = HashCombine(seed, hash);
|
||||
}
|
||||
return seed;
|
||||
}
|
||||
} // namespace detail
|
||||
|
||||
// -
|
||||
|
||||
template <class T>
|
||||
struct StdHashMembers {
|
||||
size_t operator()(const T& t) const {
|
||||
const auto members = t.Members();
|
||||
return StdHash(members);
|
||||
}
|
||||
};
|
||||
|
||||
// -
|
||||
|
||||
#define MOZ_MIXIN_DERIVE_CMP_OP_BY_MEMBERS(OP, T) \
|
||||
bool operator OP(const T& rhs) const { return Members() OP rhs.Members(); }
|
||||
|
||||
#define MOZ_MIXIN_DERIVE_CMP_OPS_BY_MEMBERS(T) \
|
||||
MOZ_MIXIN_DERIVE_CMP_OP_BY_MEMBERS(==, T) \
|
||||
MOZ_MIXIN_DERIVE_CMP_OP_BY_MEMBERS(!=, T) \
|
||||
MOZ_MIXIN_DERIVE_CMP_OP_BY_MEMBERS(<, T) \
|
||||
MOZ_MIXIN_DERIVE_CMP_OP_BY_MEMBERS(<=, T) \
|
||||
MOZ_MIXIN_DERIVE_CMP_OP_BY_MEMBERS(>, T) \
|
||||
MOZ_MIXIN_DERIVE_CMP_OP_BY_MEMBERS(>=, T)
|
||||
|
||||
template <class T>
|
||||
struct DeriveCmpOpMembers {
|
||||
private:
|
||||
auto Members() const { return reinterpret_cast<const T*>(this)->Members(); }
|
||||
|
||||
public:
|
||||
MOZ_MIXIN_DERIVE_CMP_OPS_BY_MEMBERS(T)
|
||||
};
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
template <class... Args>
|
||||
size_t HashTuple(const std::tuple<Args...>& tup) {
|
||||
return HashTupleN(tup, std::make_index_sequence<sizeof...(Args)>());
|
||||
}
|
||||
|
||||
// -
|
||||
|
||||
template <class T>
|
||||
auto MembersEq(const T& a, const T& b) {
|
||||
const auto atup = a.Members();
|
||||
const auto btup = b.Members();
|
||||
return atup == btup;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
auto MembersLt(const T& a, const T& b) {
|
||||
const auto atup = a.Members();
|
||||
const auto btup = b.Members();
|
||||
return atup == btup;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
auto MembersHash(const T& a) {
|
||||
const auto atup = a.Members();
|
||||
return HashTuple(atup);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
struct MembersHasher final {
|
||||
auto operator()(const T& v) const { return v.hash(); }
|
||||
struct std::hash<std::tuple<Args...>> {
|
||||
size_t operator()(const std::tuple<Args...>& t) const {
|
||||
return mozilla::detail::StdHashTupleN(
|
||||
t, std::make_index_sequence<sizeof...(Args)>());
|
||||
}
|
||||
};
|
||||
|
||||
/** E.g.:
|
||||
struct Foo {
|
||||
int i;
|
||||
bool b;
|
||||
|
||||
auto Members() const { return std::tie(i, b); }
|
||||
INLINE_AUTO_MAPPABLE(Foo)
|
||||
};
|
||||
std::unordered_set<T, T::Hasher> easy;
|
||||
**/
|
||||
#define INLINE_DERIVE_MEMBERS_EQ(T) \
|
||||
friend bool operator==(const T& a, const T& b) { \
|
||||
return mozilla::gfx::MembersEq(a, b); \
|
||||
} \
|
||||
friend bool operator!=(const T& a, const T& b) { return !operator==(a, b); }
|
||||
#define INLINE_AUTO_MAPPABLE(T) \
|
||||
friend bool operator<(const T& a, const T& b) { \
|
||||
return mozilla::gfx::MembersLt(a, b); \
|
||||
} \
|
||||
INLINE_DERIVE_MEMBERS_EQ(T) \
|
||||
size_t hash() const { \
|
||||
return mozilla::gfx::MembersHash(*reinterpret_cast<const T*>(this)); \
|
||||
} \
|
||||
using Hasher = mozilla::gfx::MembersHasher<T>;
|
||||
|
||||
// -
|
||||
|
||||
/** E.g.:
|
||||
```
|
||||
struct Foo : public AutoMappable<Foo> {
|
||||
int i;
|
||||
bool b;
|
||||
|
||||
auto Members() const { return std::tie(i, b); }
|
||||
};
|
||||
std::unordered_set<T, T::Hasher> easy;
|
||||
```
|
||||
`easy.insert({{}, 2, true});`
|
||||
The initial {} is needed for aggregate initialization of AutoMappable<Foo>.
|
||||
Use INLINE_AUTO_MAPPABLE if this is too annoying.
|
||||
**/
|
||||
template <class T>
|
||||
struct AutoMappable {
|
||||
INLINE_AUTO_MAPPABLE(T)
|
||||
};
|
||||
|
||||
} // namespace mozilla::gfx
|
||||
|
||||
#endif // MOZILLA_AUTO_MAPPABLE_H
|
||||
|
|
|
@ -42,19 +42,27 @@ typedef struct _qcms_profile qcms_profile;
|
|||
|
||||
namespace mozilla::color {
|
||||
|
||||
// -
|
||||
|
||||
struct YuvLumaCoeffs final {
|
||||
float r = 0.2126;
|
||||
float g = 0.7152;
|
||||
float b = 0.0722;
|
||||
|
||||
auto Members() const { return std::tie(r, g, b); }
|
||||
INLINE_AUTO_MAPPABLE(YuvLumaCoeffs)
|
||||
MOZ_MIXIN_DERIVE_CMP_OPS_BY_MEMBERS(YuvLumaCoeffs)
|
||||
|
||||
static constexpr auto Rec709() { return YuvLumaCoeffs(); }
|
||||
|
||||
static constexpr auto Rec2020() {
|
||||
return YuvLumaCoeffs{0.2627, 0.6780, 0.0593};
|
||||
return YuvLumaCoeffs{
|
||||
.r = 0.2627,
|
||||
.g = 0.6780,
|
||||
.b = 0.0593,
|
||||
};
|
||||
}
|
||||
|
||||
static constexpr auto Gbr() { return YuvLumaCoeffs{.r = 0, .g = 1, .b = 0}; }
|
||||
};
|
||||
|
||||
struct PiecewiseGammaDesc final {
|
||||
|
@ -68,26 +76,26 @@ struct PiecewiseGammaDesc final {
|
|||
float k = 12.92;
|
||||
|
||||
auto Members() const { return std::tie(a, b, g, k); }
|
||||
INLINE_AUTO_MAPPABLE(PiecewiseGammaDesc)
|
||||
MOZ_MIXIN_DERIVE_CMP_OPS_BY_MEMBERS(PiecewiseGammaDesc)
|
||||
|
||||
static constexpr auto Srgb() { return PiecewiseGammaDesc(); }
|
||||
static constexpr auto DisplayP3() { return Srgb(); }
|
||||
|
||||
static constexpr auto Rec709() {
|
||||
return PiecewiseGammaDesc{
|
||||
1.099,
|
||||
0.018,
|
||||
1.0 / 0.45, // ~2.222
|
||||
4.5,
|
||||
.a = 1.099,
|
||||
.b = 0.018,
|
||||
.g = 1.0 / 0.45, // ~2.222
|
||||
.k = 4.5,
|
||||
};
|
||||
}
|
||||
// FYI: static constexpr auto Rec2020_10bit() { return Rec709(); }
|
||||
static constexpr auto Rec2020_12bit() {
|
||||
return PiecewiseGammaDesc{
|
||||
1.0993,
|
||||
0.0181,
|
||||
1.0 / 0.45, // ~2.222
|
||||
4.5,
|
||||
.a = 1.0993,
|
||||
.b = 0.0181,
|
||||
.g = 1.0 / 0.45, // ~2.222
|
||||
.k = 4.5,
|
||||
};
|
||||
}
|
||||
};
|
||||
|
@ -99,21 +107,21 @@ struct YcbcrDesc final {
|
|||
float uPlusHalf = 240 / 255.0;
|
||||
|
||||
auto Members() const { return std::tie(y0, y1, u0, uPlusHalf); }
|
||||
INLINE_AUTO_MAPPABLE(YcbcrDesc)
|
||||
MOZ_MIXIN_DERIVE_CMP_OPS_BY_MEMBERS(YcbcrDesc)
|
||||
|
||||
static constexpr auto Narrow8() { // AKA limited/studio/tv
|
||||
return YcbcrDesc();
|
||||
}
|
||||
static constexpr auto Full8() { // AKA pc
|
||||
return YcbcrDesc{
|
||||
0 / 255.0,
|
||||
255 / 255.0,
|
||||
128 / 255.0,
|
||||
254 / 255.0,
|
||||
.y0 = 0 / 255.0,
|
||||
.y1 = 255 / 255.0,
|
||||
.u0 = 128 / 255.0,
|
||||
.uPlusHalf = 254 / 255.0,
|
||||
};
|
||||
}
|
||||
static constexpr auto Float() { // Best for a LUT
|
||||
return YcbcrDesc{0.0, 1.0, 0.5, 1.0};
|
||||
return YcbcrDesc{.y0 = 0.0, .y1 = 1.0, .u0 = 0.5, .uPlusHalf = 1.0};
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -129,7 +137,7 @@ struct Chromaticities final {
|
|||
static constexpr float wy = 0.3290;
|
||||
|
||||
auto Members() const { return std::tie(rx, ry, gx, gy, bx, by); }
|
||||
INLINE_AUTO_MAPPABLE(Chromaticities)
|
||||
MOZ_MIXIN_DERIVE_CMP_OPS_BY_MEMBERS(Chromaticities)
|
||||
|
||||
// -
|
||||
|
||||
|
@ -145,23 +153,32 @@ struct Chromaticities final {
|
|||
}
|
||||
static constexpr auto Rec601_525_Ntsc() {
|
||||
return Chromaticities{
|
||||
0.630, 0.340, // r
|
||||
0.310, 0.595, // g
|
||||
0.155, 0.070, // b
|
||||
.rx = 0.630,
|
||||
.ry = 0.340, // r
|
||||
.gx = 0.310,
|
||||
.gy = 0.595, // g
|
||||
.bx = 0.155,
|
||||
.by = 0.070, // b
|
||||
};
|
||||
}
|
||||
static constexpr auto Rec2020() {
|
||||
return Chromaticities{
|
||||
0.708, 0.292, // r
|
||||
0.170, 0.797, // g
|
||||
0.131, 0.046, // b
|
||||
.rx = 0.708,
|
||||
.ry = 0.292, // r
|
||||
.gx = 0.170,
|
||||
.gy = 0.797, // g
|
||||
.bx = 0.131,
|
||||
.by = 0.046, // b
|
||||
};
|
||||
}
|
||||
static constexpr auto DisplayP3() {
|
||||
return Chromaticities{
|
||||
0.680, 0.320, // r
|
||||
0.265, 0.690, // g
|
||||
0.150, 0.060, // b
|
||||
.rx = 0.680,
|
||||
.ry = 0.320, // r
|
||||
.gx = 0.265,
|
||||
.gy = 0.690, // g
|
||||
.bx = 0.150,
|
||||
.by = 0.060, // b
|
||||
};
|
||||
}
|
||||
};
|
||||
|
@ -173,7 +190,7 @@ struct YuvDesc final {
|
|||
YcbcrDesc ycbcr;
|
||||
|
||||
auto Members() const { return std::tie(yCoeffs, ycbcr); }
|
||||
INLINE_AUTO_MAPPABLE(YuvDesc);
|
||||
MOZ_MIXIN_DERIVE_CMP_OPS_BY_MEMBERS(YuvDesc)
|
||||
};
|
||||
|
||||
struct ColorspaceDesc final {
|
||||
|
@ -182,11 +199,30 @@ struct ColorspaceDesc final {
|
|||
std::optional<YuvDesc> yuv;
|
||||
|
||||
auto Members() const { return std::tie(chrom, tf, yuv); }
|
||||
INLINE_AUTO_MAPPABLE(ColorspaceDesc);
|
||||
MOZ_MIXIN_DERIVE_CMP_OPS_BY_MEMBERS(ColorspaceDesc)
|
||||
};
|
||||
|
||||
// -
|
||||
|
||||
} // namespace mozilla::color
|
||||
|
||||
#define _(X) \
|
||||
template <> \
|
||||
struct std::hash<X> : mozilla::StdHashMembers<X> {};
|
||||
|
||||
_(mozilla::color::YuvLumaCoeffs)
|
||||
_(mozilla::color::PiecewiseGammaDesc)
|
||||
_(mozilla::color::YcbcrDesc)
|
||||
_(mozilla::color::Chromaticities)
|
||||
_(mozilla::color::YuvDesc)
|
||||
_(mozilla::color::ColorspaceDesc)
|
||||
|
||||
#undef _
|
||||
|
||||
namespace mozilla::color {
|
||||
|
||||
// -
|
||||
|
||||
template <class TT, int NN>
|
||||
struct avec final {
|
||||
using T = TT;
|
||||
|
@ -335,6 +371,11 @@ auto max(const avec<T, N>& a, const avec<T, N>& b) {
|
|||
return ret;
|
||||
}
|
||||
|
||||
template <class T, int N>
|
||||
auto clamp(const avec<T, N>& v, const avec<T, N>& lo, const avec<T, N>& hi) {
|
||||
return max(lo, min(v, hi));
|
||||
}
|
||||
|
||||
template <class T, int N>
|
||||
auto floor(const avec<T, N>& a) {
|
||||
auto ret = avec<T, N>{};
|
||||
|
@ -404,6 +445,11 @@ struct mat final {
|
|||
}
|
||||
}
|
||||
|
||||
constexpr bool operator==(const mat& rhs) const {
|
||||
return this->rows == rhs.rows;
|
||||
}
|
||||
constexpr bool operator!=(const mat& rhs) const { return !(*this == rhs); }
|
||||
|
||||
const auto& at(const int x, const int y) const { return rows.at(y)[x]; }
|
||||
auto& at(const int x, const int y) { return rows.at(y)[x]; }
|
||||
|
||||
|
@ -722,17 +768,19 @@ inline float SampleOutByIn(const C& outByIn, const float in) {
|
|||
return outByIn.at(0);
|
||||
}
|
||||
MOZ_ASSERT(outByIn.size() >= 2);
|
||||
const auto begin = outByIn.begin();
|
||||
|
||||
const auto in0i = size_t(floorf(in * (outByIn.size() - 1)));
|
||||
const auto out0_itr = begin + std::min(in0i, outByIn.size() - 2);
|
||||
// Estimate based on nearest (first) derivative:
|
||||
// Find the nearest point to `in` in `outByIn`.
|
||||
const auto inId = in * (outByIn.size() - 1);
|
||||
const auto inId0F = std::clamp(floorf(inId), 0.f, float(outByIn.size() - 2));
|
||||
const auto inId0 = size_t(inId0F);
|
||||
const auto out0 = outByIn.at(inId0 + 0);
|
||||
const auto out1 = outByIn.at(inId0 + 1);
|
||||
const auto d_inId0 = float(1);
|
||||
const auto d_out0 = out1 - out0;
|
||||
const auto d_inId = inId - inId0;
|
||||
|
||||
const auto in0 = float(out0_itr - begin) / (outByIn.size() - 1);
|
||||
const auto out0 = *out0_itr;
|
||||
const auto d_in = float(1) / (outByIn.size() - 1);
|
||||
const auto d_out = *(out0_itr + 1) - *out0_itr;
|
||||
|
||||
const auto out = out0 + (d_out / d_in) * (in - in0);
|
||||
const auto out = out0 + (d_out0 / d_inId0) * d_inId;
|
||||
// printf("SampleOutByIn(%f)->%f\n", in, out);
|
||||
return out;
|
||||
}
|
||||
|
@ -963,7 +1011,7 @@ struct ColorProfileConversionDesc {
|
|||
};
|
||||
static ColorProfileConversionDesc From(const FromDesc&);
|
||||
|
||||
vec3 Apply(const vec3 src) const {
|
||||
vec3 DstFromSrc(const vec3 src) const {
|
||||
const auto srcRgb = vec3(srcRgbFromSrcYuv * vec4(src, 1));
|
||||
const auto srcLinear = vec3{{
|
||||
SampleOutByIn(srcLinearFromSrcTf.r, srcRgb.x()),
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
#include "mozilla/Preferences.h"
|
||||
#include "mozilla/StaticPrefs_gfx.h"
|
||||
#include "mozilla/UniquePtr.h"
|
||||
#include "mozilla/gfx/BuildConstants.h"
|
||||
#include "mozilla/gfx/Logging.h"
|
||||
#include "mozilla/gfx/Matrix.h"
|
||||
#include "mozilla/layers/ImageDataSerializer.h"
|
||||
|
@ -189,16 +190,16 @@ const char* const kFragConvert_ColorMatrix = R"(
|
|||
return (uColorMatrix * vec4(src, 1)).rgb;
|
||||
}
|
||||
)";
|
||||
const char* const kFragConvert_ColorLut = R"(
|
||||
const char* const kFragConvert_ColorLut3d = R"(
|
||||
uniform PRECISION sampler3D uColorLut;
|
||||
|
||||
vec3 metaConvert(vec3 src) {
|
||||
// Half-texel filtering hazard!
|
||||
// E.g. For texture size of 2,
|
||||
// E.g. 0.5/2=0.25 is still sampling 100% of texel 0, 0% of texel 1.
|
||||
// For the LUT, we need 0.5/2=0.25 to filter 25/75 texel 0 and 1.
|
||||
// That is, we need to adjust our sampling point such that it's 0.25 of the
|
||||
// way from texel 0's center to texel 1's center.
|
||||
// E.g. x=0.25 is still sampling 100% of texel x=0, 0% of texel x=1.
|
||||
// For the LUT, we need r=0.25 to filter 75/25 from texel 0 and 1.
|
||||
// That is, we need to adjust our sampling point such that it starts in the
|
||||
// center of texel 0, and ends in the center of texel N-1.
|
||||
// We need, for N=2:
|
||||
// v=0.0|N=2 => v'=0.5/2
|
||||
// v=1.0|N=2 => v'=1.5/2
|
||||
|
@ -211,6 +212,44 @@ const char* const kFragConvert_ColorLut = R"(
|
|||
return texture(uColorLut, src).rgb;
|
||||
}
|
||||
)";
|
||||
// Delete if unused after 2024-10-01:
|
||||
const char* const kFragConvert_ColorLut2d = R"(
|
||||
uniform PRECISION sampler2D uColorLut;
|
||||
uniform mediump vec3 uColorLut3dSize;
|
||||
|
||||
vec3 metaConvert(vec3 src) {
|
||||
// Half-texel filtering hazard!
|
||||
// E.g. For texture size of 2,
|
||||
// E.g. x=0.25 is still sampling 100% of texel x=0, 0% of texel x=1.
|
||||
// For the LUT, we need r=0.25 to filter 75/25 from texel 0 and 1.
|
||||
// That is, we need to adjust our sampling point such that it starts in the
|
||||
// center of texel 0, and ends in the center of texel N-1.
|
||||
// We need, for N=2:
|
||||
// v=0.0|N=2 => v'=0.5/2
|
||||
// v=1.0|N=2 => v'=1.5/2
|
||||
// For N=3:
|
||||
// v=0.0|N=3 => v'=0.5/3
|
||||
// v=1.0|N=3 => v'=2.5/3
|
||||
// => v' = ( 0.5 + v * (3 - 1) )/3
|
||||
src = clamp(src, vec3(0,0,0), vec3(1,1,1));
|
||||
vec3 lut3dSize = uColorLut3dSize;
|
||||
vec2 lut2dSize = vec2(lut3dSize.x, lut3dSize.y * lut3dSize.z);
|
||||
vec3 texelSrc3d = 0.5 + src * (lut3dSize - 1.0);
|
||||
|
||||
vec3 texelSrc3d_zFloor = texelSrc3d;
|
||||
texelSrc3d_zFloor.z = floor(texelSrc3d_zFloor.z);
|
||||
vec3 texelSrc3d_zNext = texelSrc3d_zFloor + vec3(0,0,1);
|
||||
texelSrc3d_zNext.z = min(texelSrc3d_zNext.z, lut3dSize.z - 1.0);
|
||||
|
||||
vec2 texelSrc2d_zFloor = texelSrc3d_zFloor.xy + vec2(0, texelSrc3d_zFloor.z * lut3dSize.y);
|
||||
vec2 texelSrc2d_zNext = texelSrc3d_zNext.xy + vec2(0, texelSrc3d_zNext.z * lut3dSize.y);
|
||||
|
||||
vec4 dst_zFloor = texture(uColorLut, texelSrc2d_zFloor / lut2dSize);
|
||||
vec4 dst_zNext = texture(uColorLut, texelSrc2d_zNext / lut2dSize);
|
||||
|
||||
return mix(dst_zFloor, dst_zNext, texelSrc3d.z - texelSrc3d_zFloor.z);
|
||||
}
|
||||
)";
|
||||
|
||||
// -
|
||||
|
||||
|
@ -277,13 +316,13 @@ Mat3 SubRectMat3(const gfx::IntRect& bigSubrect, const gfx::IntSize& smallSize,
|
|||
// --
|
||||
|
||||
ScopedSaveMultiTex::ScopedSaveMultiTex(GLContext* const gl,
|
||||
const std::vector<uint8_t>& texUnits,
|
||||
const size_t texUnits,
|
||||
const GLenum texTarget)
|
||||
: mGL(*gl),
|
||||
mTexUnits(texUnits),
|
||||
mTexTarget(texTarget),
|
||||
mOldTexUnit(mGL.GetIntAs<GLenum>(LOCAL_GL_ACTIVE_TEXTURE)) {
|
||||
MOZ_RELEASE_ASSERT(texUnits.size() >= 1);
|
||||
MOZ_RELEASE_ASSERT(texUnits >= 1);
|
||||
|
||||
GLenum texBinding;
|
||||
switch (mTexTarget) {
|
||||
|
@ -304,12 +343,11 @@ ScopedSaveMultiTex::ScopedSaveMultiTex(GLContext* const gl,
|
|||
MOZ_CRASH();
|
||||
}
|
||||
|
||||
for (const auto i : IntegerRange(mTexUnits.size())) {
|
||||
const auto& unit = mTexUnits[i];
|
||||
mGL.fActiveTexture(LOCAL_GL_TEXTURE0 + unit);
|
||||
for (const auto i : IntegerRange(mTexUnits)) {
|
||||
mGL.fActiveTexture(LOCAL_GL_TEXTURE0 + i);
|
||||
if (mGL.IsSupported(GLFeature::sampler_objects)) {
|
||||
mOldTexSampler[i] = mGL.GetIntAs<GLuint>(LOCAL_GL_SAMPLER_BINDING);
|
||||
mGL.fBindSampler(unit, 0);
|
||||
mGL.fBindSampler(i, 0);
|
||||
}
|
||||
mOldTex[i] = mGL.GetIntAs<GLuint>(texBinding);
|
||||
}
|
||||
|
@ -319,11 +357,10 @@ ScopedSaveMultiTex::~ScopedSaveMultiTex() {
|
|||
// Unbind in reverse order, in case we have repeats.
|
||||
// Order matters because we unbound samplers during ctor, so now we have to
|
||||
// make sure we rebind them in the right order.
|
||||
for (const auto i : Reversed(IntegerRange(mTexUnits.size()))) {
|
||||
const auto& unit = mTexUnits[i];
|
||||
mGL.fActiveTexture(LOCAL_GL_TEXTURE0 + unit);
|
||||
for (const auto i : Reversed(IntegerRange(mTexUnits))) {
|
||||
mGL.fActiveTexture(LOCAL_GL_TEXTURE0 + i);
|
||||
if (mGL.IsSupported(GLFeature::sampler_objects)) {
|
||||
mGL.fBindSampler(unit, mOldTexSampler[i]);
|
||||
mGL.fBindSampler(i, mOldTexSampler[i]);
|
||||
}
|
||||
mGL.fBindTexture(mTexTarget, mOldTex[i]);
|
||||
}
|
||||
|
@ -520,11 +557,6 @@ void DrawBlitProg::Draw(const BaseArgs& args,
|
|||
gl->fUniformMatrix3fv(mLoc_uDestMatrix, 1, false, destMatrix.m);
|
||||
gl->fUniformMatrix3fv(mLoc_uTexMatrix0, 1, false, args.texMatrix0.m);
|
||||
|
||||
if (args.texUnitForColorLut) {
|
||||
gl->fUniform1i(mLoc_uColorLut,
|
||||
AssertedCast<GLint>(*args.texUnitForColorLut));
|
||||
}
|
||||
|
||||
MOZ_ASSERT(bool(argsYUV) == (mLoc_uColorMatrix != -1));
|
||||
if (argsYUV) {
|
||||
gl->fUniformMatrix3fv(mLoc_uTexMatrix1, 1, false, argsYUV->texMatrix1.m);
|
||||
|
@ -684,10 +716,6 @@ GLBlitHelper::GLBlitHelper(GLContext* const gl)
|
|||
}
|
||||
|
||||
GLBlitHelper::~GLBlitHelper() {
|
||||
for (const auto& pair : mDrawBlitProgs) {
|
||||
const auto& ptr = pair.second;
|
||||
delete ptr;
|
||||
}
|
||||
mDrawBlitProgs.clear();
|
||||
|
||||
if (!mGL->MakeCurrent()) return;
|
||||
|
@ -702,18 +730,16 @@ GLBlitHelper::~GLBlitHelper() {
|
|||
|
||||
// --
|
||||
|
||||
const DrawBlitProg* GLBlitHelper::GetDrawBlitProg(
|
||||
const DrawBlitProg& GLBlitHelper::GetDrawBlitProg(
|
||||
const DrawBlitProg::Key& key) const {
|
||||
const auto& res = mDrawBlitProgs.insert({key, nullptr});
|
||||
auto& pair = *(res.first);
|
||||
const auto& didInsert = res.second;
|
||||
if (didInsert) {
|
||||
pair.second = CreateDrawBlitProg(pair.first);
|
||||
auto& ret = mDrawBlitProgs[key];
|
||||
if (!ret) {
|
||||
ret = CreateDrawBlitProg(key);
|
||||
}
|
||||
return pair.second;
|
||||
return *ret;
|
||||
}
|
||||
|
||||
const DrawBlitProg* GLBlitHelper::CreateDrawBlitProg(
|
||||
std::unique_ptr<const DrawBlitProg> GLBlitHelper::CreateDrawBlitProg(
|
||||
const DrawBlitProg::Key& key) const {
|
||||
const auto precisionPref = StaticPrefs::gfx_blithelper_precision();
|
||||
const char* precision;
|
||||
|
@ -790,7 +816,7 @@ const DrawBlitProg* GLBlitHelper::CreateDrawBlitProg(
|
|||
mGL->fUniform1i(loc, i);
|
||||
}
|
||||
|
||||
return new DrawBlitProg(this, prog);
|
||||
return std::make_unique<DrawBlitProg>(this, prog);
|
||||
}
|
||||
|
||||
GLuint progLogLen = 0;
|
||||
|
@ -997,7 +1023,7 @@ bool GLBlitHelper::Blit(const java::GeckoSurfaceTexture::Ref& surfaceTexture,
|
|||
{kFragHeader_TexExt, {kFragSample_OnePlane, kFragConvert_None}});
|
||||
const DrawBlitProg::BaseArgs baseArgs = {transform3, yFlip, destSize,
|
||||
Nothing()};
|
||||
prog->Draw(baseArgs, nullptr);
|
||||
prog.Draw(baseArgs, nullptr);
|
||||
|
||||
if (surfaceTexture->IsSingleBuffer()) {
|
||||
surfaceTexture->ReleaseTexImage();
|
||||
|
@ -1087,7 +1113,7 @@ bool GLBlitHelper::BlitPlanarYCbCr(const PlanarYCbCrData& yuvData,
|
|||
|
||||
// --
|
||||
|
||||
const ScopedSaveMultiTex saveTex(mGL, {0, 1, 2}, LOCAL_GL_TEXTURE_2D);
|
||||
const ScopedSaveMultiTex saveTex(mGL, 3, LOCAL_GL_TEXTURE_2D);
|
||||
const ResetUnpackState reset(mGL);
|
||||
const gfx::IntSize yTexSize(yuvData.mYStride, yuvData.YDataSize().height);
|
||||
const gfx::IntSize uvTexSize(yuvData.mCbCrStride,
|
||||
|
@ -1139,7 +1165,7 @@ bool GLBlitHelper::BlitPlanarYCbCr(const PlanarYCbCrData& yuvData,
|
|||
yFlip, destSize, Nothing()};
|
||||
const DrawBlitProg::YUVArgs yuvArgs = {
|
||||
SubRectMat3(clipRect, uvTexSize, divisors), Some(yuvData.mYUVColorSpace)};
|
||||
prog->Draw(baseArgs, &yuvArgs);
|
||||
prog.Draw(baseArgs, &yuvArgs);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -1197,11 +1223,7 @@ bool GLBlitHelper::BlitImage(MacIOSurface* const iosurf,
|
|||
|
||||
const GLenum texTarget = LOCAL_GL_TEXTURE_RECTANGLE;
|
||||
|
||||
std::vector<uint8_t> texUnits;
|
||||
for (uint8_t i = 0; i < planes; i++) {
|
||||
texUnits.push_back(i);
|
||||
}
|
||||
const ScopedSaveMultiTex saveTex(mGL, texUnits, texTarget);
|
||||
const ScopedSaveMultiTex saveTex(mGL, planes, texTarget);
|
||||
const ScopedTexture tex0(mGL);
|
||||
const ScopedTexture tex1(mGL);
|
||||
const ScopedTexture tex2(mGL);
|
||||
|
@ -1282,7 +1304,7 @@ bool GLBlitHelper::BlitImage(MacIOSurface* const iosurf,
|
|||
kFragHeader_Tex2DRect,
|
||||
{fragSample, kFragConvert_ColorMatrix},
|
||||
});
|
||||
prog->Draw(baseArgs, pYuvArgs);
|
||||
prog.Draw(baseArgs, pYuvArgs);
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
@ -1315,14 +1337,14 @@ void GLBlitHelper::DrawBlitTextureToFramebuffer(const GLuint srcTex,
|
|||
{kFragSample_OnePlane, fragConvert},
|
||||
});
|
||||
|
||||
const ScopedSaveMultiTex saveTex(mGL, {0}, srcTarget);
|
||||
const ScopedSaveMultiTex saveTex(mGL, 1, srcTarget);
|
||||
mGL->fActiveTexture(LOCAL_GL_TEXTURE0);
|
||||
mGL->fBindTexture(srcTarget, srcTex);
|
||||
|
||||
const bool yFlip = false;
|
||||
const DrawBlitProg::BaseArgs baseArgs = {texMatrix0, yFlip, destSize,
|
||||
Nothing()};
|
||||
prog->Draw(baseArgs);
|
||||
prog.Draw(baseArgs);
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
@ -1519,11 +1541,7 @@ bool GLBlitHelper::Blit(DMABufSurface* surface, const gfx::IntSize& destSize,
|
|||
|
||||
const GLenum texTarget = LOCAL_GL_TEXTURE_2D;
|
||||
|
||||
std::vector<uint8_t> texUnits;
|
||||
for (uint8_t i = 0; i < planes; i++) {
|
||||
texUnits.push_back(i);
|
||||
}
|
||||
const ScopedSaveMultiTex saveTex(mGL, texUnits, texTarget);
|
||||
const ScopedSaveMultiTex saveTex(mGL, planes, texTarget);
|
||||
const auto pixelFormat = surface->GetSurfaceType();
|
||||
|
||||
const char* fragSample;
|
||||
|
@ -1560,7 +1578,7 @@ bool GLBlitHelper::Blit(DMABufSurface* surface, const gfx::IntSize& destSize,
|
|||
|
||||
const auto& prog =
|
||||
GetDrawBlitProg({kFragHeader_Tex2D, {fragSample, fragConvert}});
|
||||
prog->Draw(baseArgs, pYuvArgs);
|
||||
prog.Draw(baseArgs, pYuvArgs);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -1603,23 +1621,205 @@ static uint32_t toRgb10A2(const color::vec4& val) {
|
|||
return ret;
|
||||
}
|
||||
|
||||
std::shared_ptr<gl::Texture> GLBlitHelper::GetColorLutTex(
|
||||
const ColorLutKey& key) const {
|
||||
auto& weak = mColorLutTexMap[key];
|
||||
auto strong = weak.lock();
|
||||
if (!strong) {
|
||||
auto& gl = *mGL;
|
||||
strong = std::make_shared<gl::Texture>(gl);
|
||||
weak = strong;
|
||||
// -
|
||||
|
||||
const auto ct = color::ColorspaceTransform::Create(key.src, key.dst);
|
||||
color::ColorspaceDesc ToColorspaceDesc(const gfx::YUVRangedColorSpace cs) {
|
||||
switch (cs) {
|
||||
case gfx::YUVRangedColorSpace::BT601_Narrow:
|
||||
return {
|
||||
.chrom = color::Chromaticities::Rec601_525_Ntsc(),
|
||||
.tf = color::PiecewiseGammaDesc::Rec709(),
|
||||
.yuv =
|
||||
color::YuvDesc{
|
||||
.yCoeffs = color::YuvLumaCoeffs::Rec709(),
|
||||
.ycbcr = color::YcbcrDesc::Narrow8(),
|
||||
},
|
||||
};
|
||||
case gfx::YUVRangedColorSpace::BT601_Full:
|
||||
return {
|
||||
.chrom = color::Chromaticities::Rec601_525_Ntsc(),
|
||||
.tf = color::PiecewiseGammaDesc::Rec709(),
|
||||
.yuv =
|
||||
color::YuvDesc{
|
||||
.yCoeffs = color::YuvLumaCoeffs::Rec709(),
|
||||
.ycbcr = color::YcbcrDesc::Full8(),
|
||||
},
|
||||
};
|
||||
case gfx::YUVRangedColorSpace::BT709_Narrow:
|
||||
return {
|
||||
.chrom = color::Chromaticities::Rec709(),
|
||||
.tf = color::PiecewiseGammaDesc::Rec709(),
|
||||
.yuv =
|
||||
color::YuvDesc{
|
||||
.yCoeffs = color::YuvLumaCoeffs::Rec709(),
|
||||
.ycbcr = color::YcbcrDesc::Narrow8(),
|
||||
},
|
||||
};
|
||||
case gfx::YUVRangedColorSpace::BT709_Full:
|
||||
return {
|
||||
.chrom = color::Chromaticities::Rec709(),
|
||||
.tf = color::PiecewiseGammaDesc::Rec709(),
|
||||
.yuv =
|
||||
color::YuvDesc{
|
||||
.yCoeffs = color::YuvLumaCoeffs::Rec709(),
|
||||
.ycbcr = color::YcbcrDesc::Full8(),
|
||||
},
|
||||
};
|
||||
case gfx::YUVRangedColorSpace::BT2020_Narrow:
|
||||
return {
|
||||
.chrom = color::Chromaticities::Rec2020(),
|
||||
.tf = color::PiecewiseGammaDesc::Rec2020_12bit(),
|
||||
.yuv =
|
||||
color::YuvDesc{
|
||||
.yCoeffs = color::YuvLumaCoeffs::Rec709(),
|
||||
.ycbcr = color::YcbcrDesc::Narrow8(),
|
||||
},
|
||||
};
|
||||
case gfx::YUVRangedColorSpace::BT2020_Full:
|
||||
return {
|
||||
.chrom = color::Chromaticities::Rec2020(),
|
||||
.tf = color::PiecewiseGammaDesc::Rec2020_12bit(),
|
||||
.yuv =
|
||||
color::YuvDesc{
|
||||
.yCoeffs = color::YuvLumaCoeffs::Rec2020(),
|
||||
.ycbcr = color::YcbcrDesc::Full8(),
|
||||
},
|
||||
};
|
||||
case gfx::YUVRangedColorSpace::GbrIdentity:
|
||||
return {
|
||||
.chrom = color::Chromaticities::Rec709(),
|
||||
.tf = color::PiecewiseGammaDesc::Rec709(),
|
||||
.yuv =
|
||||
color::YuvDesc{
|
||||
.yCoeffs = color::YuvLumaCoeffs::Gbr(),
|
||||
.ycbcr = color::YcbcrDesc::Full8(),
|
||||
},
|
||||
};
|
||||
}
|
||||
MOZ_CRASH("Bad YUVRangedColorSpace.");
|
||||
}
|
||||
|
||||
static std::optional<color::ColorProfileDesc> ToColorProfileDesc(
|
||||
gfx::ColorSpace2);
|
||||
|
||||
} // namespace gl
|
||||
namespace gfx {
|
||||
|
||||
color::ColorProfileDesc QueryOutputColorProfile();
|
||||
|
||||
} // namespace gfx
|
||||
namespace gl {
|
||||
|
||||
// -
|
||||
|
||||
static std::optional<color::ColorProfileDesc> ToColorProfileDesc(
|
||||
const gfx::ColorSpace2 cspace) {
|
||||
color::ColorspaceDesc cspaceDesc;
|
||||
switch (cspace) {
|
||||
case gfx::ColorSpace2::Display:
|
||||
if (kIsWindows) {
|
||||
#ifdef XP_WIN
|
||||
return gfx::QueryOutputColorProfile();
|
||||
#endif
|
||||
}
|
||||
return {};
|
||||
|
||||
case gfx::ColorSpace2::SRGB:
|
||||
cspaceDesc = {.chrom = color::Chromaticities::Srgb(),
|
||||
.tf = color::PiecewiseGammaDesc::Srgb()};
|
||||
break;
|
||||
case gfx::ColorSpace2::DISPLAY_P3:
|
||||
cspaceDesc = {.chrom = color::Chromaticities::DisplayP3(),
|
||||
.tf = color::PiecewiseGammaDesc::DisplayP3()};
|
||||
break;
|
||||
case gfx::ColorSpace2::BT601_525: // aka smpte170m NTSC
|
||||
cspaceDesc = {.chrom = color::Chromaticities::Rec601_525_Ntsc(),
|
||||
.tf = color::PiecewiseGammaDesc::Rec709()};
|
||||
break;
|
||||
case gfx::ColorSpace2::BT709: // Same gamut as SRGB, but different gamma.
|
||||
cspaceDesc = {.chrom = color::Chromaticities::Rec709(),
|
||||
.tf = color::PiecewiseGammaDesc::Rec709()};
|
||||
break;
|
||||
case gfx::ColorSpace2::BT2020:
|
||||
cspaceDesc = {.chrom = color::Chromaticities::Rec2020(),
|
||||
.tf = color::PiecewiseGammaDesc::Rec2020_12bit()};
|
||||
break;
|
||||
}
|
||||
const auto profileDesc = color::ColorProfileDesc::From(cspaceDesc);
|
||||
return profileDesc;
|
||||
}
|
||||
|
||||
// -
|
||||
|
||||
// For std::visit
|
||||
template <class... Ts>
|
||||
struct overloaded : Ts... {
|
||||
using Ts::operator()...;
|
||||
};
|
||||
// explicit deduction guide (not needed as of C++20)
|
||||
template <class... Ts>
|
||||
overloaded(Ts...) -> overloaded<Ts...>;
|
||||
|
||||
// -
|
||||
|
||||
template <typename C, typename K>
|
||||
inline auto MaybeFind(C& container, const K& key)
|
||||
-> decltype(&(container.find(key)->second)) {
|
||||
const auto itr = container.find(key);
|
||||
if (itr == container.end()) return nullptr;
|
||||
return &(itr->second);
|
||||
}
|
||||
|
||||
// -
|
||||
|
||||
std::shared_ptr<gl::Texture> GLBlitHelper::GetColorLutTex(
|
||||
const ColorLutKey& request) const {
|
||||
if (const auto found = MaybeFind(mColorLutTexMap, request)) {
|
||||
return *found; // Might be *Some(nullptr) -> nullptr!
|
||||
}
|
||||
|
||||
return mColorLutTexMap[request] = [&]() -> std::shared_ptr<gl::Texture> {
|
||||
auto& gl = *mGL;
|
||||
const auto tex = std::make_shared<gl::Texture>(gl);
|
||||
|
||||
// -
|
||||
|
||||
const std::optional<color::ColorProfileDesc> srcProfile =
|
||||
std::visit(overloaded{
|
||||
[&](const gfx::ColorSpace2& cs)
|
||||
-> std::optional<color::ColorProfileDesc> {
|
||||
MOZ_ASSERT(cs != request.dst);
|
||||
const auto cpd = ToColorProfileDesc(cs);
|
||||
return cpd;
|
||||
},
|
||||
[&](const gfx::YUVRangedColorSpace& cs)
|
||||
-> std::optional<color::ColorProfileDesc> {
|
||||
const auto csd = ToColorspaceDesc(cs);
|
||||
const auto cpd = color::ColorProfileDesc::From(csd);
|
||||
return cpd;
|
||||
},
|
||||
},
|
||||
request.src);
|
||||
MOZ_ASSERT(srcProfile);
|
||||
|
||||
const auto dstProfile = ToColorProfileDesc(request.dst);
|
||||
if (kIsWindows) {
|
||||
MOZ_ASSERT(dstProfile);
|
||||
}
|
||||
if (!srcProfile || !dstProfile) return nullptr;
|
||||
const auto conversion = color::ColorProfileConversionDesc::From({
|
||||
.src = *srcProfile,
|
||||
.dst = *dstProfile,
|
||||
});
|
||||
|
||||
// -
|
||||
|
||||
const auto minLutSize = color::ivec3{2};
|
||||
const auto maxLutSize = color::ivec3{256};
|
||||
auto lutSize = minLutSize;
|
||||
if (ct.srcSpace.yuv) {
|
||||
const bool isYcbcr =
|
||||
(conversion.srcRgbFromSrcYuv != color::mat4::Identity());
|
||||
if (isYcbcr) {
|
||||
lutSize.x(int(StaticPrefs::gfx_blithelper_lut_size_ycbcr_y()));
|
||||
lutSize.y(int(StaticPrefs::gfx_blithelper_lut_size_ycbcr_cb()));
|
||||
lutSize.z(int(StaticPrefs::gfx_blithelper_lut_size_ycbcr_cr()));
|
||||
|
@ -1628,15 +1828,20 @@ std::shared_ptr<gl::Texture> GLBlitHelper::GetColorLutTex(
|
|||
lutSize.y(int(StaticPrefs::gfx_blithelper_lut_size_rgb_g()));
|
||||
lutSize.z(int(StaticPrefs::gfx_blithelper_lut_size_rgb_b()));
|
||||
}
|
||||
lutSize = max(minLutSize, min(lutSize, maxLutSize)); // Clamp
|
||||
lutSize = clamp(lutSize, minLutSize, maxLutSize);
|
||||
|
||||
const auto lut = ct.ToLut3(lutSize);
|
||||
const auto lut = [&]() {
|
||||
auto lut = color::Lut3::Create(lutSize);
|
||||
lut.SetMap(
|
||||
[&](const color::vec3& src) { return conversion.DstFromSrc(src); });
|
||||
return lut;
|
||||
}();
|
||||
const auto& size = lut.size;
|
||||
|
||||
// -
|
||||
|
||||
constexpr GLenum target = LOCAL_GL_TEXTURE_3D;
|
||||
const auto bind = gl::ScopedBindTexture(&gl, strong->name, target);
|
||||
const auto bind = gl::ScopedBindTexture(&gl, tex->name, target);
|
||||
gl.fTexParameteri(target, LOCAL_GL_TEXTURE_WRAP_S, LOCAL_GL_CLAMP_TO_EDGE);
|
||||
gl.fTexParameteri(target, LOCAL_GL_TEXTURE_WRAP_T, LOCAL_GL_CLAMP_TO_EDGE);
|
||||
gl.fTexParameteri(target, LOCAL_GL_TEXTURE_WRAP_R, LOCAL_GL_CLAMP_TO_EDGE);
|
||||
|
@ -1673,8 +1878,8 @@ std::shared_ptr<gl::Texture> GLBlitHelper::GetColorLutTex(
|
|||
LOCAL_GL_RGBA, LOCAL_GL_UNSIGNED_INT_2_10_10_10_REV,
|
||||
uploadData.data());
|
||||
}
|
||||
}
|
||||
return strong;
|
||||
return tex;
|
||||
}();
|
||||
}
|
||||
|
||||
} // namespace gl
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
#include <map>
|
||||
#include <memory>
|
||||
#include <unordered_map>
|
||||
#include <variant>
|
||||
#include "Colorspaces.h"
|
||||
#include "GLConsts.h"
|
||||
#include "GLContextTypes.h"
|
||||
|
@ -126,6 +127,8 @@ Mat3 SubRectMat3(const gfx::IntRect& bigSubrect, const gfx::IntSize& smallSize,
|
|||
|
||||
class DrawBlitProg final {
|
||||
const GLBlitHelper& mParent;
|
||||
|
||||
public:
|
||||
const GLuint mProg;
|
||||
const GLint mLoc_uDestMatrix;
|
||||
const GLint mLoc_uTexMatrix0;
|
||||
|
@ -154,7 +157,6 @@ class DrawBlitProg final {
|
|||
gfx::IntSize
|
||||
destSize; // Always needed for (at least) setting the viewport.
|
||||
Maybe<gfx::IntRect> destRect;
|
||||
Maybe<uint32_t> texUnitForColorLut;
|
||||
};
|
||||
struct YUVArgs final {
|
||||
Mat3 texMatrix1;
|
||||
|
@ -166,15 +168,14 @@ class DrawBlitProg final {
|
|||
|
||||
class ScopedSaveMultiTex final {
|
||||
GLContext& mGL;
|
||||
const std::vector<uint8_t> mTexUnits;
|
||||
const size_t mTexUnits;
|
||||
const GLenum mTexTarget;
|
||||
const GLuint mOldTexUnit;
|
||||
GLuint mOldTexSampler[3];
|
||||
GLuint mOldTex[3];
|
||||
|
||||
public:
|
||||
ScopedSaveMultiTex(GLContext* gl, const std::vector<uint8_t>& texUnits,
|
||||
GLenum texTarget);
|
||||
ScopedSaveMultiTex(GLContext* gl, size_t texUnits, GLenum texTarget);
|
||||
~ScopedSaveMultiTex();
|
||||
};
|
||||
|
||||
|
@ -185,7 +186,8 @@ class GLBlitHelper final {
|
|||
friend class GLContext;
|
||||
|
||||
GLContext* const mGL;
|
||||
mutable std::map<DrawBlitProg::Key, const DrawBlitProg*> mDrawBlitProgs;
|
||||
mutable std::map<DrawBlitProg::Key, std::unique_ptr<const DrawBlitProg>>
|
||||
mDrawBlitProgs;
|
||||
|
||||
GLuint mQuadVAO = 0;
|
||||
GLuint mQuadVBO = 0;
|
||||
|
@ -197,16 +199,19 @@ class GLBlitHelper final {
|
|||
gfx::IntSize mYuvUploads_UVSize = {0, 0};
|
||||
|
||||
public:
|
||||
struct ColorLutKey {
|
||||
color::ColorspaceDesc src;
|
||||
color::ColorspaceDesc dst;
|
||||
struct ColorLutKey : DeriveCmpOpMembers<ColorLutKey> {
|
||||
std::variant<gfx::ColorSpace2, gfx::YUVRangedColorSpace> src;
|
||||
gfx::ColorSpace2 dst;
|
||||
|
||||
auto Members() const { return std::tie(src, dst); }
|
||||
INLINE_AUTO_MAPPABLE(ColorLutKey)
|
||||
|
||||
MOZ_MIXIN_DERIVE_CMP_OPS_BY_MEMBERS(ColorLutKey)
|
||||
|
||||
struct Hasher : mozilla::StdHashMembers<ColorLutKey> {};
|
||||
};
|
||||
|
||||
private:
|
||||
mutable std::unordered_map<ColorLutKey, std::weak_ptr<gl::Texture>,
|
||||
mutable std::unordered_map<ColorLutKey, std::shared_ptr<gl::Texture>,
|
||||
ColorLutKey::Hasher>
|
||||
mColorLutTexMap;
|
||||
|
||||
|
@ -219,10 +224,11 @@ class GLBlitHelper final {
|
|||
ID3D11Device* GetD3D11() const;
|
||||
#endif
|
||||
|
||||
const DrawBlitProg* GetDrawBlitProg(const DrawBlitProg::Key& key) const;
|
||||
const DrawBlitProg& GetDrawBlitProg(const DrawBlitProg::Key& key) const;
|
||||
|
||||
private:
|
||||
const DrawBlitProg* CreateDrawBlitProg(const DrawBlitProg::Key& key) const;
|
||||
std::unique_ptr<const DrawBlitProg> CreateDrawBlitProg(
|
||||
const DrawBlitProg::Key& key) const;
|
||||
|
||||
public:
|
||||
bool BlitPlanarYCbCr(const layers::PlanarYCbCrData&,
|
||||
|
@ -326,7 +332,8 @@ extern const char* const kFragSample_ThreePlane;
|
|||
extern const char* const kFragConvert_None;
|
||||
extern const char* const kFragConvert_BGR;
|
||||
extern const char* const kFragConvert_ColorMatrix;
|
||||
extern const char* const kFragConvert_ColorLut;
|
||||
extern const char* const kFragConvert_ColorLut3d;
|
||||
extern const char* const kFragConvert_ColorLut2d;
|
||||
|
||||
extern const char* const kFragMixin_AlphaMultColors;
|
||||
extern const char* const kFragMixin_AlphaClampColors;
|
||||
|
|
|
@ -95,16 +95,7 @@ class BindAnglePlanes final {
|
|||
const EGLAttrib* const* postAttribsList = nullptr)
|
||||
: mParent(*parent),
|
||||
mNumPlanes(numPlanes),
|
||||
mMultiTex(
|
||||
mParent.mGL,
|
||||
[&]() {
|
||||
std::vector<uint8_t> ret;
|
||||
for (int i = 0; i < numPlanes; i++) {
|
||||
ret.push_back(i);
|
||||
}
|
||||
return ret;
|
||||
}(),
|
||||
LOCAL_GL_TEXTURE_EXTERNAL),
|
||||
mMultiTex(mParent.mGL, mNumPlanes, LOCAL_GL_TEXTURE_EXTERNAL),
|
||||
mTempTexs{0},
|
||||
mStreams{0},
|
||||
mSuccess(true) {
|
||||
|
@ -336,7 +327,7 @@ bool GLBlitHelper::BlitDescriptor(const layers::SurfaceDescriptorD3D10& desc,
|
|||
|
||||
const auto& prog = GetDrawBlitProg(
|
||||
{kFragHeader_TexExt, {kFragSample_TwoPlane, kFragConvert_ColorMatrix}});
|
||||
prog->Draw(baseArgs, &yuvArgs);
|
||||
prog.Draw(baseArgs, &yuvArgs);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -391,7 +382,7 @@ bool GLBlitHelper::BlitAngleYCbCr(const WindowsHandle (&handleList)[3],
|
|||
|
||||
const auto& prog = GetDrawBlitProg(
|
||||
{kFragHeader_TexExt, {kFragSample_ThreePlane, kFragConvert_ColorMatrix}});
|
||||
prog->Draw(baseArgs, &yuvArgs);
|
||||
prog.Draw(baseArgs, &yuvArgs);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -45,6 +45,12 @@
|
|||
#include "mozilla/GenericRefCounted.h"
|
||||
#include "mozilla/WeakPtr.h"
|
||||
|
||||
template <class ElemT, class... More>
|
||||
constexpr inline std::array<ElemT, 1 + sizeof...(More)> make_array(
|
||||
ElemT&& arg1, More&&... more) {
|
||||
return {std::forward<ElemT>(arg1), std::forward<ElemT>(more)...};
|
||||
}
|
||||
|
||||
#ifdef MOZ_WIDGET_ANDROID
|
||||
# include "mozilla/ProfilerLabels.h"
|
||||
#endif
|
||||
|
@ -797,8 +803,15 @@ class GLContext : public GenericAtomicRefCounted, public SupportsWeakPtr {
|
|||
AFTER_GL_CALL;
|
||||
}
|
||||
|
||||
void InvalidateFramebuffer(GLenum target) {
|
||||
constexpr auto ATTACHMENTS = make_array(GLenum{LOCAL_GL_COLOR_ATTACHMENT0},
|
||||
LOCAL_GL_DEPTH_STENCIL_ATTACHMENT);
|
||||
fInvalidateFramebuffer(target, ATTACHMENTS.size(), ATTACHMENTS.data());
|
||||
}
|
||||
|
||||
void fInvalidateFramebuffer(GLenum target, GLsizei numAttachments,
|
||||
const GLenum* attachments) {
|
||||
if (!mSymbols.fInvalidateFramebuffer) return;
|
||||
BeforeGLDrawCall();
|
||||
BEFORE_GL_CALL;
|
||||
ASSERT_SYMBOL_PRESENT(fInvalidateFramebuffer);
|
||||
|
@ -810,6 +823,7 @@ class GLContext : public GenericAtomicRefCounted, public SupportsWeakPtr {
|
|||
void fInvalidateSubFramebuffer(GLenum target, GLsizei numAttachments,
|
||||
const GLenum* attachments, GLint x, GLint y,
|
||||
GLsizei width, GLsizei height) {
|
||||
if (!mSymbols.fInvalidateSubFramebuffer) return;
|
||||
BeforeGLDrawCall();
|
||||
BEFORE_GL_CALL;
|
||||
ASSERT_SYMBOL_PRESENT(fInvalidateSubFramebuffer);
|
||||
|
@ -825,6 +839,13 @@ class GLContext : public GenericAtomicRefCounted, public SupportsWeakPtr {
|
|||
AFTER_GL_CALL;
|
||||
}
|
||||
|
||||
void BindSamplerTexture(GLuint texUnitId, GLuint samplerHandle,
|
||||
GLenum texTarget, GLuint texHandle) {
|
||||
fBindSampler(texUnitId, samplerHandle);
|
||||
fActiveTexture(LOCAL_GL_TEXTURE0 + texUnitId);
|
||||
fBindTexture(texTarget, texHandle);
|
||||
}
|
||||
|
||||
void fBlendColor(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha) {
|
||||
BEFORE_GL_CALL;
|
||||
mSymbols.fBlendColor(red, green, blue, alpha);
|
||||
|
@ -2028,7 +2049,11 @@ class GLContext : public GenericAtomicRefCounted, public SupportsWeakPtr {
|
|||
public:
|
||||
bool mElideDuplicateBindFramebuffers = false;
|
||||
|
||||
void fBindFramebuffer(const GLenum target, const GLuint fb) const {
|
||||
// If e.g. GL_DRAW_FRAMEBUFFER isn't supported, will bind GL_FRAMEBUFFER.
|
||||
void fBindFramebuffer(GLenum target, const GLuint fb) const {
|
||||
if (!IsSupported(gl::GLFeature::framebuffer_blit)) {
|
||||
target = LOCAL_GL_FRAMEBUFFER;
|
||||
}
|
||||
if (mElideDuplicateBindFramebuffers) {
|
||||
MOZ_ASSERT(mCachedDrawFb ==
|
||||
GetIntAs<GLuint>(LOCAL_GL_DRAW_FRAMEBUFFER_BINDING));
|
||||
|
@ -3861,6 +3886,30 @@ class Texture final {
|
|||
}
|
||||
};
|
||||
|
||||
// -
|
||||
|
||||
class Sampler final {
|
||||
public:
|
||||
const WeakPtr<GLContext> weakGl;
|
||||
const GLuint name;
|
||||
|
||||
private:
|
||||
static GLuint Create(GLContext& gl) {
|
||||
GLuint ret = 0;
|
||||
gl.fGenSamplers(1, &ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
public:
|
||||
explicit Sampler(GLContext& gl) : weakGl(&gl), name(Create(gl)) {}
|
||||
|
||||
~Sampler() {
|
||||
const RefPtr<GLContext> gl = weakGl.get();
|
||||
if (!gl || !gl->MakeCurrent()) return;
|
||||
gl->fDeleteSamplers(1, &name);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Helper function that creates a 2D texture aSize.width x aSize.height with
|
||||
* storage type specified by aFormats. Returns GL texture object id.
|
||||
|
|
|
@ -182,8 +182,13 @@ class SurfaceFactory {
|
|||
const SharedSurfaceDesc&) = 0;
|
||||
|
||||
public:
|
||||
virtual bool SupportsCspaces() const { return false; }
|
||||
|
||||
UniquePtr<SharedSurface> CreateShared(const gfx::IntSize& size,
|
||||
gfx::ColorSpace2 cs) {
|
||||
if (!SupportsCspaces()) {
|
||||
cs = gfx::ColorSpace2::Display;
|
||||
}
|
||||
return CreateSharedImpl({mDesc, size, cs});
|
||||
}
|
||||
};
|
||||
|
|
|
@ -47,6 +47,8 @@ class SurfaceFactory_IOSurface : public SurfaceFactory {
|
|||
|
||||
explicit SurfaceFactory_IOSurface(GLContext& gl);
|
||||
|
||||
bool SupportsCspaces() const override { return true; }
|
||||
|
||||
virtual UniquePtr<SharedSurface> CreateSharedImpl(
|
||||
const SharedSurfaceDesc& desc) override {
|
||||
if (desc.size.width > mMaxDims.width ||
|
||||
|
|
|
@ -650,7 +650,7 @@ TEST(Colorspaces, ColorProfileConversionDesc_SrgbFromRec709)
|
|||
.dst = srgb,
|
||||
});
|
||||
auto src = vec3(16.0);
|
||||
auto dst = conv.Apply(src / 255) * 255;
|
||||
auto dst = conv.DstFromSrc(src / 255) * 255;
|
||||
|
||||
const auto tfa = PiecewiseGammaDesc::Srgb();
|
||||
const auto tfb = PiecewiseGammaDesc::Srgb();
|
||||
|
@ -667,7 +667,7 @@ TEST(Colorspaces, ColorProfileConversionDesc_SrgbFromRec709)
|
|||
.dst = rec709,
|
||||
});
|
||||
auto src = vec3(16.0);
|
||||
auto dst = conv.Apply(src / 255) * 255;
|
||||
auto dst = conv.DstFromSrc(src / 255) * 255;
|
||||
|
||||
const auto tfa = PiecewiseGammaDesc::Rec709();
|
||||
const auto tfb = PiecewiseGammaDesc::Rec709();
|
||||
|
@ -684,7 +684,7 @@ TEST(Colorspaces, ColorProfileConversionDesc_SrgbFromRec709)
|
|||
.dst = srgb,
|
||||
});
|
||||
auto src = vec3(16.0);
|
||||
auto dst = conv.Apply(src / 255) * 255;
|
||||
auto dst = conv.DstFromSrc(src / 255) * 255;
|
||||
|
||||
const auto tfa = PiecewiseGammaDesc::Rec709();
|
||||
const auto tfb = PiecewiseGammaDesc::Srgb();
|
||||
|
@ -696,3 +696,9 @@ TEST(Colorspaces, ColorProfileConversionDesc_SrgbFromRec709)
|
|||
EXPECT_LT(Stats::Diff(dst.data, vec3(expected).data), (Stats::Error{0.12}));
|
||||
}
|
||||
}
|
||||
|
||||
TEST(Colorspaces, SampleOutByIn_NegativeInputs)
|
||||
{
|
||||
const auto tf = MakeGamma(1.0 / 2.2, 256);
|
||||
EXPECT_LT(SampleOutByIn(tf, -0.1f), 0.0f);
|
||||
}
|
||||
|
|
|
@ -2083,7 +2083,7 @@ Maybe<nsTArray<uint8_t>>& gfxPlatform::GetCMSOutputProfileData() {
|
|||
|
||||
CMSMode GfxColorManagementMode() {
|
||||
const auto mode = StaticPrefs::gfx_color_management_mode();
|
||||
if (mode >= 0 && mode < UnderlyingValue(CMSMode::AllCount)) {
|
||||
if (mode >= 0 && mode <= UnderlyingValue(CMSMode::_ENUM_MAX)) {
|
||||
return CMSMode(mode);
|
||||
}
|
||||
return CMSMode::Off;
|
||||
|
|
|
@ -82,7 +82,7 @@ enum class CMSMode : int32_t {
|
|||
Off = 0, // No color management
|
||||
All = 1, // Color manage everything
|
||||
TaggedOnly = 2, // Color manage tagged Images Only
|
||||
AllCount = 3
|
||||
_ENUM_MAX = TaggedOnly
|
||||
};
|
||||
|
||||
enum eGfxLog {
|
||||
|
|
|
@ -751,9 +751,9 @@ DCSurface* DCExternalSurfaceWrapper::EnsureSurfaceForExternalImage(
|
|||
auto cprofileOut = mDCLayerTree->OutputColorProfile();
|
||||
bool pretendSrgb = true;
|
||||
if (pretendSrgb) {
|
||||
cprofileOut = color::ColorProfileDesc::From({
|
||||
color::Chromaticities::Srgb(),
|
||||
color::PiecewiseGammaDesc::Srgb(),
|
||||
cprofileOut = color::ColorProfileDesc::From(color::ColorspaceDesc{
|
||||
.chrom = color::Chromaticities::Srgb(),
|
||||
.tf = color::PiecewiseGammaDesc::Srgb(),
|
||||
});
|
||||
}
|
||||
const auto conversion = color::ColorProfileConversionDesc::From({
|
||||
|
@ -2097,7 +2097,10 @@ void DCLayerTree::DestroyEGLSurface() {
|
|||
|
||||
// -
|
||||
|
||||
color::ColorProfileDesc DCLayerTree::QueryOutputColorProfile() {
|
||||
} // namespace wr
|
||||
namespace gfx {
|
||||
|
||||
color::ColorProfileDesc QueryOutputColorProfile() {
|
||||
// GPU process can't simply init gfxPlatform, (and we don't need most of it)
|
||||
// but we do need gfxPlatform::GetCMSOutputProfile().
|
||||
// So we steal what we need through the window:
|
||||
|
@ -2151,6 +2154,9 @@ color::ColorProfileDesc DCLayerTree::QueryOutputColorProfile() {
|
|||
return ret;
|
||||
}
|
||||
|
||||
} // namespace gfx
|
||||
namespace wr {
|
||||
|
||||
inline D2D1_MATRIX_5X4_F to_D2D1_MATRIX_5X4_F(const color::mat4& m) {
|
||||
return D2D1_MATRIX_5X4_F{{{
|
||||
m.rows[0][0],
|
||||
|
|
|
@ -44,6 +44,10 @@ struct IDCompositionVirtualSurface;
|
|||
|
||||
namespace mozilla {
|
||||
|
||||
namespace gfx {
|
||||
color::ColorProfileDesc QueryOutputColorProfile();
|
||||
}
|
||||
|
||||
namespace gl {
|
||||
class GLContext;
|
||||
}
|
||||
|
@ -248,8 +252,6 @@ class DCLayerTree {
|
|||
|
||||
bool mPendingCommit;
|
||||
|
||||
static color::ColorProfileDesc QueryOutputColorProfile();
|
||||
|
||||
mutable Maybe<color::ColorProfileDesc> mOutputColorProfile;
|
||||
|
||||
DCompOverlayTypes mUsedOverlayTypesInFrame = DCompOverlayTypes::NO_OVERLAY;
|
||||
|
@ -258,7 +260,7 @@ class DCLayerTree {
|
|||
public:
|
||||
const color::ColorProfileDesc& OutputColorProfile() const {
|
||||
if (!mOutputColorProfile) {
|
||||
mOutputColorProfile = Some(QueryOutputColorProfile());
|
||||
mOutputColorProfile = Some(gfx::QueryOutputColorProfile());
|
||||
}
|
||||
return *mOutputColorProfile;
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче