Backed out 2 changesets (bug 1956355) for causing build bustages @WebGLContextGL.cpp.
Backed out changeset 5e479ac652f4 (bug 1956355) Backed out changeset 194f0fa0c62e (bug 1956355)
This commit is contained in:
@@ -6,7 +6,6 @@
|
|||||||
#include "ClientWebGLContext.h"
|
#include "ClientWebGLContext.h"
|
||||||
|
|
||||||
#include <bitset>
|
#include <bitset>
|
||||||
#include <fmt/format.h>
|
|
||||||
|
|
||||||
#include "ClientWebGLExtensions.h"
|
#include "ClientWebGLExtensions.h"
|
||||||
#include "gfxCrashReporterUtils.h"
|
#include "gfxCrashReporterUtils.h"
|
||||||
@@ -2487,7 +2486,7 @@ void ClientWebGLContext::GetParameter(JSContext* cx, GLenum pname,
|
|||||||
case LOCAL_GL_TRANSFORM_FEEDBACK_ACTIVE:
|
case LOCAL_GL_TRANSFORM_FEEDBACK_ACTIVE:
|
||||||
case LOCAL_GL_TRANSFORM_FEEDBACK_PAUSED:
|
case LOCAL_GL_TRANSFORM_FEEDBACK_PAUSED:
|
||||||
retval.set(JS::BooleanValue(*maybe));
|
retval.set(JS::BooleanValue(*maybe));
|
||||||
return;
|
break;
|
||||||
|
|
||||||
// 4 bools
|
// 4 bools
|
||||||
case LOCAL_GL_COLOR_WRITEMASK: {
|
case LOCAL_GL_COLOR_WRITEMASK: {
|
||||||
@@ -2502,19 +2501,9 @@ void ClientWebGLContext::GetParameter(JSContext* cx, GLenum pname,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
case LOCAL_GL_IMPLEMENTATION_COLOR_READ_TYPE: {
|
|
||||||
auto readType = (GLenum)*maybe;
|
|
||||||
// Map HALF_FLOAT to HALF_FLOAT_OES for webgl 1 clients.
|
|
||||||
if (readType == LOCAL_GL_HALF_FLOAT && !mIsWebGL2) {
|
|
||||||
readType = LOCAL_GL_HALF_FLOAT_OES;
|
|
||||||
}
|
|
||||||
retval.set(JS::NumberValue(readType));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
default:
|
default:
|
||||||
retval.set(JS::NumberValue(*maybe));
|
retval.set(JS::NumberValue(*maybe));
|
||||||
return;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -5139,7 +5128,7 @@ void ClientWebGLContext::ReadPixels(GLint x, GLint y, GLsizei width,
|
|||||||
dom::CallerType aCallerType,
|
dom::CallerType aCallerType,
|
||||||
ErrorResult& out_error) const {
|
ErrorResult& out_error) const {
|
||||||
const FuncScope funcScope(*this, "readPixels");
|
const FuncScope funcScope(*this, "readPixels");
|
||||||
if (!ReadPixels_SharedPrecheck(&type, aCallerType, out_error)) return;
|
if (!ReadPixels_SharedPrecheck(aCallerType, out_error)) return;
|
||||||
const auto& state = State();
|
const auto& state = State();
|
||||||
if (!ValidateNonNegative("width", width)) return;
|
if (!ValidateNonNegative("width", width)) return;
|
||||||
if (!ValidateNonNegative("height", height)) return;
|
if (!ValidateNonNegative("height", height)) return;
|
||||||
@@ -5159,7 +5148,7 @@ void ClientWebGLContext::ReadPixels(GLint x, GLint y, GLsizei width,
|
|||||||
dom::CallerType aCallerType,
|
dom::CallerType aCallerType,
|
||||||
ErrorResult& out_error) const {
|
ErrorResult& out_error) const {
|
||||||
const FuncScope funcScope(*this, "readPixels");
|
const FuncScope funcScope(*this, "readPixels");
|
||||||
if (!ReadPixels_SharedPrecheck(&type, aCallerType, out_error)) return;
|
if (!ReadPixels_SharedPrecheck(aCallerType, out_error)) return;
|
||||||
const auto& state = State();
|
const auto& state = State();
|
||||||
if (!ValidateNonNegative("width", width)) return;
|
if (!ValidateNonNegative("width", width)) return;
|
||||||
if (!ValidateNonNegative("height", height)) return;
|
if (!ValidateNonNegative("height", height)) return;
|
||||||
@@ -5256,28 +5245,9 @@ bool ClientWebGLContext::DoReadPixels(const webgl::ReadPixelsDesc& desc,
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool ClientWebGLContext::ReadPixels_SharedPrecheck(
|
bool ClientWebGLContext::ReadPixels_SharedPrecheck(
|
||||||
GLenum* const inout_readType, dom::CallerType aCallerType,
|
dom::CallerType aCallerType, ErrorResult& out_error) const {
|
||||||
ErrorResult& out_error) const {
|
|
||||||
if (IsContextLost()) return false;
|
if (IsContextLost()) return false;
|
||||||
|
|
||||||
GLenum validHalfFloatType = LOCAL_GL_HALF_FLOAT;
|
|
||||||
GLenum forbiddenHalfFloatType = LOCAL_GL_HALF_FLOAT_OES;
|
|
||||||
if (!mIsWebGL2) {
|
|
||||||
std::swap(validHalfFloatType, forbiddenHalfFloatType); // Tragic.
|
|
||||||
}
|
|
||||||
if (*inout_readType == forbiddenHalfFloatType) {
|
|
||||||
const auto msg = fmt::format(
|
|
||||||
FMT_STRING("For WebGL {}, for `type`, enum {} is forbidden. Use {}."),
|
|
||||||
mIsWebGL2 ? "2" : "1", EnumString(forbiddenHalfFloatType),
|
|
||||||
EnumString(validHalfFloatType));
|
|
||||||
EnqueueError({LOCAL_GL_INVALID_ENUM, msg});
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
// Normalize to HALF_FLOAT non-_OES internally:
|
|
||||||
if (*inout_readType == LOCAL_GL_HALF_FLOAT_OES) {
|
|
||||||
*inout_readType = LOCAL_GL_HALF_FLOAT;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mCanvasElement && mCanvasElement->IsWriteOnly() &&
|
if (mCanvasElement && mCanvasElement->IsWriteOnly() &&
|
||||||
aCallerType != dom::CallerType::System) {
|
aCallerType != dom::CallerType::System) {
|
||||||
JsWarning("readPixels: Not allowed");
|
JsWarning("readPixels: Not allowed");
|
||||||
|
|||||||
@@ -2224,8 +2224,7 @@ class ClientWebGLContext final : public nsICanvasRenderingContextInternal,
|
|||||||
dom::CallerType aCallerType, ErrorResult& out_error) const;
|
dom::CallerType aCallerType, ErrorResult& out_error) const;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
bool ReadPixels_SharedPrecheck(GLenum* inout_readType,
|
bool ReadPixels_SharedPrecheck(dom::CallerType aCallerType,
|
||||||
dom::CallerType aCallerType,
|
|
||||||
ErrorResult& out_error) const;
|
ErrorResult& out_error) const;
|
||||||
|
|
||||||
// ------------------------------ Vertex Array ------------------------------
|
// ------------------------------ Vertex Array ------------------------------
|
||||||
|
|||||||
@@ -304,6 +304,7 @@ class WebGLContext : public VRefCounted, public SupportsWeakPtr {
|
|||||||
const uint32_t mMaxAcceptableFBStatusInvals =
|
const uint32_t mMaxAcceptableFBStatusInvals =
|
||||||
StaticPrefs::webgl_perf_max_acceptable_fb_status_invals();
|
StaticPrefs::webgl_perf_max_acceptable_fb_status_invals();
|
||||||
bool mWarnOnce_DepthTexCompareFilterable = true;
|
bool mWarnOnce_DepthTexCompareFilterable = true;
|
||||||
|
mutable bool mRemapImplReadType_HalfFloatOes = false;
|
||||||
|
|
||||||
mutable std::optional<bool> mIsSupportedCache_DrawBuffers;
|
mutable std::optional<bool> mIsSupportedCache_DrawBuffers;
|
||||||
mutable std::optional<bool> mIsSupportedCache_FragDepth;
|
mutable std::optional<bool> mIsSupportedCache_FragDepth;
|
||||||
|
|||||||
@@ -38,7 +38,6 @@
|
|||||||
#include "WebGLTexelConversions.h"
|
#include "WebGLTexelConversions.h"
|
||||||
#include "WebGLValidateStrings.h"
|
#include "WebGLValidateStrings.h"
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <fmt/format.h>
|
|
||||||
|
|
||||||
#include "mozilla/DebugOnly.h"
|
#include "mozilla/DebugOnly.h"
|
||||||
#include "mozilla/dom/BindingUtils.h"
|
#include "mozilla/dom/BindingUtils.h"
|
||||||
@@ -866,7 +865,13 @@ bool WebGLContext::DoReadPixelsAndConvert(
|
|||||||
const auto& x = desc.srcOffset.x;
|
const auto& x = desc.srcOffset.x;
|
||||||
const auto& y = desc.srcOffset.y;
|
const auto& y = desc.srcOffset.y;
|
||||||
const auto size = *ivec2::From(desc.size);
|
const auto size = *ivec2::From(desc.size);
|
||||||
const auto& pi = desc.pi;
|
|
||||||
|
auto pi = desc.pi;
|
||||||
|
if (mRemapImplReadType_HalfFloatOes) {
|
||||||
|
if (pi.type == LOCAL_GL_HALF_FLOAT_OES) {
|
||||||
|
pi.type = LOCAL_GL_HALF_FLOAT;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// On at least Win+NV, we'll get PBO errors if we don't have at least
|
// On at least Win+NV, we'll get PBO errors if we don't have at least
|
||||||
// `rowStride * height` bytes available to read into.
|
// `rowStride * height` bytes available to read into.
|
||||||
@@ -985,8 +990,8 @@ static webgl::PackingInfo DefaultReadPixelPI(
|
|||||||
case webgl::ComponentType::Float:
|
case webgl::ComponentType::Float:
|
||||||
return {LOCAL_GL_RGBA, LOCAL_GL_FLOAT};
|
return {LOCAL_GL_RGBA, LOCAL_GL_FLOAT};
|
||||||
|
|
||||||
case webgl::ComponentType::NormInt:
|
default:
|
||||||
MOZ_CRASH("SNORM formats are never color-renderable!");
|
MOZ_CRASH();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1017,48 +1022,33 @@ static bool ArePossiblePackEnums(const webgl::PackingInfo& pi) {
|
|||||||
|
|
||||||
webgl::PackingInfo WebGLContext::ValidImplementationColorReadPI(
|
webgl::PackingInfo WebGLContext::ValidImplementationColorReadPI(
|
||||||
const webgl::FormatUsageInfo* usage) const {
|
const webgl::FormatUsageInfo* usage) const {
|
||||||
if (const auto implPI = usage->implReadPiCache) return *implPI;
|
|
||||||
|
|
||||||
const auto defaultPI = DefaultReadPixelPI(usage);
|
const auto defaultPI = DefaultReadPixelPI(usage);
|
||||||
usage->implReadPiCache = [&]() {
|
|
||||||
if (StaticPrefs::webgl_porting_strict_readpixels_formats())
|
|
||||||
return defaultPI;
|
|
||||||
auto implPI = defaultPI;
|
|
||||||
// ES2_compatibility always returns RGBA/UNSIGNED_BYTE, so branch on actual
|
// ES2_compatibility always returns RGBA/UNSIGNED_BYTE, so branch on actual
|
||||||
// IsGLES(). Also OSX+NV generates an error here.
|
// IsGLES(). Also OSX+NV generates an error here.
|
||||||
if (gl->IsGLES()) {
|
if (!gl->IsGLES()) return defaultPI;
|
||||||
gl->GetInt(LOCAL_GL_IMPLEMENTATION_COLOR_READ_FORMAT, &implPI.format);
|
|
||||||
gl->GetInt(LOCAL_GL_IMPLEMENTATION_COLOR_READ_TYPE, &implPI.type);
|
|
||||||
} else {
|
|
||||||
if (StaticPrefs::webgl_porting_strict_readpixels_formats_non_es())
|
|
||||||
return defaultPI;
|
|
||||||
// Non-ES GL is way more open, and basically supports reading anything.
|
|
||||||
// (Sucks to be their driver team!)
|
|
||||||
if (usage->idealUnpack) {
|
|
||||||
for (const auto& [validPi, validDui] : usage->validUnpacks) {
|
|
||||||
if (validDui != *usage->idealUnpack) continue;
|
|
||||||
implPI = validPi;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Normalize HALF_FLOAT_OES to HALF_FLOAT internally.
|
|
||||||
if (implPI.type == LOCAL_GL_HALF_FLOAT_OES) {
|
|
||||||
implPI.type = LOCAL_GL_HALF_FLOAT;
|
|
||||||
}
|
|
||||||
if (!ArePossiblePackEnums(implPI)) return defaultPI;
|
|
||||||
return implPI;
|
|
||||||
}();
|
|
||||||
return *usage->implReadPiCache;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string webgl::format_as(const PackingInfo& pi) {
|
webgl::PackingInfo implPI;
|
||||||
return fmt::format(FMT_STRING("{}/{}"), pi.format, pi.type);
|
gl->fGetIntegerv(LOCAL_GL_IMPLEMENTATION_COLOR_READ_FORMAT,
|
||||||
|
(GLint*)&implPI.format);
|
||||||
|
gl->fGetIntegerv(LOCAL_GL_IMPLEMENTATION_COLOR_READ_TYPE,
|
||||||
|
(GLint*)&implPI.type);
|
||||||
|
|
||||||
|
if (!IsWebGL2()) {
|
||||||
|
if (implPI.type == LOCAL_GL_HALF_FLOAT) {
|
||||||
|
mRemapImplReadType_HalfFloatOes = true;
|
||||||
|
implPI.type = LOCAL_GL_HALF_FLOAT_OES;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!ArePossiblePackEnums(implPI)) return defaultPI;
|
||||||
|
|
||||||
|
return implPI;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool ValidateReadPixelsFormatAndType(
|
static bool ValidateReadPixelsFormatAndType(
|
||||||
const webgl::FormatUsageInfo* srcUsage, const webgl::PackingInfo& pi,
|
const webgl::FormatUsageInfo* srcUsage, const webgl::PackingInfo& pi,
|
||||||
WebGLContext* webgl) {
|
gl::GLContext* gl, WebGLContext* webgl) {
|
||||||
if (!ArePossiblePackEnums(pi)) {
|
if (!ArePossiblePackEnums(pi)) {
|
||||||
webgl->ErrorInvalidEnum("Unexpected format or type.");
|
webgl->ErrorInvalidEnum("Unexpected format or type.");
|
||||||
return false;
|
return false;
|
||||||
@@ -1072,48 +1062,32 @@ static bool ValidateReadPixelsFormatAndType(
|
|||||||
// OpenGL ES 3.0.4 p194 - When the internal format of the rendering surface is
|
// OpenGL ES 3.0.4 p194 - When the internal format of the rendering surface is
|
||||||
// RGB10_A2, a third combination of format RGBA and type
|
// RGB10_A2, a third combination of format RGBA and type
|
||||||
// UNSIGNED_INT_2_10_10_10_REV is accepted.
|
// UNSIGNED_INT_2_10_10_10_REV is accepted.
|
||||||
std::optional<webgl::PackingInfo> bonusValidPi;
|
|
||||||
if (srcUsage->format->effectiveFormat == webgl::EffectiveFormat::RGB10_A2) {
|
if (webgl->IsWebGL2() &&
|
||||||
bonusValidPi =
|
srcUsage->format->effectiveFormat == webgl::EffectiveFormat::RGB10_A2 &&
|
||||||
webgl::PackingInfo{LOCAL_GL_RGBA, LOCAL_GL_UNSIGNED_INT_2_10_10_10_REV};
|
pi.format == LOCAL_GL_RGBA &&
|
||||||
|
pi.type == LOCAL_GL_UNSIGNED_INT_2_10_10_10_REV) {
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
if (bonusValidPi && pi == *bonusValidPi) return true;
|
|
||||||
|
|
||||||
////
|
////
|
||||||
|
|
||||||
const auto implPI = webgl->ValidImplementationColorReadPI(srcUsage);
|
const auto implPI = webgl->ValidImplementationColorReadPI(srcUsage);
|
||||||
MOZ_ASSERT(pi.type != LOCAL_GL_HALF_FLOAT_OES); // HALF_FLOAT-only
|
|
||||||
MOZ_ASSERT(implPI.type != LOCAL_GL_HALF_FLOAT_OES); // HALF_FLOAT-only
|
|
||||||
if (pi == implPI) return true;
|
if (pi == implPI) return true;
|
||||||
|
|
||||||
////
|
////
|
||||||
|
|
||||||
// Map HALF_FLOAT to HALF_FLOAT_OES for error messages in webgl1.
|
// clang-format off
|
||||||
webgl::PackingInfo clientImplPI = implPI;
|
|
||||||
if (clientImplPI.type == LOCAL_GL_HALF_FLOAT && !webgl->IsWebGL2()) {
|
|
||||||
clientImplPI.type = LOCAL_GL_HALF_FLOAT_OES;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto validPiStr =
|
|
||||||
fmt::format(FMT_STRING("{} (spec-required baseline for format {})"),
|
|
||||||
defaultPI, srcUsage->format->name);
|
|
||||||
if (implPI != defaultPI) {
|
|
||||||
validPiStr += fmt::format(
|
|
||||||
FMT_STRING(
|
|
||||||
", or {} (spec-optional implementation-chosen format-dependant"
|
|
||||||
" IMPLEMENTATION_COLOR_READ_FORMAT/_TYPE)"),
|
|
||||||
clientImplPI);
|
|
||||||
}
|
|
||||||
if (bonusValidPi) {
|
|
||||||
validPiStr +=
|
|
||||||
fmt::format(FMT_STRING(", or {} (spec-required bonus for format {})"),
|
|
||||||
*bonusValidPi, srcUsage->format->name);
|
|
||||||
}
|
|
||||||
|
|
||||||
webgl->ErrorInvalidOperation(
|
webgl->ErrorInvalidOperation(
|
||||||
"Format/type %s/%s incompatible with this %s framebuffer. Must use: %s.",
|
"Format and type %s/%s incompatible with this %s attachment."
|
||||||
|
" This framebuffer requires either %s/%s or"
|
||||||
|
" getParameter(IMPLEMENTATION_COLOR_READ_FORMAT/_TYPE) %s/%s.",
|
||||||
EnumString(pi.format).c_str(), EnumString(pi.type).c_str(),
|
EnumString(pi.format).c_str(), EnumString(pi.type).c_str(),
|
||||||
srcUsage->format->name, validPiStr.c_str());
|
srcUsage->format->name,
|
||||||
|
EnumString(defaultPI.format).c_str(), EnumString(defaultPI.type).c_str(),
|
||||||
|
EnumString(implPI.format).c_str(), EnumString(implPI.type).c_str());
|
||||||
|
// clang-format on
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1127,7 +1101,7 @@ webgl::ReadPixelsResult WebGLContext::ReadPixelsImpl(
|
|||||||
|
|
||||||
//////
|
//////
|
||||||
|
|
||||||
if (!ValidateReadPixelsFormatAndType(srcFormat, desc.pi, this)) return {};
|
if (!ValidateReadPixelsFormatAndType(srcFormat, desc.pi, gl, this)) return {};
|
||||||
|
|
||||||
//////
|
//////
|
||||||
|
|
||||||
|
|||||||
@@ -351,9 +351,6 @@ struct FormatUsageInfo {
|
|||||||
std::map<PackingInfo, DriverUnpackInfo> validUnpacks;
|
std::map<PackingInfo, DriverUnpackInfo> validUnpacks;
|
||||||
const DriverUnpackInfo* idealUnpack = nullptr;
|
const DriverUnpackInfo* idealUnpack = nullptr;
|
||||||
|
|
||||||
// LOCAL_GL_IMPLEMENTATION_COLOR_READ_FORMAT/_TYPE:
|
|
||||||
mutable std::optional<PackingInfo> implReadPiCache;
|
|
||||||
|
|
||||||
const GLint* textureSwizzleRGBA = nullptr;
|
const GLint* textureSwizzleRGBA = nullptr;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|||||||
@@ -553,9 +553,6 @@ struct PackingInfo final {
|
|||||||
friend bool operator==(const Self& a, const Self& b) {
|
friend bool operator==(const Self& a, const Self& b) {
|
||||||
return TiedFields(a) == TiedFields(b);
|
return TiedFields(a) == TiedFields(b);
|
||||||
}
|
}
|
||||||
friend bool operator!=(const Self& a, const Self& b) {
|
|
||||||
return TiedFields(a) != TiedFields(b);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
friend T& operator<<(T& s, const PackingInfo& pi) {
|
friend T& operator<<(T& s, const PackingInfo& pi) {
|
||||||
@@ -564,28 +561,13 @@ struct PackingInfo final {
|
|||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
std::string format_as(const PackingInfo& pi);
|
|
||||||
|
|
||||||
struct DriverUnpackInfo final {
|
struct DriverUnpackInfo final {
|
||||||
using Self = DriverUnpackInfo;
|
|
||||||
|
|
||||||
GLenum internalFormat = 0;
|
GLenum internalFormat = 0;
|
||||||
GLenum unpackFormat = 0;
|
GLenum unpackFormat = 0;
|
||||||
GLenum unpackType = 0;
|
GLenum unpackType = 0;
|
||||||
|
|
||||||
PackingInfo ToPacking() const { return {unpackFormat, unpackType}; }
|
PackingInfo ToPacking() const { return {unpackFormat, unpackType}; }
|
||||||
|
|
||||||
template<class ConstOrMutSelf>
|
|
||||||
static constexpr auto Fields(ConstOrMutSelf& self) {
|
|
||||||
return std::tie(self.internalFormat, self.unpackFormat, self.unpackType);
|
|
||||||
}
|
|
||||||
|
|
||||||
constexpr bool operator==(const Self& rhs) const {
|
|
||||||
return Fields(*this) == Fields(rhs);
|
|
||||||
}
|
|
||||||
constexpr bool operator!=(const Self& rhs) const {
|
|
||||||
return Fields(*this) != Fields(rhs);
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// -
|
// -
|
||||||
|
|||||||
@@ -210,9 +210,6 @@ skip-if = [
|
|||||||
|
|
||||||
["test_read_pixels_no_format.html"]
|
["test_read_pixels_no_format.html"]
|
||||||
|
|
||||||
["test_read_pixels_naive_impl_read_formats.html"]
|
|
||||||
tags = "os_integration"
|
|
||||||
|
|
||||||
["test_renderer_strings.html"]
|
["test_renderer_strings.html"]
|
||||||
skip-if = ["display == 'wayland'"]
|
skip-if = ["display == 'wayland'"]
|
||||||
tags = "os_integration"
|
tags = "os_integration"
|
||||||
|
|||||||
@@ -1,194 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<meta charset=utf-8>
|
|
||||||
<script src='/tests/SimpleTest/SimpleTest.js'></script>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<h2><pre id=e_results></pre></h2>
|
|
||||||
<pre id=e_out></pre>
|
|
||||||
<script>
|
|
||||||
'use strict';
|
|
||||||
|
|
||||||
const RESULTS = {
|
|
||||||
failures: 0,
|
|
||||||
tests: 0,
|
|
||||||
};
|
|
||||||
|
|
||||||
window.ok = window.ok || function(e, s) {
|
|
||||||
const failure = !e;
|
|
||||||
e_out.textContent += `\n${failure ? 'FAIL' : 'ok '}: ${s}`;
|
|
||||||
RESULTS.failures += failure|0;
|
|
||||||
RESULTS.tests += 1;
|
|
||||||
e_results.textContent = `${RESULTS.failures} failures in ${RESULTS.tests} tests`;
|
|
||||||
};
|
|
||||||
|
|
||||||
// -
|
|
||||||
|
|
||||||
function throwv(v) {
|
|
||||||
throw v;
|
|
||||||
}
|
|
||||||
|
|
||||||
function jsobj_strinify(obj) {
|
|
||||||
if (typeof(obj) == 'function') return `[function ${obj.name}]`;
|
|
||||||
if (typeof(obj) == 'string') return `'${obj}'`;
|
|
||||||
if (typeof(obj) != 'object') return ''+obj;
|
|
||||||
if (obj.constructor == Object) {
|
|
||||||
return '{' + Object.entries(obj).map(
|
|
||||||
([k, v]) => `${k}: ${jsobj_strinify(v)}`
|
|
||||||
).join(', ') + '}';
|
|
||||||
}
|
|
||||||
if (Array.isArray(obj)) {
|
|
||||||
obj = obj.map(jsobj_strinify);
|
|
||||||
return '[' + obj + ']';
|
|
||||||
}
|
|
||||||
if (ArrayBuffer.isView(obj)) {
|
|
||||||
if (obj instanceof DataView) throw 'todo';
|
|
||||||
const ctor = obj.constructor;
|
|
||||||
obj = [].map.call(obj, jsobj_strinify);
|
|
||||||
return `new ${ctor.name}([` + obj + `])`;
|
|
||||||
}
|
|
||||||
let ret = ''+obj;
|
|
||||||
if (obj.label) {
|
|
||||||
ret = ret.replace(']', ` "${obj.label}"]`);
|
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
// -
|
|
||||||
|
|
||||||
const GL = globalThis.WebGL2RenderingContext || WebGLRenderingContext;
|
|
||||||
function GL_(enumName) {
|
|
||||||
const enumNameGl = enumName.toUpperCase().replaceAll('-', '_');
|
|
||||||
return GL[enumNameGl] || throwv({enumName, enumNameGl, GL});
|
|
||||||
}
|
|
||||||
|
|
||||||
const GL_NAMES_BY_VAL = new Map();
|
|
||||||
function UNGL_(val, prettyNames=false) {
|
|
||||||
if (!val) return val; // E.g. 0 => 0
|
|
||||||
if (!GL_NAMES_BY_VAL.size) {
|
|
||||||
GL_NAMES_BY_VAL.set(0, ['NONE']);
|
|
||||||
for (const [k, v] of Object.entries(GL)) {
|
|
||||||
const existing = GL_NAMES_BY_VAL.get(v);
|
|
||||||
if (!existing) {
|
|
||||||
GL_NAMES_BY_VAL.set(v, [k]);
|
|
||||||
} else {
|
|
||||||
if (!existing.includes(k)) {
|
|
||||||
existing.push(v);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
const enumNameGlList = GL_NAMES_BY_VAL.get(val) || [`0x${val.toString(16)}`];
|
|
||||||
const enumNameGl = enumNameGlList.join('/');
|
|
||||||
let enumName = enumNameGl;
|
|
||||||
if (prettyNames) {
|
|
||||||
enumName = enumName.replaceAll('_', '-').toLowerCase();
|
|
||||||
}
|
|
||||||
return enumName;
|
|
||||||
}
|
|
||||||
|
|
||||||
// -
|
|
||||||
|
|
||||||
const gl = document.createElement('canvas').getContext('webgl2');
|
|
||||||
|
|
||||||
const WEBGL_debug_renderer_info = gl.getExtension('WEBGL_debug_renderer_info');
|
|
||||||
const context_info = {
|
|
||||||
vendor: gl.getParameter(GL_('vendor')),
|
|
||||||
renderer: gl.getParameter(GL_('renderer')),
|
|
||||||
};
|
|
||||||
if (WEBGL_debug_renderer_info) {
|
|
||||||
const unmasked_vendor = gl.getParameter(WEBGL_debug_renderer_info.UNMASKED_VENDOR_WEBGL);
|
|
||||||
if (!context_info.vendor.includes(unmasked_vendor)) {
|
|
||||||
context_info.vendor = `${context_info.vendor} (${unmasked_vendor})`;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ok(true, jsobj_strinify({context_info}));
|
|
||||||
|
|
||||||
const fb = gl.createFramebuffer();
|
|
||||||
gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
|
|
||||||
|
|
||||||
const pbo = gl.createBuffer();
|
|
||||||
gl.bindBuffer(gl.PIXEL_PACK_BUFFER, pbo);
|
|
||||||
pbo.size = 1024
|
|
||||||
gl.bufferData(gl.PIXEL_PACK_BUFFER, pbo.size, gl.DYNAMIC_READ);
|
|
||||||
|
|
||||||
// -
|
|
||||||
|
|
||||||
function test(desc) {
|
|
||||||
ok(true, '(end of section)\n\n---\n');
|
|
||||||
if (desc.readType.includes('FLOAT')) {
|
|
||||||
const EXT_color_buffer_float = gl.getExtension('EXT_color_buffer_float');
|
|
||||||
if (!gl.getExtension('EXT_color_buffer_float')) {
|
|
||||||
ok(true, {EXT_color_buffer_float, desc});
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
const tex = gl.createTexture();
|
|
||||||
gl.bindTexture(gl.TEXTURE_2D, tex);
|
|
||||||
gl.texStorage2D(gl.TEXTURE_2D, 1, GL_(desc.texFormat), 1, 1);
|
|
||||||
gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, tex, 0);
|
|
||||||
try {
|
|
||||||
const setupErr = UNGL_(gl.getError());
|
|
||||||
ok(!setupErr, jsobj_strinify({setupErr, desc}));
|
|
||||||
|
|
||||||
const implFormat = UNGL_(gl.getParameter(GL.IMPLEMENTATION_COLOR_READ_FORMAT));
|
|
||||||
const implType = UNGL_(gl.getParameter(GL.IMPLEMENTATION_COLOR_READ_TYPE));
|
|
||||||
ok(implFormat == desc.readFormat && implType == desc.readType, jsobj_strinify({implFormat, implType, desc}));
|
|
||||||
|
|
||||||
gl.readPixels(0, 0, 1, 1, GL_(desc.readFormat), GL_(desc.readType), 0);
|
|
||||||
const readPixelsErr = UNGL_(gl.getError());
|
|
||||||
ok(!readPixelsErr, jsobj_strinify({readPixelsErr, desc}));
|
|
||||||
} finally {
|
|
||||||
gl.deleteTexture(tex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// -
|
|
||||||
|
|
||||||
[
|
|
||||||
['R8', 'RED', 'UNSIGNED_BYTE'],
|
|
||||||
['RG8', 'RG', 'UNSIGNED_BYTE'],
|
|
||||||
//['RGB8', 'RGB', 'UNSIGNED_BYTE'],
|
|
||||||
['RGBA8', 'RGBA', 'UNSIGNED_BYTE'],
|
|
||||||
['RGB10_A2', 'RGBA', 'UNSIGNED_INT_2_10_10_10_REV'],
|
|
||||||
['RGB10_A2UI', 'RGBA_INTEGER', 'UNSIGNED_INT_2_10_10_10_REV'],
|
|
||||||
['SRGB8_ALPHA8', 'RGBA', 'UNSIGNED_BYTE'],
|
|
||||||
|
|
||||||
['R8I', 'RED_INTEGER', 'BYTE'],
|
|
||||||
['RG8I', 'RG_INTEGER', 'BYTE'],
|
|
||||||
['RGBA8I', 'RGBA_INTEGER', 'BYTE'],
|
|
||||||
['R8UI', 'RED_INTEGER', 'UNSIGNED_BYTE'],
|
|
||||||
['RG8UI', 'RG_INTEGER', 'UNSIGNED_BYTE'],
|
|
||||||
['RGBA8UI', 'RGBA_INTEGER', 'UNSIGNED_BYTE'],
|
|
||||||
|
|
||||||
['R16I', 'RED_INTEGER', 'SHORT'],
|
|
||||||
['RG16I', 'RG_INTEGER', 'SHORT'],
|
|
||||||
['RGBA16I', 'RGBA_INTEGER', 'SHORT'],
|
|
||||||
['R16UI', 'RED_INTEGER', 'UNSIGNED_SHORT'],
|
|
||||||
['RG16UI', 'RG_INTEGER', 'UNSIGNED_SHORT'],
|
|
||||||
['RGBA16UI', 'RGBA_INTEGER', 'UNSIGNED_SHORT'],
|
|
||||||
|
|
||||||
['R32I', 'RED_INTEGER', 'INT'],
|
|
||||||
['RG32I', 'RG_INTEGER', 'INT'],
|
|
||||||
['RGBA32I', 'RGBA_INTEGER', 'INT'],
|
|
||||||
['R32UI', 'RED_INTEGER', 'UNSIGNED_INT'],
|
|
||||||
['RG32UI', 'RG_INTEGER', 'UNSIGNED_INT'],
|
|
||||||
['RGBA32UI', 'RGBA_INTEGER', 'UNSIGNED_INT'],
|
|
||||||
|
|
||||||
['R16F', 'RED', 'HALF_FLOAT'],
|
|
||||||
['RG16F', 'RG', 'HALF_FLOAT'],
|
|
||||||
['RGBA16F', 'RGBA', 'HALF_FLOAT'],
|
|
||||||
['R32F', 'RED', 'FLOAT'],
|
|
||||||
['RG32F', 'RG', 'FLOAT'],
|
|
||||||
['RGBA32F', 'RGBA', 'FLOAT'],
|
|
||||||
].map(
|
|
||||||
([texFormat, readFormat, readType]) => {
|
|
||||||
test({texFormat, readFormat, readType});
|
|
||||||
}
|
|
||||||
);
|
|
||||||
const ignoredResults = gl.getBufferSubData(gl.PIXEL_PACK_BUFFER, 0, new Uint8Array(pbo.size));
|
|
||||||
ok(true, 'done');
|
|
||||||
</script>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
@@ -17755,16 +17755,6 @@
|
|||||||
value: false
|
value: false
|
||||||
mirror: always
|
mirror: always
|
||||||
|
|
||||||
- name: webgl.porting.strict_readpixels_formats
|
|
||||||
type: RelaxedAtomicBool
|
|
||||||
value: false
|
|
||||||
mirror: always
|
|
||||||
|
|
||||||
- name: webgl.porting.strict_readpixels_formats.non_es
|
|
||||||
type: RelaxedAtomicBool
|
|
||||||
value: false
|
|
||||||
mirror: always
|
|
||||||
|
|
||||||
- name: webgl.dxgl.enabled
|
- name: webgl.dxgl.enabled
|
||||||
type: RelaxedAtomicBool
|
type: RelaxedAtomicBool
|
||||||
#ifdef XP_WIN
|
#ifdef XP_WIN
|
||||||
|
|||||||
Reference in New Issue
Block a user