mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-08 19:04:45 +00:00
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:
parent
231ad45e42
commit
047e98938e
@ -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'
|
||||
|
@ -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,
|
||||
|
@ -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) {
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
// -
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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(
|
||||
|
@ -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:
|
||||
|
@ -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
|
||||
|
@ -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_
|
||||
|
@ -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();
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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; }
|
||||
|
@ -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.
|
||||
|
@ -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),
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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,
|
||||
|
@ -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]
|
||||
|
@ -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
|
||||
|
@ -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>
|
@ -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]],
|
||||
];
|
||||
|
||||
////////////////////
|
||||
|
@ -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]
|
||||
|
@ -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);
|
||||
};
|
||||
|
@ -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.
|
||||
|
@ -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"
|
||||
|
@ -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
|
||||
|
@ -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_
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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__=',
|
||||
|
@ -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__=',
|
||||
|
@ -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__=',
|
||||
|
@ -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__=',
|
||||
|
@ -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',
|
||||
|
@ -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',
|
||||
|
@ -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__=',
|
||||
|
@ -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__=',
|
||||
|
@ -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
|
||||
|
@ -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" }} },
|
||||
|
@ -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
|
||||
|
@ -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,
|
||||
|
@ -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
|
||||
|
@ -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',
|
||||
])
|
||||
|
||||
|
||||
|
@ -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();
|
||||
|
Loading…
Reference in New Issue
Block a user