Bug 1536672 - Implement WebGL OVR_multiview2 behind draft flag. r=lsalzman,qdot

Also disable clang-format for gfx/gl/GLConsts.h.

Differential Revision: https://phabricator.services.mozilla.com/D28168

--HG--
extra : moz-landing-system : lando
This commit is contained in:
Jeff Gilbert 2019-05-23 20:48:21 +00:00
parent 231ad45e42
commit 047e98938e
48 changed files with 646 additions and 414 deletions

View File

@ -1171,6 +1171,11 @@ DOMInterfaces = {
'headerFile': 'WebGLExtensions.h'
},
'OVR_multiview2': {
'nativeType': 'mozilla::WebGLExtensionMultiview',
'headerFile': 'WebGLExtensions.h'
},
'WEBGL_compressed_texture_astc': {
'nativeType': 'mozilla::WebGLExtensionCompressedTextureASTC',
'headerFile': 'WebGLExtensions.h'

View File

@ -58,8 +58,6 @@ class WebGL2Context : public WebGLContext {
void BlitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
GLbitfield mask, GLenum filter);
void FramebufferTextureLayer(GLenum target, GLenum attachment,
WebGLTexture* texture, GLint level, GLint layer);
virtual JS::Value GetFramebufferAttachmentParameter(JSContext* cx,
GLenum target,

View File

@ -66,34 +66,6 @@ void WebGL2Context::BlitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1,
dstY0, dstX1, dstY1, mask, filter);
}
void WebGL2Context::FramebufferTextureLayer(GLenum target, GLenum attachment,
WebGLTexture* texture, GLint level,
GLint layer) {
const FuncScope funcScope(*this, "framebufferTextureLayer");
if (IsContextLost()) return;
if (!ValidateFramebufferTarget(target)) return;
WebGLFramebuffer* fb;
switch (target) {
case LOCAL_GL_FRAMEBUFFER:
case LOCAL_GL_DRAW_FRAMEBUFFER:
fb = mBoundDrawFramebuffer;
break;
case LOCAL_GL_READ_FRAMEBUFFER:
fb = mBoundReadFramebuffer;
break;
default:
MOZ_CRASH("GFX: Bad target.");
}
if (!fb) return ErrorInvalidOperation("Cannot modify framebuffer 0.");
fb->FramebufferTextureLayer(attachment, texture, level, layer);
}
JS::Value WebGL2Context::GetFramebufferAttachmentParameter(
JSContext* cx, GLenum target, GLenum attachment, GLenum pname,
ErrorResult& out_error) {

View File

@ -99,6 +99,7 @@ class MozFramebuffer;
namespace webgl {
class AvailabilityRunnable;
struct CachedDrawFetchLimits;
struct FbAttachInfo;
struct FormatInfo;
class FormatUsageAuthority;
struct FormatUsageInfo;
@ -598,11 +599,24 @@ class WebGLContext : public nsICanvasRenderingContextInternal,
void DrawBuffers(const dom::Sequence<GLenum>& buffers);
void Flush();
void Finish();
private:
void FramebufferAttach(GLenum target, GLenum attachEnum,
TexTarget reqTexTarget,
const webgl::FbAttachInfo& toAttach) const;
public:
void FramebufferRenderbuffer(GLenum target, GLenum attachment,
GLenum rbTarget, WebGLRenderbuffer* rb);
GLenum rbTarget, WebGLRenderbuffer* rb) const;
void FramebufferTexture2D(GLenum target, GLenum attachment,
GLenum texImageTarget, WebGLTexture* tex,
GLint level);
GLint level) const;
void FramebufferTextureLayer(GLenum target, GLenum attachment,
WebGLTexture* tex, GLint level,
GLint layer) const;
void FramebufferTextureMultiview(GLenum target, GLenum attachment,
WebGLTexture* texture, GLint level,
GLint baseViewIndex, GLsizei numViews) const;
void FrontFace(GLenum mode);
already_AddRefed<WebGLActiveInfo> GetActiveAttrib(const WebGLProgram& prog,
@ -1533,6 +1547,7 @@ class WebGLContext : public nsICanvasRenderingContextInternal,
uint32_t mGLMaxCubeMapTextureSize = 0;
uint32_t mGLMax3DTextureSize = 0;
uint32_t mGLMaxArrayTextureLayers = 0;
uint32_t mGLMaxMultiviewViews = 1;
uint32_t mGLMaxRenderbufferSize = 0;
public:
@ -1738,7 +1753,7 @@ class WebGLContext : public nsICanvasRenderingContextInternal,
//////
public:
bool ValidateObjectAllowDeleted(const char* const argName,
const WebGLContextBoundObject& object) {
const WebGLContextBoundObject& object) const {
if (!object.IsCompatibleWithContext(this)) {
ErrorInvalidOperation(
"%s: Object from different WebGL context (or older"
@ -1752,7 +1767,7 @@ class WebGLContext : public nsICanvasRenderingContextInternal,
bool ValidateObject(const char* const argName,
const WebGLDeletableObject& object,
const bool isShaderOrProgram = false) {
const bool isShaderOrProgram = false) const {
if (!ValidateObjectAllowDeleted(argName, object)) return false;
if (isShaderOrProgram) {
@ -1789,8 +1804,10 @@ class WebGLContext : public nsICanvasRenderingContextInternal,
// Program and Shader are incomplete, so we can't inline the conversion to
// WebGLDeletableObject here.
bool ValidateObject(const char* const argName, const WebGLProgram& object);
bool ValidateObject(const char* const argName, const WebGLShader& object);
bool ValidateObject(const char* const argName,
const WebGLProgram& object) const;
bool ValidateObject(const char* const argName,
const WebGLShader& object) const;
////
@ -1821,7 +1838,7 @@ class WebGLContext : public nsICanvasRenderingContextInternal,
WebGLRefPtr<WebGLProgram> mCurrentProgram;
RefPtr<const webgl::LinkedProgramInfo> mActiveProgramLinkInfo;
bool ValidateFramebufferTarget(GLenum target);
bool ValidateFramebufferTarget(GLenum target) const;
bool ValidateInvalidateFramebuffer(GLenum target,
const dom::Sequence<GLenum>& attachments,
ErrorResult* const out_rv,
@ -1835,6 +1852,10 @@ class WebGLContext : public nsICanvasRenderingContextInternal,
WebGLRefPtr<WebGLTransformFeedback> mBoundTransformFeedback;
WebGLRefPtr<WebGLVertexArray> mBoundVertexArray;
public:
const auto& BoundReadFb() const { return mBoundReadFramebuffer; }
protected:
LinkedList<WebGLBuffer> mBuffers;
LinkedList<WebGLFramebuffer> mFramebuffers;
LinkedList<WebGLProgram> mPrograms;

View File

@ -279,6 +279,15 @@ const webgl::CachedDrawFetchLimits* ValidateDraw(WebGLContext* const webgl,
const auto& tfo = webgl->mBoundTransformFeedback;
if (tfo && tfo->IsActiveAndNotPaused()) {
if (fb) {
const auto& info = *fb->GetCompletenessInfo();
if (info.isMultiview) {
webgl->ErrorInvalidOperation(
"Cannot render to multiview with transform feedback.");
return nullptr;
}
}
uint32_t numUsed;
switch (linkInfo->transformFeedbackBufferMode) {
case LOCAL_GL_INTERLEAVED_ATTRIBS:
@ -339,7 +348,11 @@ const webgl::CachedDrawFetchLimits* ValidateDraw(WebGLContext* const webgl,
};
if (!webgl->mRasterizerDiscardEnabled) {
uint8_t fbZLayerCount = 1;
if (fb) {
const auto& info = *fb->GetCompletenessInfo();
fbZLayerCount = info.zLayerCount;
for (const auto& attach : fb->ColorDrawBuffers()) {
const auto i =
uint8_t(attach->mAttachmentPoint - LOCAL_GL_COLOR_ATTACHMENT0);
@ -352,6 +365,13 @@ const webgl::CachedDrawFetchLimits* ValidateDraw(WebGLContext* const webgl,
if (!fnValidateFragOutputType(0, webgl::TextureBaseType::Float))
return nullptr;
}
if (fbZLayerCount != linkInfo->zLayerCount) {
webgl->ErrorInvalidOperation(
"Multiview count mismatch: shader: %u, framebuffer: %u",
uint32_t{linkInfo->zLayerCount}, uint32_t{fbZLayerCount});
return nullptr;
}
}
// -

View File

@ -51,6 +51,7 @@ namespace mozilla {
WEBGL_EXTENSION_IDENTIFIER(OES_texture_half_float)
WEBGL_EXTENSION_IDENTIFIER(OES_texture_half_float_linear)
WEBGL_EXTENSION_IDENTIFIER(OES_vertex_array_object)
WEBGL_EXTENSION_IDENTIFIER(OVR_multiview2)
WEBGL_EXTENSION_IDENTIFIER(WEBGL_color_buffer_float)
WEBGL_EXTENSION_IDENTIFIER(WEBGL_compressed_texture_astc)
WEBGL_EXTENSION_IDENTIFIER(WEBGL_compressed_texture_etc)
@ -186,6 +187,10 @@ bool WebGLContext::IsExtensionSupported(WebGLExtensionID ext) const {
case WebGLExtensionID::OES_vertex_array_object:
return !IsWebGL2(); // Always supported in webgl1.
// OVR_
case WebGLExtensionID::OVR_multiview2:
return WebGLExtensionMultiview::IsSupported(this);
// WEBGL_
case WebGLExtensionID::WEBGL_color_buffer_float:
return WebGLExtensionColorBufferFloat::IsSupported(this);
@ -389,6 +394,11 @@ void WebGLContext::EnableExtension(WebGLExtensionID ext) {
obj = new WebGLExtensionVertexArray(this);
break;
// WEBGL_
case WebGLExtensionID::OVR_multiview2:
obj = new WebGLExtensionMultiview(this);
break;
// WEBGL_
case WebGLExtensionID::WEBGL_color_buffer_float:
obj = new WebGLExtensionColorBufferFloat(this);

View File

@ -59,12 +59,12 @@
namespace mozilla {
bool WebGLContext::ValidateObject(const char* const argName,
const WebGLProgram& object) {
const WebGLProgram& object) const {
return ValidateObject(argName, object, true);
}
bool WebGLContext::ValidateObject(const char* const argName,
const WebGLShader& object) {
const WebGLShader& object) const {
return ValidateObject(argName, object, true);
}
@ -446,62 +446,204 @@ void WebGLContext::DepthRange(GLfloat zNear, GLfloat zFar) {
gl->fDepthRange(zNear, zFar);
}
void WebGLContext::FramebufferRenderbuffer(GLenum target, GLenum attachment,
GLenum rbtarget,
WebGLRenderbuffer* wrb) {
// -
void WebGLContext::FramebufferAttach(
const GLenum target, const GLenum attachEnum, const TexTarget reqTexTarget,
const webgl::FbAttachInfo& toAttach) const {
if (!ValidateFramebufferTarget(target)) return;
WebGLFramebuffer* fb = mBoundDrawFramebuffer;
if (target == LOCAL_GL_READ_FRAMEBUFFER) {
fb = mBoundReadFramebuffer;
}
if (!fb) return ErrorInvalidOperation("Cannot modify framebuffer 0.");
// `rb`
if (toAttach.rb) {
if (!ValidateObject("rb", *toAttach.rb)) return;
if (!toAttach.rb->mHasBeenBound) {
ErrorInvalidOperation(
"bindRenderbuffer must be called before"
" attachment.");
return;
}
}
// `tex`
if (toAttach.tex) {
if (!ValidateObject("tex", *toAttach.tex)) return;
const auto texTarget = toAttach.tex->Target();
bool targetOk = bool(texTarget);
if (reqTexTarget) {
targetOk = texTarget == reqTexTarget;
}
if (!targetOk) {
ErrorInvalidOperation("`tex`'s binding target type is not valid.");
return;
}
GLint maxMipLevel;
GLint maxZLayer;
const char* maxMipLevelText;
const char* maxZLayerText;
switch (texTarget.get()) {
case LOCAL_GL_TEXTURE_2D:
maxMipLevel = FloorLog2(mGLMaxTextureSize);
maxMipLevelText = "log2(MAX_TEXTURE_SIZE)";
maxZLayer = 1;
maxZLayerText = "1";
break;
case LOCAL_GL_TEXTURE_CUBE_MAP:
maxMipLevel = FloorLog2(mGLMaxCubeMapTextureSize);
maxMipLevelText = "log2(MAX_CUBE_MAP_TEXTURE_SIZE)";
maxZLayer = 6;
maxZLayerText = "6";
break;
case LOCAL_GL_TEXTURE_3D:
maxMipLevel = FloorLog2(mGLMax3DTextureSize);
maxMipLevelText = "log2(MAX_3D_TEXTURE_SIZE)";
maxZLayer = mGLMax3DTextureSize - 1;
maxZLayerText = "MAX_3D_TEXTURE_SIZE";
break;
case LOCAL_GL_TEXTURE_2D_ARRAY:
maxMipLevel = FloorLog2(mGLMaxTextureSize);
maxMipLevelText = "log2(MAX_TEXTURE_SIZE)";
maxZLayer = mGLMaxArrayTextureLayers;
maxZLayerText = "MAX_ARRAY_TEXTURE_LAYERS";
break;
default:
MOZ_CRASH();
}
if (!IsWebGL2() &&
!IsExtensionEnabled(WebGLExtensionID::OES_fbo_render_mipmap)) {
maxMipLevel = 0;
maxMipLevelText = "0";
}
if (toAttach.mipLevel < 0)
return ErrorInvalidValue("`level` must be >= 0.");
if (toAttach.mipLevel > maxMipLevel) {
ErrorInvalidValue("`level` must be <= %s.", maxMipLevelText);
return;
}
if (toAttach.zLayer < 0) return ErrorInvalidValue("`layer` must be >= 0.");
if (toAttach.zLayerCount < 1)
return ErrorInvalidValue("`numViews` must be >= 1.");
if (AssertedCast<uint32_t>(toAttach.zLayerCount) > mGLMaxMultiviewViews)
return ErrorInvalidValue("`numViews` must be <= MAX_VIEWS_OVR.");
const auto lastZLayer = toAttach.zLayer + toAttach.zLayerCount;
if (lastZLayer > maxZLayer) {
const char* formatText = "`layer` must be < %s.";
if (toAttach.zLayerCount != 1) {
formatText = "`layer` + `numViews` must be <= %s.";
}
ErrorInvalidValue(formatText, maxZLayerText);
return;
}
}
fb->FramebufferAttach(attachEnum, toAttach);
}
void WebGLContext::FramebufferRenderbuffer(const GLenum target,
const GLenum attachEnum,
const GLenum rbTarget,
WebGLRenderbuffer* const rb) const {
const FuncScope funcScope(*this, "framebufferRenderbuffer");
if (IsContextLost()) return;
if (!ValidateFramebufferTarget(target)) return;
WebGLFramebuffer* fb;
switch (target) {
case LOCAL_GL_FRAMEBUFFER:
case LOCAL_GL_DRAW_FRAMEBUFFER:
fb = mBoundDrawFramebuffer;
break;
case LOCAL_GL_READ_FRAMEBUFFER:
fb = mBoundReadFramebuffer;
break;
default:
MOZ_CRASH("GFX: Bad target.");
if (rbTarget != LOCAL_GL_RENDERBUFFER) {
ErrorInvalidEnumArg("rbTarget", rbTarget);
return;
}
if (!fb) return ErrorInvalidOperation("Cannot modify framebuffer 0.");
fb->FramebufferRenderbuffer(attachment, rbtarget, wrb);
const auto toAttach = webgl::FbAttachInfo{rb};
FramebufferAttach(target, attachEnum, 0, toAttach);
}
void WebGLContext::FramebufferTexture2D(GLenum target, GLenum attachment,
GLenum textarget, WebGLTexture* tobj,
GLint level) {
void WebGLContext::FramebufferTexture2D(const GLenum target,
const GLenum attachEnum,
const GLenum imageTarget,
WebGLTexture* const tex,
const GLint level) const {
const FuncScope funcScope(*this, "framebufferTexture2D");
if (IsContextLost()) return;
if (!ValidateFramebufferTarget(target)) return;
WebGLFramebuffer* fb;
switch (target) {
case LOCAL_GL_FRAMEBUFFER:
case LOCAL_GL_DRAW_FRAMEBUFFER:
fb = mBoundDrawFramebuffer;
break;
case LOCAL_GL_READ_FRAMEBUFFER:
fb = mBoundReadFramebuffer;
break;
default:
MOZ_CRASH("GFX: Bad target.");
TexTarget reqTexTarget = LOCAL_GL_TEXTURE_2D;
auto toAttach = webgl::FbAttachInfo{nullptr, tex, level, 0};
if (toAttach.tex) {
switch (imageTarget) {
case LOCAL_GL_TEXTURE_2D:
break;
case LOCAL_GL_TEXTURE_CUBE_MAP_POSITIVE_X:
case LOCAL_GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
case LOCAL_GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
case LOCAL_GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
case LOCAL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
case LOCAL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
toAttach.zLayer = imageTarget - LOCAL_GL_TEXTURE_CUBE_MAP_POSITIVE_X;
reqTexTarget = LOCAL_GL_TEXTURE_CUBE_MAP;
break;
default:
ErrorInvalidEnumArg("texImageTarget", imageTarget);
return;
}
}
if (!fb) return ErrorInvalidOperation("Cannot modify framebuffer 0.");
fb->FramebufferTexture2D(attachment, textarget, tobj, level);
FramebufferAttach(target, attachEnum, reqTexTarget, toAttach);
}
void WebGLContext::FramebufferTextureLayer(const GLenum target,
const GLenum attachEnum,
WebGLTexture* const tex,
const GLint mipLevel,
const GLint zLayer) const {
const FuncScope funcScope(*this, "framebufferTextureLayer");
if (IsContextLost()) return;
const auto toAttach = webgl::FbAttachInfo{nullptr, tex, mipLevel, zLayer};
if (toAttach.tex) {
if (!ValidateObject("tex", *toAttach.tex))
return; // Technically we need to check this first...
switch (toAttach.tex->Target().get()) {
case LOCAL_GL_TEXTURE_3D:
case LOCAL_GL_TEXTURE_2D_ARRAY:
break;
default:
ErrorInvalidOperation(
"`texture` must be a TEXTURE_3D or"
" TEXTURE_2D_ARRAY.");
return;
}
}
FramebufferAttach(target, attachEnum, 0, toAttach);
}
void WebGLContext::FramebufferTextureMultiview(
const GLenum target, const GLenum attachEnum, WebGLTexture* const tex,
const GLint mipLevel, const GLint zLayerBase,
const GLsizei numViewLayers) const {
if (IsContextLost()) return;
const auto toAttach = webgl::FbAttachInfo{nullptr, tex, mipLevel,
zLayerBase, numViewLayers, true};
FramebufferAttach(target, attachEnum, LOCAL_GL_TEXTURE_2D_ARRAY, toAttach);
}
// -
void WebGLContext::FrontFace(GLenum mode) {
const FuncScope funcScope(*this, "frontFace");
if (IsContextLost()) return;

View File

@ -410,6 +410,12 @@ JS::Value WebGLContext::GetParameter(JSContext* cx, GLenum pname,
case LOCAL_GL_MAX_VARYING_VECTORS:
return JS::Int32Value(mGLMaxFragmentInputVectors);
case LOCAL_GL_MAX_VIEWS_OVR:
if (IsExtensionEnabled(WebGLExtensionID::OVR_multiview2)) {
return JS::NumberValue(mGLMaxMultiviewViews);
}
break;
case LOCAL_GL_COMPRESSED_TEXTURE_FORMATS: {
uint32_t length = mCompressedTextureFormats.Length();
JSObject* obj = dom::Uint32Array::Create(

View File

@ -411,6 +411,9 @@ bool WebGLContext::InitAndValidateGL(FailureReason* const out_failReason) {
(GLint*)&mGLMaxArrayTextureLayers))
mGLMaxArrayTextureLayers = 0;
(void)gl->GetPotentialInteger(LOCAL_GL_MAX_VIEWS_OVR,
(GLint*)&mGLMaxMultiviewViews);
gl->GetUIntegerv(LOCAL_GL_MAX_TEXTURE_IMAGE_UNITS,
&mGLMaxFragmentTextureImageUnits);
gl->GetUIntegerv(LOCAL_GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS,
@ -676,7 +679,7 @@ bool WebGLContext::InitAndValidateGL(FailureReason* const out_failReason) {
return true;
}
bool WebGLContext::ValidateFramebufferTarget(GLenum target) {
bool WebGLContext::ValidateFramebufferTarget(GLenum target) const {
bool isValid = true;
switch (target) {
case LOCAL_GL_FRAMEBUFFER:

View File

@ -72,4 +72,38 @@ bool WebGLExtensionFBORenderMipmap::IsSupported(
IMPL_WEBGL_EXTENSION_GOOP(WebGLExtensionFBORenderMipmap, OES_fbo_render_mipmap)
// -
WebGLExtensionMultiview::WebGLExtensionMultiview(WebGLContext* const webgl)
: WebGLExtensionBase(webgl) {
MOZ_ASSERT(IsSupported(webgl), "Don't construct extension if unsupported.");
}
WebGLExtensionMultiview::~WebGLExtensionMultiview() = default;
bool WebGLExtensionMultiview::IsSupported(const WebGLContext* const webgl) {
if (!webgl->IsWebGL2()) return false;
if (!gfxPrefs::WebGLDraftExtensionsEnabled()) return false;
const auto& gl = webgl->gl;
return gl->IsSupported(gl::GLFeature::multiview);
}
void WebGLExtensionMultiview::FramebufferTextureMultiviewOVR(
const GLenum target, const GLenum attachment, WebGLTexture* const texture,
const GLint level, const GLint baseViewIndex,
const GLsizei numViews) const {
const WebGLContext::FuncScope funcScope(*mContext,
"framebufferTextureMultiviewOVR");
if (mIsLost) {
mContext->ErrorInvalidOperation("Extension is lost.");
return;
}
mContext->FramebufferTextureMultiview(target, attachment, texture, level,
baseViewIndex, numViews);
}
IMPL_WEBGL_EXTENSION_GOOP(WebGLExtensionMultiview, OVR_multiview2)
} // namespace mozilla

View File

@ -28,8 +28,9 @@ class FormatUsageAuthority;
} // namespace webgl
class WebGLContext;
class WebGLShader;
class WebGLQuery;
class WebGLShader;
class WebGLTexture;
class WebGLVertexArray;
class WebGLExtensionBase : public nsWrapperCache,
@ -405,6 +406,20 @@ class WebGLExtensionMOZDebug final : public WebGLExtensionBase {
DECL_WEBGL_EXTENSION_GOOP
};
class WebGLExtensionMultiview : public WebGLExtensionBase {
public:
explicit WebGLExtensionMultiview(WebGLContext*);
virtual ~WebGLExtensionMultiview();
static bool IsSupported(const WebGLContext*);
void FramebufferTextureMultiviewOVR(GLenum target, GLenum attachment,
WebGLTexture* texture, GLint level,
GLint baseViewIndex,
GLsizei numViews) const;
DECL_WEBGL_EXTENSION_GOOP
};
} // namespace mozilla
#endif // WEBGL_EXTENSIONS_H_

View File

@ -51,44 +51,31 @@ bool WebGLFBAttachPoint::IsDeleteRequested() const {
: Renderbuffer() ? Renderbuffer()->IsDeleteRequested() : false;
}
void WebGLFBAttachPoint::Clear() {
mRenderbufferPtr = nullptr;
mTexturePtr = nullptr;
mTexImageTarget = 0;
mTexImageLevel = 0;
mTexImageLayer = 0;
}
void WebGLFBAttachPoint::Clear() { Set(nullptr, {}); }
void WebGLFBAttachPoint::SetTexImage(gl::GLContext* const gl,
WebGLTexture* const tex,
TexImageTarget target, GLint level,
GLint layer) {
Clear();
void WebGLFBAttachPoint::Set(gl::GLContext* const gl,
const webgl::FbAttachInfo& toAttach) {
mRenderbufferPtr = toAttach.rb;
mTexturePtr = toAttach.tex;
mTexImageLayer = AssertedCast<uint32_t>(toAttach.zLayer);
mTexImageZLayerCount = AssertedCast<uint8_t>(toAttach.zLayerCount);
mTexImageLevel = AssertedCast<uint8_t>(toAttach.mipLevel);
mIsMultiview = toAttach.isMultiview;
mTexturePtr = tex;
mTexImageTarget = target;
mTexImageLevel = level;
mTexImageLayer = layer;
if (!mDeferAttachment) {
DoAttachment(gl);
}
}
void WebGLFBAttachPoint::SetRenderbuffer(gl::GLContext* const gl,
WebGLRenderbuffer* const rb) {
Clear();
mRenderbufferPtr = rb;
if (!mDeferAttachment) {
if (gl && !mDeferAttachment) {
DoAttachment(gl);
}
}
const webgl::ImageInfo* WebGLFBAttachPoint::GetImageInfo() const {
if (mTexturePtr)
return &mTexturePtr->ImageInfoAt(mTexImageTarget, mTexImageLevel);
if (mTexturePtr) {
const auto target = Texture()->Target();
uint8_t face = 0;
if (target == LOCAL_GL_TEXTURE_CUBE_MAP) {
face = Layer() % 6;
}
return &mTexturePtr->ImageInfoAtFace(face, mTexImageLevel);
}
if (mRenderbufferPtr) return &mRenderbufferPtr->ImageInfo();
return nullptr;
}
@ -99,6 +86,7 @@ bool WebGLFBAttachPoint::IsComplete(WebGLContext* webgl,
const auto fnWriteErrorInfo = [&](const char* const text) {
WebGLContext::EnumName(mAttachmentPoint, out_info);
out_info->AppendLiteral(": ");
out_info->AppendASCII(text);
};
@ -117,7 +105,9 @@ bool WebGLFBAttachPoint::IsComplete(WebGLContext* webgl,
// because immutable textures are *always* texture-complete. We need to
// check immutable textures though, because checking completeness is also
// when we zero invalidated/no-data tex images.
const bool complete = [&]() {
const auto attachedMipLevel = MipLevel();
const bool withinValidMipLevels = [&]() {
const bool ensureInit = false;
const auto texCompleteness = tex->CalcCompletenessInfo(ensureInit);
if (!texCompleteness) // OOM
@ -126,10 +116,18 @@ bool WebGLFBAttachPoint::IsComplete(WebGLContext* webgl,
const auto baseLevel = tex->BaseMipmapLevel();
const auto maxLevel = baseLevel + texCompleteness->levels - 1;
return baseLevel <= mTexImageLevel && mTexImageLevel <= maxLevel;
return baseLevel <= attachedMipLevel && attachedMipLevel <= maxLevel;
}();
if (!complete) {
fnWriteErrorInfo("Attached texture is not texture-complete.");
if (!withinValidMipLevels) {
fnWriteErrorInfo("Attached mip level is invalid for texture.");
return false;
}
const auto& levelInfo = tex->ImageInfoAtFace(0, attachedMipLevel);
const auto faceDepth = levelInfo.mDepth * tex->FaceCount();
const bool withinValidZLayers = Layer() + ZLayerCount() - 1 < faceDepth;
if (!withinValidZLayers) {
fnWriteErrorInfo("Attached z layer is invalid for texture.");
return false;
}
}
@ -216,32 +214,38 @@ void WebGLFBAttachPoint::DoAttachment(gl::GLContext* const gl) const {
const auto& texName = Texture()->mGLName;
switch (mTexImageTarget.get()) {
switch (Texture()->Target().get()) {
case LOCAL_GL_TEXTURE_2D:
case LOCAL_GL_TEXTURE_CUBE_MAP_POSITIVE_X:
case LOCAL_GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
case LOCAL_GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
case LOCAL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
case LOCAL_GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
case LOCAL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
case LOCAL_GL_TEXTURE_CUBE_MAP: {
TexImageTarget imageTarget = LOCAL_GL_TEXTURE_2D;
if (Texture()->Target() == LOCAL_GL_TEXTURE_CUBE_MAP) {
imageTarget = LOCAL_GL_TEXTURE_CUBE_MAP_POSITIVE_X + Layer();
}
if (mAttachmentPoint == LOCAL_GL_DEPTH_STENCIL_ATTACHMENT) {
gl->fFramebufferTexture2D(
LOCAL_GL_FRAMEBUFFER, LOCAL_GL_DEPTH_ATTACHMENT,
mTexImageTarget.get(), texName, mTexImageLevel);
gl->fFramebufferTexture2D(
LOCAL_GL_FRAMEBUFFER, LOCAL_GL_STENCIL_ATTACHMENT,
mTexImageTarget.get(), texName, mTexImageLevel);
gl->fFramebufferTexture2D(LOCAL_GL_FRAMEBUFFER,
LOCAL_GL_DEPTH_ATTACHMENT, imageTarget.get(),
texName, MipLevel());
gl->fFramebufferTexture2D(LOCAL_GL_FRAMEBUFFER,
LOCAL_GL_STENCIL_ATTACHMENT,
imageTarget.get(), texName, MipLevel());
} else {
gl->fFramebufferTexture2D(LOCAL_GL_FRAMEBUFFER, mAttachmentPoint,
mTexImageTarget.get(), texName,
mTexImageLevel);
imageTarget.get(), texName, MipLevel());
}
break;
}
case LOCAL_GL_TEXTURE_2D_ARRAY:
case LOCAL_GL_TEXTURE_3D:
gl->fFramebufferTextureLayer(LOCAL_GL_FRAMEBUFFER, mAttachmentPoint,
texName, mTexImageLevel, mTexImageLayer);
if (ZLayerCount() != 1) {
gl->fFramebufferTextureMultiview(LOCAL_GL_FRAMEBUFFER, mAttachmentPoint,
texName, MipLevel(), Layer(),
ZLayerCount());
} else {
gl->fFramebufferTextureLayer(LOCAL_GL_FRAMEBUFFER, mAttachmentPoint,
texName, MipLevel(), Layer());
}
break;
}
}
@ -308,7 +312,7 @@ JS::Value WebGLFBAttachPoint::GetParameter(WebGLContext* webgl, JSContext* cx,
if (mTexturePtr) {
GLenum face = 0;
if (mTexturePtr->Target() == LOCAL_GL_TEXTURE_CUBE_MAP) {
face = ImageTarget().get();
face = LOCAL_GL_TEXTURE_CUBE_MAP_POSITIVE_X + Layer();
}
return JS::Int32Value(face);
}
@ -317,13 +321,20 @@ JS::Value WebGLFBAttachPoint::GetParameter(WebGLContext* webgl, JSContext* cx,
//////
case LOCAL_GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
if (webgl->IsWebGL2() && mTexturePtr) {
int32_t layer = 0;
if (ImageTarget() == LOCAL_GL_TEXTURE_2D_ARRAY ||
ImageTarget() == LOCAL_GL_TEXTURE_3D) {
layer = Layer();
}
return JS::Int32Value(layer);
if (webgl->IsWebGL2()) {
return JS::Int32Value(AssertedCast<int32_t>(Layer()));
}
break;
case LOCAL_GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_BASE_VIEW_INDEX_OVR:
if (webgl->IsExtensionEnabled(WebGLExtensionID::OVR_multiview2)) {
return JS::Int32Value(AssertedCast<int32_t>(Layer()));
}
break;
case LOCAL_GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_NUM_VIEWS_OVR:
if (webgl->IsExtensionEnabled(WebGLExtensionID::OVR_multiview2)) {
return JS::Int32Value(ZLayerCount());
}
break;
@ -674,6 +685,20 @@ FBStatus WebGLFramebuffer::PrecheckFramebufferStatus(
if (depthOrStencilCount > 1) return LOCAL_GL_FRAMEBUFFER_UNSUPPORTED;
}
{
const WebGLFBAttachPoint* example = nullptr;
for (const auto& x : mAttachments) {
if (!x->HasAttachment()) continue;
if (!example) {
example = x;
continue;
}
if (x->ZLayerCount() != example->ZLayerCount()) {
return LOCAL_GL_FRAMEBUFFER_INCOMPLETE_VIEW_TARGETS_OVR;
}
}
}
return LOCAL_GL_FRAMEBUFFER_COMPLETE;
}
@ -736,6 +761,12 @@ bool WebGLFramebuffer::ValidateForColorRead(
return false;
}
if (mColorReadBuffer->ZLayerCount() > 1) {
mContext->GenerateError(LOCAL_GL_INVALID_FRAMEBUFFER_OPERATION,
"The READ_BUFFER attachment has multiple views.");
return false;
}
const auto& imageInfo = mColorReadBuffer->GetImageInfo();
if (!imageInfo) {
mContext->ErrorInvalidOperation(
@ -841,18 +872,15 @@ void WebGLFramebuffer::ResolveAttachmentData() const {
};
if (imageInfo->mDepth > 1) {
// Todo: Use glClearTexImage.
const auto& tex = cur->Texture();
const gl::ScopedFramebuffer scopedFB(gl);
const gl::ScopedBindFramebuffer scopedBindFB(gl, scopedFB.FB());
for (uint32_t z = 0; z < imageInfo->mDepth; z++) {
gl->fFramebufferTextureLayer(LOCAL_GL_FRAMEBUFFER,
cur->mAttachmentPoint, tex->mGLName,
cur->MipLevel(), z);
fnClearBuffer();
}
gl->fFramebufferTextureLayer(LOCAL_GL_FRAMEBUFFER,
cur->mAttachmentPoint, tex->mGLName,
cur->MipLevel(), cur->Layer());
} else {
fnClearBuffer();
}
@ -979,6 +1007,8 @@ FBStatus WebGLFramebuffer::CheckFramebufferStatus() const {
info.width = std::min(info.width, imageInfo->mWidth);
info.height = std::min(info.height, imageInfo->mHeight);
info.hasFloat32 |= fnIsFloat32(*imageInfo->mFormat->format);
info.zLayerCount = cur->ZLayerCount();
info.isMultiview = cur->IsMultiview();
}
mCompletenessInfo = Some(std::move(info));
return LOCAL_GL_FRAMEBUFFER_COMPLETE;
@ -1103,9 +1133,8 @@ void WebGLFramebuffer::ReadBuffer(GLenum attachPoint) {
////
void WebGLFramebuffer::FramebufferRenderbuffer(GLenum attachEnum,
GLenum rbtarget,
WebGLRenderbuffer* rb) {
void WebGLFramebuffer::FramebufferAttach(const GLenum attachEnum,
const webgl::FbAttachInfo& toAttach) {
MOZ_ASSERT(mContext->mBoundDrawFramebuffer == this ||
mContext->mBoundReadFramebuffer == this);
@ -1117,202 +1146,17 @@ void WebGLFramebuffer::FramebufferRenderbuffer(GLenum attachEnum,
}
const auto& attach = maybeAttach.value();
// `rbTarget`
if (rbtarget != LOCAL_GL_RENDERBUFFER) {
mContext->ErrorInvalidEnumInfo("rbtarget", rbtarget);
return;
}
// `rb`
if (rb) {
if (!mContext->ValidateObject("rb", *rb)) return;
if (!rb->mHasBeenBound) {
mContext->ErrorInvalidOperation(
"bindRenderbuffer must be called before"
" attachment to %04x",
attachEnum);
return;
}
}
// End of validation.
const auto& gl = mContext->gl;
gl->fBindFramebuffer(LOCAL_GL_FRAMEBUFFER, mGLName);
if (mContext->IsWebGL2() && attachEnum == LOCAL_GL_DEPTH_STENCIL_ATTACHMENT) {
mDepthAttachment.SetRenderbuffer(gl, rb);
mStencilAttachment.SetRenderbuffer(gl, rb);
mDepthAttachment.Set(gl, toAttach);
mStencilAttachment.Set(gl, toAttach);
} else {
attach->SetRenderbuffer(gl, rb);
attach->Set(gl, toAttach);
}
InvalidateCaches();
}
void WebGLFramebuffer::FramebufferTexture2D(GLenum attachEnum,
GLenum texImageTarget,
WebGLTexture* tex, GLint level) {
MOZ_ASSERT(mContext->mBoundDrawFramebuffer == this ||
mContext->mBoundReadFramebuffer == this);
// `attachment`
const auto maybeAttach = GetAttachPoint(attachEnum);
if (!maybeAttach || !maybeAttach.value()) {
mContext->ErrorInvalidEnum("Bad `attachment`: 0x%x.", attachEnum);
return;
}
const auto& attach = maybeAttach.value();
// `texImageTarget`
if (texImageTarget != LOCAL_GL_TEXTURE_2D &&
(texImageTarget < LOCAL_GL_TEXTURE_CUBE_MAP_POSITIVE_X ||
texImageTarget > LOCAL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Z)) {
mContext->ErrorInvalidEnumInfo("texImageTarget", texImageTarget);
return;
}
// `texture`
if (tex) {
if (!mContext->ValidateObject("texture", *tex)) return;
if (!tex->Target()) {
mContext->ErrorInvalidOperation("`texture` has never been bound.");
return;
}
const TexTarget destTexTarget = TexImageTargetToTexTarget(texImageTarget);
if (tex->Target() != destTexTarget) {
mContext->ErrorInvalidOperation("Mismatched texture and texture target.");
return;
}
}
// `level`
if (level < 0)
return mContext->ErrorInvalidValue("`level` must not be negative.");
if (mContext->IsWebGL2() ||
mContext->IsExtensionEnabled(WebGLExtensionID::OES_fbo_render_mipmap)) {
/* GLES 3.0.4 p208:
* If textarget is one of TEXTURE_CUBE_MAP_POSITIVE_X,
* TEXTURE_CUBE_MAP_POSITIVE_Y, TEXTURE_CUBE_MAP_POSITIVE_Z,
* TEXTURE_CUBE_MAP_NEGATIVE_X, TEXTURE_CUBE_MAP_NEGATIVE_Y,
* or TEXTURE_CUBE_MAP_NEGATIVE_Z, then level must be greater
* than or equal to zero and less than or equal to log2 of the
* value of MAX_CUBE_MAP_TEXTURE_SIZE. If textarget is TEXTURE_2D,
* level must be greater than or equal to zero and no larger than
* log2 of the value of MAX_TEXTURE_SIZE. Otherwise, an
* INVALID_VALUE error is generated.
*/
if (texImageTarget == LOCAL_GL_TEXTURE_2D) {
if (uint32_t(level) > FloorLog2(mContext->mGLMaxTextureSize))
return mContext->ErrorInvalidValue("`level` is too large.");
} else {
MOZ_ASSERT(texImageTarget >= LOCAL_GL_TEXTURE_CUBE_MAP_POSITIVE_X &&
texImageTarget <= LOCAL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Z);
if (uint32_t(level) > FloorLog2(mContext->mGLMaxCubeMapTextureSize))
return mContext->ErrorInvalidValue("`level` is too large.");
}
} else if (level != 0) {
return mContext->ErrorInvalidValue("`level` must be 0.");
}
// End of validation.
const auto& gl = mContext->gl;
gl->fBindFramebuffer(LOCAL_GL_FRAMEBUFFER, mGLName);
if (mContext->IsWebGL2() && attachEnum == LOCAL_GL_DEPTH_STENCIL_ATTACHMENT) {
mDepthAttachment.SetTexImage(gl, tex, texImageTarget, level);
mStencilAttachment.SetTexImage(gl, tex, texImageTarget, level);
} else {
attach->SetTexImage(gl, tex, texImageTarget, level);
}
InvalidateCaches();
}
void WebGLFramebuffer::FramebufferTextureLayer(GLenum attachEnum,
WebGLTexture* tex, GLint level,
GLint layer) {
MOZ_ASSERT(mContext->mBoundDrawFramebuffer == this ||
mContext->mBoundReadFramebuffer == this);
// `attachment`
const auto maybeAttach = GetAttachPoint(attachEnum);
if (!maybeAttach || !maybeAttach.value()) {
mContext->ErrorInvalidEnum("Bad `attachment`: 0x%x.", attachEnum);
return;
}
const auto& attach = maybeAttach.value();
// `level`, `layer`
if (layer < 0) return mContext->ErrorInvalidValue("`layer` must be >= 0.");
if (level < 0) return mContext->ErrorInvalidValue("`level` must be >= 0.");
// `texture`
GLenum texImageTarget = LOCAL_GL_TEXTURE_3D;
if (tex) {
if (!mContext->ValidateObject("texture", *tex)) return;
if (!tex->Target()) {
mContext->ErrorInvalidOperation("`texture` has never been bound.");
return;
}
texImageTarget = tex->Target().get();
switch (texImageTarget) {
case LOCAL_GL_TEXTURE_3D:
if (uint32_t(layer) >= mContext->mGLMax3DTextureSize) {
mContext->ErrorInvalidValue("`layer` must be < %s.",
"MAX_3D_TEXTURE_SIZE");
return;
}
if (uint32_t(level) > FloorLog2(mContext->mGLMax3DTextureSize)) {
mContext->ErrorInvalidValue("`level` must be <= log2(%s).",
"MAX_3D_TEXTURE_SIZE");
return;
}
break;
case LOCAL_GL_TEXTURE_2D_ARRAY:
if (uint32_t(layer) >= mContext->mGLMaxArrayTextureLayers) {
mContext->ErrorInvalidValue("`layer` must be < %s.",
"MAX_ARRAY_TEXTURE_LAYERS");
return;
}
if (uint32_t(level) > FloorLog2(mContext->mGLMaxTextureSize)) {
mContext->ErrorInvalidValue("`level` must be <= log2(%s).",
"MAX_TEXTURE_SIZE");
return;
}
break;
default:
mContext->ErrorInvalidOperation(
"`texture` must be a TEXTURE_3D or"
" TEXTURE_2D_ARRAY.");
return;
}
}
// End of validation.
const auto& gl = mContext->gl;
gl->fBindFramebuffer(LOCAL_GL_FRAMEBUFFER, mGLName);
if (mContext->IsWebGL2() && attachEnum == LOCAL_GL_DEPTH_STENCIL_ATTACHMENT) {
mDepthAttachment.SetTexImage(gl, tex, texImageTarget, level, layer);
mStencilAttachment.SetTexImage(gl, tex, texImageTarget, level, layer);
} else {
attach->SetTexImage(gl, tex, texImageTarget, level, layer);
}
InvalidateCaches();
}
JS::Value WebGLFramebuffer::GetAttachmentParameter(
JSContext* cx, GLenum target, GLenum attachEnum, GLenum pname,
ErrorResult* const out_error) {
@ -1417,6 +1261,12 @@ void WebGLFramebuffer::BlitFramebuffer(WebGLContext* webgl, GLint srcX0,
const webgl::FormatInfo* srcStencilFormat;
if (srcFB) {
const auto& info = *srcFB->GetCompletenessInfo();
if (info.zLayerCount != 1) {
webgl->GenerateError(LOCAL_GL_INVALID_FRAMEBUFFER_OPERATION,
"Source framebuffer cannot have multiple views.");
return;
}
srcColorFormat = nullptr;
if (srcFB->mColorReadBuffer) {
const auto& imageInfo = srcFB->mColorReadBuffer->GetImageInfo();

View File

@ -31,6 +31,17 @@ namespace gl {
class GLContext;
} // namespace gl
namespace webgl {
struct FbAttachInfo final {
WebGLRenderbuffer* rb = nullptr;
WebGLTexture* tex = nullptr;
GLint mipLevel = 0;
GLint zLayer = 0;
GLsizei zLayerCount = 1;
bool isMultiview = false;
};
} // namespace webgl
class WebGLFBAttachPoint final {
friend class WebGLFramebuffer;
@ -41,9 +52,10 @@ class WebGLFBAttachPoint final {
private:
WebGLRefPtr<WebGLTexture> mTexturePtr;
WebGLRefPtr<WebGLRenderbuffer> mRenderbufferPtr;
TexImageTarget mTexImageTarget = 0;
GLint mTexImageLayer = 0;
uint32_t mTexImageLevel = 0;
uint32_t mTexImageLayer = 0;
uint8_t mTexImageZLayerCount = 1;
uint8_t mTexImageLevel = 0;
bool mIsMultiview = false;
////
@ -67,16 +79,16 @@ class WebGLFBAttachPoint final {
void Clear();
void SetTexImage(gl::GLContext* gl, WebGLTexture* tex, TexImageTarget target,
GLint level, GLint layer = 0);
void SetRenderbuffer(gl::GLContext* gl, WebGLRenderbuffer* rb);
void Set(gl::GLContext* gl, const webgl::FbAttachInfo&);
WebGLTexture* Texture() const { return mTexturePtr; }
WebGLRenderbuffer* Renderbuffer() const { return mRenderbufferPtr; }
TexImageTarget ImageTarget() const { return mTexImageTarget; }
GLint Layer() const { return mTexImageLayer; }
uint32_t MipLevel() const { return mTexImageLevel; }
auto Layer() const { return mTexImageLayer; }
auto ZLayerCount() const { return mTexImageZLayerCount; }
auto MipLevel() const { return mTexImageLevel; }
const auto& IsMultiview() const { return mIsMultiview; }
void AttachmentName(nsCString* out) const;
const webgl::ImageInfo* GetImageInfo() const;
@ -93,8 +105,8 @@ class WebGLFBAttachPoint final {
if (!HasAttachment() | !other.HasAttachment()) return false;
#define _(X) (X == other.X)
return (_(mRenderbufferPtr) & _(mTexturePtr) & _(mTexImageTarget.get()) &
_(mTexImageLevel) & _(mTexImageLayer));
return (_(mRenderbufferPtr) && _(mTexturePtr) && _(mTexImageLevel) &&
_(mTexImageLayer) && _(mTexImageZLayerCount));
#undef _
}
@ -113,9 +125,9 @@ class WebGLFBAttachPoint final {
ORDER_BY(mRef.mRenderbufferPtr)
ORDER_BY(mRef.mTexturePtr)
ORDER_BY(mRef.mTexImageTarget.get())
ORDER_BY(mRef.mTexImageLevel)
ORDER_BY(mRef.mTexImageLayer)
ORDER_BY(mRef.mTexImageZLayerCount)
#undef ORDER_BY
return false;
@ -167,6 +179,8 @@ class WebGLFramebuffer final : public nsWrapperCache,
uint32_t width = 0;
uint32_t height = 0;
bool hasFloat32 = false;
uint8_t zLayerCount = 1;
bool isMultiview = false;
// IsFeedback
std::vector<const WebGLFBAttachPoint*> texAttachments; // Non-null
@ -256,12 +270,8 @@ class WebGLFramebuffer final : public nsWrapperCache,
}
FBStatus CheckFramebufferStatus() const;
void FramebufferRenderbuffer(GLenum attachment, GLenum rbtarget,
WebGLRenderbuffer* rb);
void FramebufferTexture2D(GLenum attachment, GLenum texImageTarget,
WebGLTexture* tex, GLint level);
void FramebufferTextureLayer(GLenum attachment, WebGLTexture* tex,
GLint level, GLint layer);
void FramebufferAttach(GLenum attachEnum,
const webgl::FbAttachInfo& toAttach);
void DrawBuffers(const dom::Sequence<GLenum>& buffers);
void ReadBuffer(GLenum attachPoint);

View File

@ -535,6 +535,15 @@ static RefPtr<const webgl::LinkedProgramInfo> QueryProgramInfo(
}
}
const auto& vertShader = prog->VertShader();
MOZ_RELEASE_ASSERT(vertShader);
MOZ_RELEASE_ASSERT(vertShader->Validator());
const auto& handle = vertShader->Validator()->mHandle;
const auto numViews = sh::GetVertexShaderNumViews(handle);
if (numViews != -1) {
info->zLayerCount = AssertedCast<uint8_t>(numViews);
}
return info;
}

View File

@ -107,6 +107,7 @@ struct LinkedProgramInfo final : public RefCounted<LinkedProgramInfo>,
std::vector<UniformBlockInfo*> uniformBlocks; // Owns its contents.
std::vector<RefPtr<WebGLActiveInfo>> transformFeedbackVaryings;
std::unordered_map<uint8_t, const FragOutputInfo> fragOutputs;
uint8_t zLayerCount = 1;
// Needed for draw call validation.
std::vector<UniformInfo*> uniformSamplers;
@ -207,6 +208,7 @@ class WebGLProgram final : public nsWrapperCache,
return mMostRecentLinkInfo.get();
}
const auto& VertShader() const { return mVertShader; }
const auto& FragShader() const { return mFragShader; }
WebGLContext* GetParentObject() const { return mContext; }

View File

@ -182,6 +182,11 @@ webgl::ShaderValidator* WebGLContext::CreateShaderValidator(
if (IsExtensionEnabled(WebGLExtensionID::EXT_shader_texture_lod))
resources.EXT_shader_texture_lod = 1;
if (IsExtensionEnabled(WebGLExtensionID::OVR_multiview2)) {
resources.OVR_multiview2 = 1;
resources.MaxViewsOVR = mGLMaxMultiviewViews;
}
// Tell ANGLE to allow highp in frag shaders. (unless disabled)
// If underlying GLES doesn't have highp in frag shaders, it should complain
// anyways.

View File

@ -349,6 +349,7 @@ STRONG_GLENUM_VALUE(NONE), STRONG_GLENUM_VALUE(TEXTURE_2D),
STRONG_GLENUM_VALUE(FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER),
STRONG_GLENUM_VALUE(FRAMEBUFFER_INCOMPLETE_READ_BUFFER),
STRONG_GLENUM_VALUE(FRAMEBUFFER_UNSUPPORTED),
STRONG_GLENUM_VALUE(FRAMEBUFFER_INCOMPLETE_VIEW_TARGETS_OVR),
STRONG_GLENUM_END(FBStatus)
STRONG_GLENUM_BEGIN(RBParam) STRONG_GLENUM_VALUE(RENDERBUFFER_SAMPLES),

View File

@ -154,6 +154,7 @@ class WebGLTexture final : public nsWrapperCache,
const auto& Immutable() const { return mImmutable; }
const auto& BaseMipmapLevel() const { return mBaseMipmapLevel; }
const auto& FaceCount() const { return mFaceCount; }
// We can just max this out to 31, which is the number of unsigned bits in
// GLsizei.
@ -208,7 +209,6 @@ class WebGLTexture final : public nsWrapperCache,
uint32_t width, uint32_t height,
uint32_t depth,
webgl::ImageInfo** const out_imageInfo);
bool ValidateCopyTexImageForFeedback(uint32_t level, GLint layer = 0) const;
bool ValidateUnpack(const webgl::TexUnpackBlob* blob, bool isFunc3D,
const webgl::PackingInfo& srcPI) const;
@ -278,6 +278,7 @@ class WebGLTexture final : public nsWrapperCache,
}
}
public:
auto& ImageInfoAtFace(uint8_t face, uint32_t level) {
MOZ_ASSERT(face < mFaceCount);
MOZ_ASSERT(level < kMaxLevelCount);
@ -289,7 +290,6 @@ class WebGLTexture final : public nsWrapperCache,
return const_cast<WebGLTexture*>(this)->ImageInfoAtFace(face, level);
}
public:
auto& ImageInfoAt(TexImageTarget texImageTarget, GLint level) {
const auto& face = FaceForTarget(texImageTarget);
return ImageInfoAtFace(face, level);

View File

@ -1893,22 +1893,26 @@ static const webgl::FormatUsageInfo* ValidateCopyDestUsage(
return dstUsage;
}
bool WebGLTexture::ValidateCopyTexImageForFeedback(uint32_t level,
GLint layer) const {
const auto& fb = mContext->mBoundReadFramebuffer;
static bool ValidateCopyTexImageForFeedback(const WebGLContext& webgl,
const WebGLTexture& tex,
const uint8_t mipLevel,
const uint32_t zLayer) {
const auto& fb = webgl.BoundReadFb();
if (fb) {
const auto& attach = fb->ColorReadBuffer();
MOZ_ASSERT(attach);
MOZ_ASSERT(fb->ColorReadBuffer());
const auto& attach = *fb->ColorReadBuffer();
MOZ_ASSERT(attach.ZLayerCount() ==
1); // Multiview invalid for copyTexImage.
if (attach->Texture() == this && attach->Layer() == layer &&
uint32_t(attach->MipLevel()) == level) {
if (attach.Texture() == &tex && attach.Layer() == zLayer &&
attach.MipLevel() == mipLevel) {
// Note that the TexImageTargets *don't* have to match for this to be
// undefined per GLES 3.0.4 p211, thus an INVALID_OP in WebGL.
mContext->ErrorInvalidOperation(
webgl.ErrorInvalidOperation(
"Feedback loop detected, as this texture"
" is already attached to READ_FRAMEBUFFER's"
" READ_BUFFER-selected COLOR_ATTACHMENT%u.",
attach->mAttachmentPoint);
attach.mAttachmentPoint);
return false;
}
}
@ -2052,7 +2056,10 @@ void WebGLTexture::CopyTexImage2D(TexImageTarget target, GLint level,
return;
}
if (!ValidateCopyTexImageForFeedback(level)) return;
const uint32_t zOffset = 0;
if (!ValidateCopyTexImageForFeedback(*mContext, *this,
AssertedCast<uint8_t>(level), zOffset))
return;
////////////////////////////////////
// Check that source and dest info are compatible
@ -2138,7 +2145,10 @@ void WebGLTexture::CopyTexSubImage(TexImageTarget target, GLint level,
return;
}
if (!ValidateCopyTexImageForFeedback(level, zOffset)) return;
if (!ValidateCopyTexImageForFeedback(*mContext, *this,
AssertedCast<uint8_t>(level),
AssertedCast<uint32_t>(zOffset)))
return;
////////////////////////////////////
// Check that source and dest info are compatible

View File

@ -178,6 +178,7 @@ enum class WebGLExtensionID : uint8_t {
OES_texture_half_float,
OES_texture_half_float_linear,
OES_vertex_array_object,
OVR_multiview2,
WEBGL_color_buffer_float,
WEBGL_compressed_texture_astc,
WEBGL_compressed_texture_etc,

View File

@ -5074,6 +5074,7 @@ subsuite = webgl2-core
subsuite = webgl2-core
[generated/test_2_conformance2__extensions__ovr_multiview2.html]
subsuite = webgl2-core
fail-if = (os == 'win')
[generated/test_2_conformance2__extensions__ovr_multiview2_depth.html]
subsuite = webgl2-core
[generated/test_2_conformance2__extensions__ovr_multiview2_draw_buffers.html]
@ -5086,6 +5087,7 @@ subsuite = webgl2-core
subsuite = webgl2-core
[generated/test_2_conformance2__extensions__ovr_multiview2_single_view_operations.html]
subsuite = webgl2-core
fail-if = (os == 'win')
[generated/test_2_conformance2__extensions__ovr_multiview2_timer_query.html]
subsuite = webgl2-core
[generated/test_2_conformance2__extensions__ovr_multiview2_transform_feedback.html]

View File

@ -79,6 +79,12 @@ skip-if = (os == 'win')
[generated/test_2_conformance__extensions__webgl-compressed-texture-s3tc.html]
# getError expected: NO_ERROR. Was INVALID_OPERATION : uploading a texture from a PBO subrange
fail-if = 1
[generated/test_2_conformance2__extensions__ovr_multiview2.html]
# Test fixed upstream, just needs revendor.
fail-if = (os == 'win')
[generated/test_2_conformance2__extensions__ovr_multiview2_single_view_operations.html]
# Test fixed upstream, just needs revendor.
fail-if = (os == 'win')
[generated/test_conformance__offscreencanvas__context-attribute-preserve-drawing-buffer.html]
# Timeout, likely issue with unsupported OffscreenCanvas.
skip-if = 1

View File

@ -0,0 +1,20 @@
<!DOCTYPE HTML>
<html>
<head>
<meta charset='utf-8'/>
<script src='/tests/SimpleTest/SimpleTest.js'></script>
<link rel='stylesheet' href='/tests/SimpleTest/test.css'>
<script src='ensure-ext.js'></script>
</head>
<body>
<script>
'use strict';
Lastly_WithDraftExtsEnabled(function() {
EnsureExtFor('webgl2', 'OVR_multiview2');
});
</script>
</body>
</html>

View File

@ -54,7 +54,8 @@ var defaultExts = [
];
var draftExts = [
['OES_fbo_render_mipmap', [MACHINE_SPECIFIC, FORBID ]],
['OES_fbo_render_mipmap', [MACHINE_SPECIFIC, FORBID]],
['OVR_multiview2' , [FORBID, MACHINE_SPECIFIC]],
];
////////////////////

View File

@ -38,6 +38,8 @@ fail-if = (os == 'android') || (os == 'linux')
fail-if = (os == 'android') || (os == 'win')
[ensure-exts/test_OES_standard_derivatives.html]
fail-if = (os == 'android')
[ensure-exts/test_OVR_multiview2.html]
fail-if = (os == 'linux') || (os == 'mac')
[ensure-exts/test_WEBGL_color_buffer_float.html]
fail-if = (os == 'android')
[ensure-exts/test_WEBGL_compressed_texture_astc.html]

View File

@ -700,3 +700,13 @@ WebGL2RenderingContext implements WebGL2RenderingContextBase;
[NoInterfaceObject]
interface EXT_color_buffer_float {
};
[NoInterfaceObject]
interface OVR_multiview2 {
const GLenum FRAMEBUFFER_ATTACHMENT_TEXTURE_NUM_VIEWS_OVR = 0x9630;
const GLenum FRAMEBUFFER_ATTACHMENT_TEXTURE_BASE_VIEW_INDEX_OVR = 0x9632;
const GLenum MAX_VIEWS_OVR = 0x9631;
const GLenum FRAMEBUFFER_INCOMPLETE_VIEW_TARGETS_OVR = 0x9633;
void framebufferTextureMultiviewOVR(GLenum target, GLenum attachment, WebGLTexture? texture, GLint level, GLint baseViewIndex, GLsizei numViews);
};

View File

@ -230,7 +230,7 @@ const ShCompileOptions SH_INITIALIZE_BUILTINS_FOR_INSTANCED_MULTIVIEW = UINT64_C
// With the flag enabled the GLSL/ESSL vertex shader is modified to include code for viewport
// selection in the following way:
// - Code to enable the extension NV_viewport_array2 is included.
// - Code to enable the extension ARB_shader_viewport_layer_array/NV_viewport_array2 is included.
// - Code to select the viewport index or layer is inserted at the beginning of main after
// ViewID_OVR's initialization.
// - A declaration of the uniform multiviewBaseViewLayerIndex.

View File

@ -1,3 +1,3 @@
#define ANGLE_COMMIT_HASH "5814bb88b10e"
#define ANGLE_COMMIT_HASH "1d5494fc3e85"
#define ANGLE_COMMIT_HASH_SIZE 12
#define ANGLE_COMMIT_DATE "2019-05-06 18:40:01 -0700"
#define ANGLE_COMMIT_DATE "2019-05-22 18:13:00 -0700"

View File

@ -1373,4 +1373,40 @@ bool TCompiler::isVaryingDefined(const char *varyingName)
return false;
}
void EmitMultiviewGLSL(const TCompiler &compiler,
const ShCompileOptions &compileOptions,
const TBehavior behavior,
TInfoSinkBase &sink)
{
ASSERT(behavior != EBhUndefined);
if (behavior == EBhDisable)
return;
const bool isVertexShader = (compiler.getShaderType() == GL_VERTEX_SHADER);
if (compileOptions & SH_INITIALIZE_BUILTINS_FOR_INSTANCED_MULTIVIEW)
{
// Emit ARB_shader_viewport_layer_array/NV_viewport_array2 in a vertex shader if the
// SH_SELECT_VIEW_IN_NV_GLSL_VERTEX_SHADER option is set and the
// OVR_multiview(2) extension is requested.
if (isVertexShader && (compileOptions & SH_SELECT_VIEW_IN_NV_GLSL_VERTEX_SHADER))
{
sink << "#if defined(GL_ARB_shader_viewport_layer_array)\n"
<< "#extension GL_ARB_shader_viewport_layer_array : require\n"
<< "#elif defined(GL_NV_viewport_array2)\n"
<< "#extension GL_NV_viewport_array2 : require\n"
<< "#endif\n";
}
}
else
{
sink << "#extension GL_OVR_multiview2 : " << GetBehaviorString(behavior) << "\n";
const auto &numViews = compiler.getNumViews();
if (isVertexShader && numViews != -1)
{
sink << "layout(num_views=" << numViews << ") in;\n";
}
}
}
} // namespace sh

View File

@ -296,6 +296,8 @@ class TCompiler : public TShHandleBase
TCompiler *ConstructCompiler(sh::GLenum type, ShShaderSpec spec, ShShaderOutput output);
void DeleteCompiler(TCompiler *);
void EmitMultiviewGLSL(const TCompiler &, const ShCompileOptions &, TBehavior, TInfoSinkBase &sink);
} // namespace sh
#endif // COMPILER_TRANSLATOR_COMPILER_H_

View File

@ -124,9 +124,6 @@ void TranslatorESSL::writeExtensionBehavior(ShCompileOptions compileOptions)
{
TInfoSinkBase &sink = getInfoSink().obj;
const TExtensionBehavior &extBehavior = getExtensionBehavior();
const bool isMultiviewExtEmulated =
(compileOptions & (SH_INITIALIZE_BUILTINS_FOR_INSTANCED_MULTIVIEW |
SH_SELECT_VIEW_IN_NV_GLSL_VERTEX_SHADER)) != 0u;
for (TExtensionBehavior::const_iterator iter = extBehavior.begin(); iter != extBehavior.end();
++iter)
{
@ -144,16 +141,9 @@ void TranslatorESSL::writeExtensionBehavior(ShCompileOptions compileOptions)
sink << "#extension GL_NV_draw_buffers : " << GetBehaviorString(iter->second)
<< "\n";
}
else if (isMultiview && isMultiviewExtEmulated)
else if (isMultiview)
{
if (getShaderType() == GL_VERTEX_SHADER &&
(compileOptions & SH_SELECT_VIEW_IN_NV_GLSL_VERTEX_SHADER) != 0u)
{
// Emit the NV_viewport_array2 extension in a vertex shader if the
// SH_SELECT_VIEW_IN_NV_GLSL_VERTEX_SHADER option is set and the
// OVR_multiview2 extension is requested.
sink << "#extension GL_NV_viewport_array2 : require\n";
}
EmitMultiviewGLSL(*this, compileOptions, iter->second, sink);
}
else if (iter->first == TExtension::EXT_geometry_shader)
{

View File

@ -278,13 +278,9 @@ void TranslatorGLSL::writeExtensionBehavior(TIntermNode *root, ShCompileOptions
}
const bool isMultiview = (iter.first == TExtension::OVR_multiview2);
if (isMultiview && getShaderType() == GL_VERTEX_SHADER &&
(compileOptions & SH_SELECT_VIEW_IN_NV_GLSL_VERTEX_SHADER) != 0u)
if (isMultiview)
{
// Emit the NV_viewport_array2 extension in a vertex shader if the
// SH_SELECT_VIEW_IN_NV_GLSL_VERTEX_SHADER option is set and the OVR_multiview2(2)
// extension is requested.
sink << "#extension GL_NV_viewport_array2 : require\n";
EmitMultiviewGLSL(*this, compileOptions, iter.second, sink);
}
// Support ANGLE_texture_multisample extension on GLSL300

View File

@ -1,3 +1,15 @@
commit 1d5494fc3e856d4d722e266d2b2075debac5146f
Author: Jeff Gilbert <jgilbert@mozilla.com>
Date: Thu Apr 25 14:57:26 2019 -0700
Emit OVR_multiview2 on ESSL/GLSL outputs.
Add ARB_shader_viewport_layer_array support to
SH_SELECT_VIEW_IN_NV_GLSL_VERTEX_SHADER.
Bug: angleproject:3404
Change-Id: Ia89517d0cc92400ce47c9118e8c1abf8285aec41
commit 5814bb88b10ef903abcf297f2de72619d853b4e9
Author: Lee Salzman <lsalzman@mozilla.com>
Date: Tue Apr 30 23:42:31 2019 -0400

View File

@ -11,7 +11,7 @@ DEFINES['DYNAMIC_ANNOTATIONS_ENABLED'] = '1'
#DEFINES['FULL_SAFE_BROWSING'] = True
DEFINES['NOMINMAX'] = True
#DEFINES['NO_TCMALLOC'] = True
DEFINES['NTDDI_VERSION'] = '0x0A000003'
DEFINES['NTDDI_VERSION'] = 'NTDDI_WIN10_RS2'
#DEFINES['PSAPI_VERSION'] = '2'
#DEFINES['SAFE_BROWSING_CSD'] = True
#DEFINES['SAFE_BROWSING_DB_LOCAL'] = True
@ -45,7 +45,6 @@ LOCAL_INCLUDES += [
#CXXFLAGS += [
# '/bigobj',
# '/d2FastFail',
# '/D__DATE__=',
# '/D__TIME__=',
# '/D__TIMESTAMP__=',

View File

@ -11,7 +11,7 @@ DEFINES['DYNAMIC_ANNOTATIONS_ENABLED'] = '1'
DEFINES['GPU_INFO_USE_SETUPAPI'] = True
DEFINES['NOMINMAX'] = True
#DEFINES['NO_TCMALLOC'] = True
DEFINES['NTDDI_VERSION'] = '0x0A000003'
DEFINES['NTDDI_VERSION'] = 'NTDDI_WIN10_RS2'
#DEFINES['PSAPI_VERSION'] = '2'
#DEFINES['SAFE_BROWSING_CSD'] = True
#DEFINES['SAFE_BROWSING_DB_LOCAL'] = True
@ -45,7 +45,6 @@ LOCAL_INCLUDES += [
#CXXFLAGS += [
# '/bigobj',
# '/d2FastFail',
# '/D__DATE__=',
# '/D__TIME__=',
# '/D__TIMESTAMP__=',

View File

@ -10,7 +10,7 @@ DEFINES['DYNAMIC_ANNOTATIONS_ENABLED'] = '1'
#DEFINES['FULL_SAFE_BROWSING'] = True
DEFINES['NOMINMAX'] = True
#DEFINES['NO_TCMALLOC'] = True
DEFINES['NTDDI_VERSION'] = '0x0A000003'
DEFINES['NTDDI_VERSION'] = 'NTDDI_WIN10_RS2'
#DEFINES['PSAPI_VERSION'] = '2'
#DEFINES['SAFE_BROWSING_CSD'] = True
#DEFINES['SAFE_BROWSING_DB_LOCAL'] = True
@ -44,7 +44,6 @@ LOCAL_INCLUDES += [
#CXXFLAGS += [
# '/bigobj',
# '/d2FastFail',
# '/D__DATE__=',
# '/D__TIME__=',
# '/D__TIMESTAMP__=',

View File

@ -16,7 +16,7 @@ DEFINES['DYNAMIC_ANNOTATIONS_ENABLED'] = '1'
DEFINES['LIBANGLE_IMPLEMENTATION'] = True
DEFINES['NOMINMAX'] = True
#DEFINES['NO_TCMALLOC'] = True
DEFINES['NTDDI_VERSION'] = '0x0A000003'
DEFINES['NTDDI_VERSION'] = 'NTDDI_WIN10_RS2'
#DEFINES['PSAPI_VERSION'] = '2'
#DEFINES['SAFE_BROWSING_CSD'] = True
#DEFINES['SAFE_BROWSING_DB_LOCAL'] = True
@ -50,7 +50,6 @@ LOCAL_INCLUDES += [
#CXXFLAGS += [
# '/bigobj',
# '/d2FastFail',
# '/D__DATE__=',
# '/D__TIME__=',
# '/D__TIMESTAMP__=',

View File

@ -20,7 +20,7 @@ DEFINES['GL_GLEXT_PROTOTYPES'] = True
DEFINES['LIBEGL_IMPLEMENTATION'] = True
DEFINES['NOMINMAX'] = True
#DEFINES['NO_TCMALLOC'] = True
DEFINES['NTDDI_VERSION'] = '0x0A000003'
DEFINES['NTDDI_VERSION'] = 'NTDDI_WIN10_RS2'
#DEFINES['PSAPI_VERSION'] = '2'
#DEFINES['SAFE_BROWSING_CSD'] = True
#DEFINES['SAFE_BROWSING_DB_LOCAL'] = True
@ -53,7 +53,6 @@ LOCAL_INCLUDES += [
#CXXFLAGS += [
# '/bigobj',
# '/d2FastFail',
# '/D__DATE__=',
# '/D__TIME__=',
# '/D__TIMESTAMP__=',
@ -165,7 +164,6 @@ OS_LIBS += [
#LDFLAGS += [
# '/DEBUG',
# '/DYNAMICBASE',
# '/fastfail',
# '/FIXED:NO',
# '/ignore:4199',
# '/ignore:4221',

View File

@ -21,7 +21,7 @@ DEFINES['LIBANGLE_IMPLEMENTATION'] = True
DEFINES['LIBGLESV2_IMPLEMENTATION'] = True
DEFINES['NOMINMAX'] = True
#DEFINES['NO_TCMALLOC'] = True
DEFINES['NTDDI_VERSION'] = '0x0A000003'
DEFINES['NTDDI_VERSION'] = 'NTDDI_WIN10_RS2'
#DEFINES['PSAPI_VERSION'] = '2'
#DEFINES['SAFE_BROWSING_CSD'] = True
#DEFINES['SAFE_BROWSING_DB_LOCAL'] = True
@ -55,7 +55,6 @@ LOCAL_INCLUDES += [
#CXXFLAGS += [
# '/bigobj',
# '/d2FastFail',
# '/D__DATE__=',
# '/D__TIME__=',
# '/D__TIMESTAMP__=',
@ -173,7 +172,6 @@ OS_LIBS += [
#LDFLAGS += [
# '/DEBUG',
# '/DYNAMICBASE',
# '/fastfail',
# '/FIXED:NO',
# '/ignore:4199',
# '/ignore:4221',

View File

@ -10,7 +10,7 @@ DEFINES['DYNAMIC_ANNOTATIONS_ENABLED'] = '1'
#DEFINES['FULL_SAFE_BROWSING'] = True
DEFINES['NOMINMAX'] = True
#DEFINES['NO_TCMALLOC'] = True
DEFINES['NTDDI_VERSION'] = '0x0A000003'
DEFINES['NTDDI_VERSION'] = 'NTDDI_WIN10_RS2'
#DEFINES['PSAPI_VERSION'] = '2'
#DEFINES['SAFE_BROWSING_CSD'] = True
#DEFINES['SAFE_BROWSING_DB_LOCAL'] = True
@ -44,7 +44,6 @@ LOCAL_INCLUDES += [
#CXXFLAGS += [
# '/bigobj',
# '/d2FastFail',
# '/D__DATE__=',
# '/D__TIME__=',
# '/D__TIMESTAMP__=',

View File

@ -13,7 +13,7 @@ DEFINES['DYNAMIC_ANNOTATIONS_ENABLED'] = '1'
#DEFINES['FULL_SAFE_BROWSING'] = True
DEFINES['NOMINMAX'] = True
#DEFINES['NO_TCMALLOC'] = True
DEFINES['NTDDI_VERSION'] = '0x0A000003'
DEFINES['NTDDI_VERSION'] = 'NTDDI_WIN10_RS2'
#DEFINES['PSAPI_VERSION'] = '2'
#DEFINES['SAFE_BROWSING_CSD'] = True
#DEFINES['SAFE_BROWSING_DB_LOCAL'] = True
@ -47,7 +47,6 @@ LOCAL_INCLUDES += [
#CXXFLAGS += [
# '/bigobj',
# '/d2FastFail',
# '/D__DATE__=',
# '/D__TIME__=',
# '/D__TIMESTAMP__=',

View File

@ -2,6 +2,8 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
// clang-format off
#ifndef GLCONSTS_H_
#define GLCONSTS_H_
@ -7000,3 +7002,5 @@
#define LOCAL_WGL_VIDEO_OUT_STACKED_FIELDS_2_1 0x20CC
#endif // GLCONSTS_H_
// clang-format on

View File

@ -79,6 +79,7 @@ static const char* const sExtensionNames[] = {
"GL_ANGLE_framebuffer_blit",
"GL_ANGLE_framebuffer_multisample",
"GL_ANGLE_instanced_arrays",
"GL_ANGLE_multiview",
"GL_ANGLE_texture_compression_dxt3",
"GL_ANGLE_texture_compression_dxt5",
"GL_ANGLE_timer_query",
@ -204,7 +205,8 @@ static const char* const sExtensionNames[] = {
"GL_OES_texture_half_float",
"GL_OES_texture_half_float_linear",
"GL_OES_texture_npot",
"GL_OES_vertex_array_object"};
"GL_OES_vertex_array_object",
"GL_OVR_multiview2"};
static bool ShouldUseTLSIsCurrent(bool useTLSIsCurrent) {
if (gfxPrefs::UseTLSIsCurrent() == 0) return useTLSIsCurrent;
@ -1384,6 +1386,17 @@ void GLContext::LoadMoreSymbols(const SymbolLoader& loader) {
fnLoadForFeature(symbols, GLFeature::invalidate_framebuffer);
}
if (IsSupported(GLFeature::multiview)) {
const SymLoadStruct symbols[] = {
{ (PRFuncPtr*) &mSymbols.fFramebufferTextureMultiview, {{
"glFramebufferTextureMultiviewOVR",
"glFramebufferTextureMultiviewLayeredANGLE"
}} },
END_SYMBOLS
};
fnLoadForFeature(symbols, GLFeature::multiview);
}
if (IsSupported(GLFeature::prim_restart)) {
const SymLoadStruct symbols[] = {
{ (PRFuncPtr*) &mSymbols.fPrimitiveRestartIndex, {{ "glPrimitiveRestartIndex", "glPrimitiveRestartIndexNV" }} },

View File

@ -104,6 +104,7 @@ enum class GLFeature {
internalformat_query,
invalidate_framebuffer,
map_buffer_range,
multiview,
occlusion_query,
occlusion_query_boolean,
occlusion_query2,
@ -353,6 +354,7 @@ class GLContext : public GenericAtomicRefCounted,
ANGLE_framebuffer_blit,
ANGLE_framebuffer_multisample,
ANGLE_instanced_arrays,
ANGLE_multiview,
ANGLE_texture_compression_dxt3,
ANGLE_texture_compression_dxt5,
ANGLE_timer_query,
@ -479,6 +481,7 @@ class GLContext : public GenericAtomicRefCounted,
OES_texture_half_float_linear,
OES_texture_npot,
OES_vertex_array_object,
OVR_multiview2,
Extensions_Max,
Extensions_End
};
@ -3300,6 +3303,20 @@ class GLContext : public GenericAtomicRefCounted,
AFTER_GL_CALL;
}
// -----------------------------------------------------------------------------
// multiview
void fFramebufferTextureMultiview(GLenum target, GLenum attachment,
GLuint texture, GLint level,
GLint baseViewIndex,
GLsizei numViews) const {
BEFORE_GL_CALL;
ASSERT_SYMBOL_PRESENT(fFramebufferTextureMultiview);
mSymbols.fFramebufferTextureMultiview(target, attachment, texture, level,
baseViewIndex, numViews);
AFTER_GL_CALL;
}
#undef BEFORE_GL_CALL
#undef AFTER_GL_CALL
#undef ASSERT_SYMBOL_PRESENT

View File

@ -246,6 +246,12 @@ static const FeatureInfo sFeatureInfoArr[] = {
GLESVersion::ES3,
GLContext::ARB_map_buffer_range,
{GLContext::EXT_map_buffer_range, GLContext::Extensions_End}},
{"multiview",
GLVersion::NONE,
GLESVersion::NONE,
GLContext::Extension_None,
{GLContext::ANGLE_multiview, GLContext::OVR_multiview2,
GLContext::Extensions_End}},
{
"occlusion_query",
GLVersion::GL2,

View File

@ -445,6 +445,13 @@ struct GLContextSymbols final {
// NV_primitive_restart
void(GLAPIENTRY* fPrimitiveRestartIndex)(GLuint);
// OVR_multiview2
void(GLAPIENTRY* fFramebufferTextureMultiview)(GLenum target,
GLenum attachment,
GLuint texture, GLint level,
GLint baseViewIndex,
GLsizei numViews);
};
} // namespace gl

View File

@ -52,6 +52,8 @@ class GLConstHeader:
' * License, v. 2.0. If a copy of the MPL was not distributed with this',
' * file, You can obtain one at http://mozilla.org/MPL/2.0/. */',
'',
'// clang-format off',
'',
'#ifndef GLCONSTS_H_',
'#define GLCONSTS_H_',
'',
@ -62,7 +64,7 @@ class GLConstHeader:
' *',
' * To generate this file, see tutorial in \'GLParseRegistryXML.py\'.',
' */',
''
'',
])
def formatLibBegin(self, lib):
@ -89,7 +91,9 @@ class GLConstHeader:
def formatFileEnd(self):
self.write([
'',
'#endif // GLCONSTS_H_'
'#endif // GLCONSTS_H_',
'',
'// clang-format on',
])

View File

@ -122,7 +122,7 @@ struct ScopedFramebuffer : public ScopedGLWrapper<ScopedFramebuffer> {
public:
explicit ScopedFramebuffer(GLContext* aGL);
GLuint FB() { return mFB; }
const auto& FB() const { return mFB; }
protected:
void UnwrapImpl();