diff --git a/dom/bindings/Bindings.conf b/dom/bindings/Bindings.conf index c749c7c4b2..a5113329db 100644 --- a/dom/bindings/Bindings.conf +++ b/dom/bindings/Bindings.conf @@ -1336,126 +1336,131 @@ DOMInterfaces = { 'headerFile': 'WebGLBuffer.h' }, -'WebGLExtensionCompressedTextureATC': { +'WEBGL_compressed_texture_atc': { 'nativeType': 'mozilla::WebGLExtensionCompressedTextureATC', 'headerFile': 'WebGLExtensions.h' }, -'WebGLExtensionCompressedTextureETC1': { +'WEBGL_compressed_texture_etc1': { 'nativeType': 'mozilla::WebGLExtensionCompressedTextureETC1', 'headerFile': 'WebGLExtensions.h' }, -'WebGLExtensionCompressedTexturePVRTC': { +'WEBGL_compressed_texture_pvrtc': { 'nativeType': 'mozilla::WebGLExtensionCompressedTexturePVRTC', 'headerFile': 'WebGLExtensions.h' }, -'WebGLExtensionCompressedTextureS3TC': { +'WEBGL_compressed_texture_s3tc': { 'nativeType': 'mozilla::WebGLExtensionCompressedTextureS3TC', 'headerFile': 'WebGLExtensions.h' }, -'WebGLExtensionDepthTexture': { +'WEBGL_depth_texture': { 'nativeType': 'mozilla::WebGLExtensionDepthTexture', 'headerFile': 'WebGLExtensions.h' }, -'WebGLExtensionDebugRendererInfo': { +'WEBGL_debug_renderer_info': { 'nativeType': 'mozilla::WebGLExtensionDebugRendererInfo', 'headerFile': 'WebGLExtensions.h' }, -'WebGLExtensionDebugShaders': { +'WEBGL_debug_shaders': { 'nativeType': 'mozilla::WebGLExtensionDebugShaders', 'headerFile': 'WebGLExtensions.h' }, -'WebGLExtensionElementIndexUint': { +'OES_element_index_uint': { 'nativeType': 'mozilla::WebGLExtensionElementIndexUint', 'headerFile': 'WebGLExtensions.h' }, -'WebGLExtensionFragDepth': { +'EXT_frag_depth': { 'nativeType': 'mozilla::WebGLExtensionFragDepth', 'headerFile': 'WebGLExtensions.h' }, -'WebGLExtensionLoseContext': { +'WEBGL_lose_context': { 'nativeType': 'mozilla::WebGLExtensionLoseContext', 'headerFile': 'WebGLExtensions.h' }, -'WebGLExtensionSRGB': { +'EXT_sRGB': { 'nativeType': 'mozilla::WebGLExtensionSRGB', 'headerFile': 'WebGLExtensions.h' }, -'WebGLExtensionStandardDerivatives': { +'OES_standard_derivatives': { 'nativeType': 'mozilla::WebGLExtensionStandardDerivatives', 'headerFile': 'WebGLExtensions.h' }, -'WebGLExtensionShaderTextureLod': { +'EXT_shader_texture_lod': { 'nativeType': 'mozilla::WebGLExtensionShaderTextureLod', 'headerFile': 'WebGLExtensions.h' }, -'WebGLExtensionTextureFilterAnisotropic': { +'EXT_texture_filter_anisotropic': { 'nativeType': 'mozilla::WebGLExtensionTextureFilterAnisotropic', 'headerFile': 'WebGLExtensions.h' }, -'WebGLExtensionTextureFloat': { +'OES_texture_float': { 'nativeType': 'mozilla::WebGLExtensionTextureFloat', 'headerFile': 'WebGLExtensions.h' }, -'WebGLExtensionTextureFloatLinear': { +'OES_texture_float_linear': { 'nativeType': 'mozilla::WebGLExtensionTextureFloatLinear', 'headerFile': 'WebGLExtensions.h' }, -'WebGLExtensionTextureHalfFloat': { +'OES_texture_half_float': { 'nativeType': 'mozilla::WebGLExtensionTextureHalfFloat', 'headerFile': 'WebGLExtensions.h' }, -'WebGLExtensionTextureHalfFloatLinear': { +'OES_texture_half_float_linear': { 'nativeType': 'mozilla::WebGLExtensionTextureHalfFloatLinear', 'headerFile': 'WebGLExtensions.h' }, -'WebGLExtensionColorBufferFloat': { +'WEBGL_color_buffer_float': { 'nativeType': 'mozilla::WebGLExtensionColorBufferFloat', 'headerFile': 'WebGLExtensions.h' }, -'WebGLExtensionColorBufferHalfFloat': { +'EXT_color_buffer_half_float': { 'nativeType': 'mozilla::WebGLExtensionColorBufferHalfFloat', 'headerFile': 'WebGLExtensions.h' }, -'WebGLExtensionDrawBuffers': { +'WEBGL_draw_buffers': { 'nativeType': 'mozilla::WebGLExtensionDrawBuffers', 'headerFile': 'WebGLExtensions.h' }, -'WebGLExtensionVertexArray': { +'OES_vertex_array_object': { 'nativeType': 'mozilla::WebGLExtensionVertexArray', 'headerFile': 'WebGLExtensions.h' }, -'WebGLExtensionInstancedArrays': { +'ANGLE_instanced_arrays': { 'nativeType': 'mozilla::WebGLExtensionInstancedArrays', 'headerFile': 'WebGLExtensions.h' }, -'WebGLExtensionBlendMinMax': { +'EXT_blend_minmax': { 'nativeType': 'mozilla::WebGLExtensionBlendMinMax', 'headerFile': 'WebGLExtensions.h' }, +'EXT_disjoint_timer_query': { + 'nativeType': 'mozilla::WebGLExtensionDisjointTimerQuery', + 'headerFile': 'WebGLExtensions.h' +}, + 'WebGLFramebuffer': { 'nativeType': 'mozilla::WebGLFramebuffer', 'headerFile': 'WebGLFramebuffer.h' @@ -1514,6 +1519,11 @@ DOMInterfaces = { 'headerFile': 'WebGLTexture.h' }, +'WebGLTimerQueryEXT': { + 'nativeType': 'mozilla::WebGLTimerQuery', + 'headerFile': 'WebGLTimerQuery.h' +}, + 'WebGLTransformFeedback': { 'nativeType': 'mozilla::WebGLTransformFeedback', 'headerFile': 'WebGLTransformFeedback.h' @@ -1524,7 +1534,7 @@ DOMInterfaces = { 'headerFile': 'WebGLUniformLocation.h' }, -'WebGLVertexArray': { +'WebGLVertexArrayObjectOES': { 'nativeType': 'mozilla::WebGLVertexArray', 'headerFile': 'WebGLVertexArray.h' }, diff --git a/dom/canvas/WebGL1Context.cpp b/dom/canvas/WebGL1Context.cpp index 5dec3638e4..2e65e8729d 100644 --- a/dom/canvas/WebGL1Context.cpp +++ b/dom/canvas/WebGL1Context.cpp @@ -31,6 +31,13 @@ WebGL1Context::WrapObject(JSContext* cx, JS::Handle aGivenProto) return dom::WebGLRenderingContextBinding::Wrap(cx, this, aGivenProto); } +bool +WebGL1Context::ValidateQueryTarget(GLenum target, const char* info) +{ + // TODO: Implement this for EXT_disjoint_timer + return false; +} + } // namespace mozilla nsresult diff --git a/dom/canvas/WebGL1Context.h b/dom/canvas/WebGL1Context.h index 32084c6ad2..a20845a6b6 100644 --- a/dom/canvas/WebGL1Context.h +++ b/dom/canvas/WebGL1Context.h @@ -34,6 +34,9 @@ private: virtual bool ValidateBufferTarget(GLenum target, const char* info) override; virtual bool ValidateBufferIndexedTarget(GLenum target, const char* info) override; virtual bool ValidateBufferForTarget(GLenum target, WebGLBuffer* buffer, const char* info) override; + virtual bool ValidateBufferUsageEnum(GLenum usage, const char* info) override; + virtual bool ValidateQueryTarget(GLenum target, const char* info) override; + virtual bool ValidateUniformMatrixTranspose(bool transpose, const char* info) override; }; } // namespace mozilla diff --git a/dom/canvas/WebGL1ContextBuffers.cpp b/dom/canvas/WebGL1ContextBuffers.cpp index 5f54ec6fd9..77fe5ff8ff 100644 --- a/dom/canvas/WebGL1ContextBuffers.cpp +++ b/dom/canvas/WebGL1ContextBuffers.cpp @@ -50,3 +50,19 @@ WebGL1Context::ValidateBufferForTarget(GLenum target, WebGLBuffer* buffer, return true; } + +bool +WebGL1Context::ValidateBufferUsageEnum(GLenum usage, const char* info) +{ + switch (usage) { + case LOCAL_GL_STREAM_DRAW: + case LOCAL_GL_STATIC_DRAW: + case LOCAL_GL_DYNAMIC_DRAW: + return true; + default: + break; + } + + ErrorInvalidEnumInfo(info, usage); + return false; +} diff --git a/dom/canvas/WebGL1ContextUniforms.cpp b/dom/canvas/WebGL1ContextUniforms.cpp index 41af49437c..371bc72596 100644 --- a/dom/canvas/WebGL1ContextUniforms.cpp +++ b/dom/canvas/WebGL1ContextUniforms.cpp @@ -5,7 +5,7 @@ #include "WebGL1Context.h" -using namespace mozilla; +namespace mozilla { bool WebGL1Context::ValidateAttribPointerType(bool /*integerMode*/, GLenum type, GLsizei* out_alignment, const char* info) @@ -33,3 +33,17 @@ WebGL1Context::ValidateAttribPointerType(bool /*integerMode*/, GLenum type, GLsi ErrorInvalidEnumInfo(info, type); return false; } + +bool +WebGL1Context::ValidateUniformMatrixTranspose(bool transpose, const char* info) +{ + if (transpose) { + ErrorInvalidValue("%s: transpose must be FALSE as per the " + "OpenGL ES 2.0 spec", info); + return false; + } + + return true; +} + +} // namespace mozilla diff --git a/dom/canvas/WebGL2Context.cpp b/dom/canvas/WebGL2Context.cpp index 38d171d176..cd89e0e213 100644 --- a/dom/canvas/WebGL2Context.cpp +++ b/dom/canvas/WebGL2Context.cpp @@ -88,7 +88,8 @@ static const gl::GLFeature kRequiredFeatures[] = { gl::GLFeature::query_objects, gl::GLFeature::renderbuffer_color_float, gl::GLFeature::renderbuffer_color_half_float, - gl::GLFeature::sRGB, + gl::GLFeature::sRGB_framebuffer, + gl::GLFeature::sRGB_texture, gl::GLFeature::sampler_objects, gl::GLFeature::standard_derivatives, gl::GLFeature::texture_3D, @@ -121,12 +122,30 @@ WebGLContext::InitWebGL2() return false; } + std::vector missingList; + for (size_t i = 0; i < ArrayLength(kRequiredFeatures); i++) { - if (!gl->IsSupported(kRequiredFeatures[i])) { - GenerateWarning("WebGL 2 unavailable. Requires feature %s.", - gl::GLContext::GetFeatureName(kRequiredFeatures[i])); - return false; + if (!gl->IsSupported(kRequiredFeatures[i])) + missingList.push_back(kRequiredFeatures[i]); + } + +#ifdef XP_MACOSX + // On OSX, GL core profile is used. This requires texture swizzle + // support to emulate legacy texture formats: ALPHA, LUMINANCE, + // and LUMINANCE_ALPHA. + if (!gl->IsSupported(gl::GLFeature::texture_swizzle)) + missingList.push_back(gl::GLFeature::texture_swizzle); +#endif + + if (missingList.size()) { + nsAutoCString exts; + for (auto itr = missingList.begin(); itr != missingList.end(); ++itr) { + exts.AppendLiteral("\n "); + exts.Append(gl::GLContext::GetFeatureName(*itr)); } + GenerateWarning("WebGL 2 unavailable. The following required features are" + " unavailible: %s", exts.BeginReading()); + return false; } // ok WebGL 2 is compatible, we can enable natively supported extensions. diff --git a/dom/canvas/WebGL2Context.h b/dom/canvas/WebGL2Context.h index 997ee006bd..953cb55fab 100644 --- a/dom/canvas/WebGL2Context.h +++ b/dom/canvas/WebGL2Context.h @@ -111,26 +111,112 @@ public: // Uniforms and attributes - WebGL2ContextUniforms.cpp void VertexAttribIPointer(GLuint index, GLint size, GLenum type, GLsizei stride, GLintptr offset); + // GL 3.0 & ES 3.0 void Uniform1ui(WebGLUniformLocation* location, GLuint v0); void Uniform2ui(WebGLUniformLocation* location, GLuint v0, GLuint v1); void Uniform3ui(WebGLUniformLocation* location, GLuint v0, GLuint v1, GLuint v2); void Uniform4ui(WebGLUniformLocation* location, GLuint v0, GLuint v1, GLuint v2, GLuint v3); - void Uniform1uiv(WebGLUniformLocation* location, const dom::Sequence& value); - void Uniform2uiv(WebGLUniformLocation* location, const dom::Sequence& value); - void Uniform3uiv(WebGLUniformLocation* location, const dom::Sequence& value); - void Uniform4uiv(WebGLUniformLocation* location, const dom::Sequence& value); - void UniformMatrix2x3fv(WebGLUniformLocation* location, bool transpose, const dom::Float32Array& value); - void UniformMatrix2x3fv(WebGLUniformLocation* location, bool transpose, const dom::Sequence& value); - void UniformMatrix3x2fv(WebGLUniformLocation* location, bool transpose, const dom::Float32Array& value); - void UniformMatrix3x2fv(WebGLUniformLocation* location, bool transpose, const dom::Sequence& value); - void UniformMatrix2x4fv(WebGLUniformLocation* location, bool transpose, const dom::Float32Array& value); - void UniformMatrix2x4fv(WebGLUniformLocation* location, bool transpose, const dom::Sequence& value); - void UniformMatrix4x2fv(WebGLUniformLocation* location, bool transpose, const dom::Float32Array& value); - void UniformMatrix4x2fv(WebGLUniformLocation* location, bool transpose, const dom::Sequence& value); - void UniformMatrix3x4fv(WebGLUniformLocation* location, bool transpose, const dom::Float32Array& value); - void UniformMatrix3x4fv(WebGLUniformLocation* location, bool transpose, const dom::Sequence& value); - void UniformMatrix4x3fv(WebGLUniformLocation* location, bool transpose, const dom::Float32Array& value); - void UniformMatrix4x3fv(WebGLUniformLocation* location, bool transpose, const dom::Sequence& value); + +private: + void Uniform1uiv_base(WebGLUniformLocation* loc, size_t arrayLength, const GLuint* data); + void Uniform2uiv_base(WebGLUniformLocation* loc, size_t arrayLength, const GLuint* data); + void Uniform3uiv_base(WebGLUniformLocation* loc, size_t arrayLength, const GLuint* data); + void Uniform4uiv_base(WebGLUniformLocation* loc, size_t arrayLength, const GLuint* data); + +public: + void Uniform1uiv(WebGLUniformLocation* loc, const dom::Sequence& arr) { + Uniform1uiv_base(loc, arr.Length(), arr.Elements()); + } + void Uniform2uiv(WebGLUniformLocation* loc, const dom::Sequence& arr) { + Uniform2uiv_base(loc, arr.Length(), arr.Elements()); + } + void Uniform3uiv(WebGLUniformLocation* loc, const dom::Sequence& arr) { + Uniform3uiv_base(loc, arr.Length(), arr.Elements()); + } + void Uniform4uiv(WebGLUniformLocation* loc, const dom::Sequence& arr) { + Uniform4uiv_base(loc, arr.Length(), arr.Elements()); + } + void Uniform1uiv(WebGLUniformLocation* loc, const dom::Uint32Array& arr) { + arr.ComputeLengthAndData(); + Uniform1uiv_base(loc, arr.Length(), arr.Data()); + } + void Uniform2uiv(WebGLUniformLocation* loc, const dom::Uint32Array& arr) { + arr.ComputeLengthAndData(); + Uniform2uiv_base(loc, arr.Length(), arr.Data()); + } + void Uniform3uiv(WebGLUniformLocation* loc, const dom::Uint32Array& arr) { + arr.ComputeLengthAndData(); + Uniform3uiv_base(loc, arr.Length(), arr.Data()); + } + void Uniform4uiv(WebGLUniformLocation* loc, const dom::Uint32Array& arr) { + arr.ComputeLengthAndData(); + Uniform4uiv_base(loc, arr.Length(), arr.Data()); + } + +private: + void UniformMatrix2x3fv_base(WebGLUniformLocation* loc, bool transpose, + size_t arrayLength, const GLfloat* data); + void UniformMatrix3x2fv_base(WebGLUniformLocation* loc, bool transpose, + size_t arrayLength, const GLfloat* data); + void UniformMatrix2x4fv_base(WebGLUniformLocation* loc, bool transpose, + size_t arrayLength, const GLfloat* data); + void UniformMatrix4x2fv_base(WebGLUniformLocation* loc, bool transpose, + size_t arrayLength, const GLfloat* data); + void UniformMatrix3x4fv_base(WebGLUniformLocation* loc, bool transpose, + size_t arrayLength, const GLfloat* data); + void UniformMatrix4x3fv_base(WebGLUniformLocation* loc, bool transpose, + size_t arrayLength, const GLfloat* data); + +public: + // GL 2.1 & ES 3.0 + void UniformMatrix2x3fv(WebGLUniformLocation* loc, bool transpose, const dom::Sequence& value){ + UniformMatrix2x3fv_base(loc, transpose, value.Length(), value.Elements()); + } + void UniformMatrix2x4fv(WebGLUniformLocation* loc, bool transpose, const dom::Sequence& value){ + UniformMatrix2x4fv_base(loc, transpose, value.Length(), value.Elements()); + } + void UniformMatrix3x2fv(WebGLUniformLocation* loc, bool transpose, const dom::Sequence& value){ + UniformMatrix3x2fv_base(loc, transpose, value.Length(), value.Elements()); + } + void UniformMatrix3x4fv(WebGLUniformLocation* loc, bool transpose, const dom::Sequence& value){ + UniformMatrix3x4fv_base(loc, transpose, value.Length(), value.Elements()); + } + void UniformMatrix4x2fv(WebGLUniformLocation* loc, bool transpose, const dom::Sequence& value){ + UniformMatrix4x2fv_base(loc, transpose, value.Length(), value.Elements()); + } + void UniformMatrix4x3fv(WebGLUniformLocation* loc, bool transpose, const dom::Sequence& value){ + UniformMatrix4x3fv_base(loc, transpose, value.Length(), value.Elements()); + } + + void UniformMatrix2x3fv(WebGLUniformLocation* loc, bool transpose, const dom::Float32Array& value){ + value.ComputeLengthAndData(); + UniformMatrix2x3fv_base(loc, transpose, value.Length(), value.Data()); + } + + void UniformMatrix2x4fv(WebGLUniformLocation* loc, bool transpose, const dom::Float32Array& value){ + value.ComputeLengthAndData(); + UniformMatrix2x4fv_base(loc, transpose, value.Length(), value.Data()); + } + + void UniformMatrix3x2fv(WebGLUniformLocation* loc, bool transpose, const dom::Float32Array& value){ + value.ComputeLengthAndData(); + UniformMatrix3x2fv_base(loc, transpose, value.Length(), value.Data()); + } + + void UniformMatrix3x4fv(WebGLUniformLocation* loc, bool transpose, const dom::Float32Array& value){ + value.ComputeLengthAndData(); + UniformMatrix3x4fv_base(loc, transpose, value.Length(), value.Data()); + } + + void UniformMatrix4x2fv(WebGLUniformLocation* loc, bool transpose, const dom::Float32Array& value){ + value.ComputeLengthAndData(); + UniformMatrix4x2fv_base(loc, transpose, value.Length(), value.Data()); + } + + void UniformMatrix4x3fv(WebGLUniformLocation* loc, bool transpose, const dom::Float32Array& value){ + value.ComputeLengthAndData(); + UniformMatrix4x3fv_base(loc, transpose, value.Length(), value.Data()); + } private: void VertexAttribI4iv(GLuint index, size_t length, const GLint* v); @@ -238,6 +324,7 @@ public: void BindBufferBase(GLenum target, GLuint index, WebGLBuffer* buffer); void BindBufferRange(GLenum target, GLuint index, WebGLBuffer* buffer, GLintptr offset, GLsizeiptr size); */ + virtual JS::Value GetParameter(JSContext* cx, GLenum pname, ErrorResult& rv) override; void GetIndexedParameter(GLenum target, GLuint index, dom::Nullable& retval); void GetUniformIndices(WebGLProgram* program, @@ -272,6 +359,8 @@ private: JS::Value GetTexParameterInternal(const TexTarget& target, GLenum pname) override; + void UpdateBoundQuery(GLenum target, WebGLQuery* query); + bool ValidateSizedInternalFormat(GLenum internalFormat, const char* info); bool ValidateTexStorage(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, @@ -283,6 +372,9 @@ private: virtual bool ValidateBufferTarget(GLenum target, const char* info) override; virtual bool ValidateBufferIndexedTarget(GLenum target, const char* info) override; virtual bool ValidateBufferForTarget(GLenum target, WebGLBuffer* buffer, const char* info) override; + virtual bool ValidateBufferUsageEnum(GLenum usage, const char* info) override; + virtual bool ValidateQueryTarget(GLenum target, const char* info) override; + virtual bool ValidateUniformMatrixTranspose(bool transpose, const char* info) override; }; } // namespace mozilla diff --git a/dom/canvas/WebGL2ContextBuffers.cpp b/dom/canvas/WebGL2ContextBuffers.cpp index 9fe6b41617..56e50cfda4 100644 --- a/dom/canvas/WebGL2ContextBuffers.cpp +++ b/dom/canvas/WebGL2ContextBuffers.cpp @@ -75,6 +75,28 @@ WebGL2Context::ValidateBufferForTarget(GLenum target, WebGLBuffer* buffer, return false; } +bool +WebGL2Context::ValidateBufferUsageEnum(GLenum usage, const char* info) +{ + switch (usage) { + case LOCAL_GL_DYNAMIC_COPY: + case LOCAL_GL_DYNAMIC_DRAW: + case LOCAL_GL_DYNAMIC_READ: + case LOCAL_GL_STATIC_COPY: + case LOCAL_GL_STATIC_DRAW: + case LOCAL_GL_STATIC_READ: + case LOCAL_GL_STREAM_COPY: + case LOCAL_GL_STREAM_DRAW: + case LOCAL_GL_STREAM_READ: + return true; + default: + break; + } + + ErrorInvalidEnumInfo(info, usage); + return false; +} + // ------------------------------------------------------------------------- // Buffer objects diff --git a/dom/canvas/WebGL2ContextQueries.cpp b/dom/canvas/WebGL2ContextQueries.cpp index 8a5660e3cd..91d83bfa8f 100644 --- a/dom/canvas/WebGL2ContextQueries.cpp +++ b/dom/canvas/WebGL2ContextQueries.cpp @@ -7,8 +7,7 @@ #include "GLContext.h" #include "WebGLQuery.h" -using namespace mozilla; -using namespace mozilla::dom; +namespace mozilla { /* * We fake ANY_SAMPLES_PASSED and ANY_SAMPLES_PASSED_CONSERVATIVE with @@ -26,14 +25,14 @@ GetQueryTargetEnumString(GLenum target) { switch (target) { - case LOCAL_GL_ANY_SAMPLES_PASSED: - return "ANY_SAMPLES_PASSED"; - case LOCAL_GL_ANY_SAMPLES_PASSED_CONSERVATIVE: - return "ANY_SAMPLES_PASSED_CONSERVATIVE"; - case LOCAL_GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN: - return "TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN"; - default: - break; + case LOCAL_GL_ANY_SAMPLES_PASSED: + return "ANY_SAMPLES_PASSED"; + case LOCAL_GL_ANY_SAMPLES_PASSED_CONSERVATIVE: + return "ANY_SAMPLES_PASSED_CONSERVATIVE"; + case LOCAL_GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN: + return "TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN"; + default: + break; } MOZ_ASSERT(false, "Unknown query `target`."); @@ -56,19 +55,23 @@ SimulateOcclusionQueryTarget(const gl::GLContext* gl, GLenum target) return LOCAL_GL_SAMPLES_PASSED; } -WebGLRefPtr* -WebGLContext::GetQueryTargetSlot(GLenum target) +WebGLRefPtr& +WebGLContext::GetQuerySlotByTarget(GLenum target) { + /* This function assumes that target has been validated for either + * WebGL1 or WebGL2. + */ switch (target) { - case LOCAL_GL_ANY_SAMPLES_PASSED: - case LOCAL_GL_ANY_SAMPLES_PASSED_CONSERVATIVE: - return &mActiveOcclusionQuery; + case LOCAL_GL_ANY_SAMPLES_PASSED: + case LOCAL_GL_ANY_SAMPLES_PASSED_CONSERVATIVE: + return mActiveOcclusionQuery; - case LOCAL_GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN: - return &mActiveTransformFeedbackQuery; + case LOCAL_GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN: + return mActiveTransformFeedbackQuery; + + default: + MOZ_CRASH("Should not get here."); } - - return nullptr; } @@ -152,11 +155,8 @@ WebGL2Context::BeginQuery(GLenum target, WebGLQuery* query) if (IsContextLost()) return; - WebGLRefPtr* targetSlot = GetQueryTargetSlot(target); - if (!targetSlot) { - ErrorInvalidEnum("beginQuery: unknown query target"); + if (!ValidateQueryTarget(target, "beginQuery")) return; - } if (!query) { /* From GLES's EXT_occlusion_query_boolean: @@ -193,10 +193,10 @@ WebGL2Context::BeginQuery(GLenum target, WebGLQuery* query) return; } - if (*targetSlot) { - ErrorInvalidOperation("beginQuery: An other query already active."); - return; - } + WebGLRefPtr& querySlot = GetQuerySlotByTarget(target); + WebGLQuery* activeQuery = querySlot.get(); + if (activeQuery) + return ErrorInvalidOperation("beginQuery: An other query already active."); if (!query->HasEverBeenActive()) query->mType = target; @@ -211,7 +211,7 @@ WebGL2Context::BeginQuery(GLenum target, WebGLQuery* query) query->mGLName); } - *targetSlot = query; + UpdateBoundQuery(target, query); } void @@ -220,14 +220,13 @@ WebGL2Context::EndQuery(GLenum target) if (IsContextLost()) return; - WebGLRefPtr* targetSlot = GetQueryTargetSlot(target); - if (!targetSlot) { - ErrorInvalidEnum("endQuery: unknown query target"); + if (!ValidateQueryTarget(target, "endQuery")) return; - } - if (!*targetSlot || - target != (*targetSlot)->mType) + WebGLRefPtr& querySlot = GetQuerySlotByTarget(target); + WebGLQuery* activeQuery = querySlot.get(); + + if (!activeQuery || target != activeQuery->mType) { /* From GLES's EXT_occlusion_query_boolean: * marks the end of the sequence of commands to be tracked for the @@ -255,7 +254,7 @@ WebGL2Context::EndQuery(GLenum target) gl->fEndQuery(SimulateOcclusionQueryTarget(gl, target)); } - *targetSlot = nullptr; + UpdateBoundQuery(target, nullptr); } already_AddRefed @@ -264,11 +263,8 @@ WebGL2Context::GetQuery(GLenum target, GLenum pname) if (IsContextLost()) return nullptr; - WebGLRefPtr* targetSlot = GetQueryTargetSlot(target); - if (!targetSlot) { - ErrorInvalidEnum("getQuery: unknown query target"); + if (!ValidateQueryTarget(target, "getQuery")) return nullptr; - } if (pname != LOCAL_GL_CURRENT_QUERY) { /* OpenGL ES 3.0 spec 6.1.7: @@ -278,7 +274,9 @@ WebGL2Context::GetQuery(GLenum target, GLenum pname) return nullptr; } - nsRefPtr tmp = targetSlot->get(); + WebGLRefPtr& targetSlot = GetQuerySlotByTarget(target); + + nsRefPtr tmp = targetSlot.get(); return tmp.forget(); } @@ -353,3 +351,27 @@ WebGL2Context::GetQueryParameter(JSContext*, WebGLQuery* query, GLenum pname, ErrorInvalidEnum("getQueryObject: `pname` must be QUERY_RESULT{_AVAILABLE}."); } + +void +WebGL2Context::UpdateBoundQuery(GLenum target, WebGLQuery* query) +{ + WebGLRefPtr& querySlot = GetQuerySlotByTarget(target); + querySlot = query; +} + +bool +WebGL2Context::ValidateQueryTarget(GLenum target, const char* info) +{ + switch (target) { + case LOCAL_GL_ANY_SAMPLES_PASSED: + case LOCAL_GL_ANY_SAMPLES_PASSED_CONSERVATIVE: + case LOCAL_GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN: + return true; + + default: + ErrorInvalidEnumInfo(info, target); + return false; + } +} + +} // namespace mozilla diff --git a/dom/canvas/WebGL2ContextSamplers.cpp b/dom/canvas/WebGL2ContextSamplers.cpp index bad4b50bdb..3e2b31ebd3 100644 --- a/dom/canvas/WebGL2ContextSamplers.cpp +++ b/dom/canvas/WebGL2ContextSamplers.cpp @@ -36,6 +36,12 @@ WebGL2Context::DeleteSampler(WebGLSampler* sampler) if (!sampler || sampler->IsDeleted()) return; + for (int n = 0; n < mGLMaxTextureUnits; n++) { + if (mBoundSamplers[n] == sampler) { + mBoundSamplers[n] = nullptr; + } + } + sampler->RequestDelete(); } @@ -74,6 +80,8 @@ WebGL2Context::BindSampler(GLuint unit, WebGLSampler* sampler) return ErrorInvalidOperation("bindSampler: binding deleted sampler"); WebGLContextUnchecked::BindSampler(unit, sampler); + + mBoundSamplers[unit] = sampler; } void diff --git a/dom/canvas/WebGL2ContextState.cpp b/dom/canvas/WebGL2ContextState.cpp new file mode 100644 index 0000000000..09a842730b --- /dev/null +++ b/dom/canvas/WebGL2ContextState.cpp @@ -0,0 +1,177 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * 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/. */ + +#include "WebGL2Context.h" +#include "WebGLContextUtils.h" + +namespace mozilla { + +JS::Value +WebGL2Context::GetParameter(JSContext* cx, GLenum pname, ErrorResult& rv) +{ + // The following cases are handled in WebGLContext::GetParameter(): + // case LOCAL_GL_MAX_COLOR_ATTACHMENTS: + // case LOCAL_GL_MAX_DRAW_BUFFERS: + // case LOCAL_GL_DRAW_BUFFERi: + + if (IsContextLost()) + return JS::NullValue(); + + MakeContextCurrent(); + + switch (pname) { + /* GLboolean */ + case LOCAL_GL_RASTERIZER_DISCARD: + case LOCAL_GL_SAMPLE_ALPHA_TO_COVERAGE: + case LOCAL_GL_SAMPLE_COVERAGE: + case LOCAL_GL_TRANSFORM_FEEDBACK_PAUSED: + case LOCAL_GL_TRANSFORM_FEEDBACK_ACTIVE: + case LOCAL_GL_UNPACK_SKIP_IMAGES: + case LOCAL_GL_UNPACK_SKIP_PIXELS: + case LOCAL_GL_UNPACK_SKIP_ROWS: { + realGLboolean b = 0; + gl->fGetBooleanv(pname, &b); + return JS::BooleanValue(bool(b)); + } + + /* GLenum */ + case LOCAL_GL_READ_BUFFER: { + if (mBoundReadFramebuffer) { + GLint val = LOCAL_GL_NONE; + gl->fGetIntegerv(pname, &val); + return JS::Int32Value(val); + } + + return JS::Int32Value(LOCAL_GL_BACK); + } + + case LOCAL_GL_FRAGMENT_SHADER_DERIVATIVE_HINT: + /* fall through */ + + /* GLint */ + case LOCAL_GL_MAX_3D_TEXTURE_SIZE: + case LOCAL_GL_MAX_ARRAY_TEXTURE_LAYERS: + case LOCAL_GL_MAX_COMBINED_UNIFORM_BLOCKS: + case LOCAL_GL_MAX_ELEMENTS_INDICES: + case LOCAL_GL_MAX_ELEMENTS_VERTICES: + case LOCAL_GL_MAX_FRAGMENT_INPUT_COMPONENTS: + case LOCAL_GL_MAX_FRAGMENT_UNIFORM_BLOCKS: + case LOCAL_GL_MAX_FRAGMENT_UNIFORM_COMPONENTS: + case LOCAL_GL_MAX_PROGRAM_TEXEL_OFFSET: + case LOCAL_GL_MAX_SAMPLES: + case LOCAL_GL_MAX_TEXTURE_LOD_BIAS: + case LOCAL_GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS: + case LOCAL_GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS: + case LOCAL_GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS: + case LOCAL_GL_MAX_UNIFORM_BUFFER_BINDINGS: + case LOCAL_GL_MAX_VERTEX_OUTPUT_COMPONENTS: + case LOCAL_GL_MAX_VERTEX_UNIFORM_BLOCKS: + case LOCAL_GL_MAX_VERTEX_UNIFORM_COMPONENTS: + case LOCAL_GL_MIN_PROGRAM_TEXEL_OFFSET: + case LOCAL_GL_PACK_ROW_LENGTH: + case LOCAL_GL_PACK_SKIP_PIXELS: + case LOCAL_GL_PACK_SKIP_ROWS: + case LOCAL_GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT: + case LOCAL_GL_UNPACK_IMAGE_HEIGHT: + case LOCAL_GL_UNPACK_ROW_LENGTH: { + GLint val; + gl->fGetIntegerv(pname, &val); + return JS::Int32Value(val); + } + + case LOCAL_GL_MAX_VARYING_COMPONENTS: { + // On OS X Core Profile this is buggy. The spec says that the + // value is 4 * GL_MAX_VARYING_VECTORS + GLint val; + gl->fGetIntegerv(LOCAL_GL_MAX_VARYING_VECTORS, &val); + return JS::Int32Value(4*val); + } + + /* GLint64 */ + case LOCAL_GL_MAX_CLIENT_WAIT_TIMEOUT_WEBGL: + return JS::NumberValue(0); // TODO + + case LOCAL_GL_MAX_ELEMENT_INDEX: + // GL_MAX_ELEMENT_INDEX becomes available in GL 4.3 or via ES3 + // compatibility + if (!gl->IsSupported(gl::GLFeature::ES3_compatibility)) + return JS::NumberValue(0); + + /*** fall through to fGetInteger64v ***/ + + case LOCAL_GL_MAX_COMBINED_FRAGMENT_UNIFORM_COMPONENTS: + case LOCAL_GL_MAX_COMBINED_VERTEX_UNIFORM_COMPONENTS: + case LOCAL_GL_MAX_UNIFORM_BLOCK_SIZE: { + GLint64 val; + gl->fGetInteger64v(pname, &val); + return JS::DoubleValue(static_cast(val)); + } + + + /* GLuint64 */ + case LOCAL_GL_MAX_SERVER_WAIT_TIMEOUT: { + GLuint64 val; + gl->fGetInteger64v(pname, (GLint64*) &val); + return JS::DoubleValue(static_cast(val)); + } + + case LOCAL_GL_COPY_READ_BUFFER_BINDING: + return WebGLObjectAsJSValue(cx, mBoundCopyReadBuffer.get(), rv); + + case LOCAL_GL_COPY_WRITE_BUFFER_BINDING: + return WebGLObjectAsJSValue(cx, mBoundCopyWriteBuffer.get(), rv); + + case LOCAL_GL_PIXEL_PACK_BUFFER_BINDING: + return WebGLObjectAsJSValue(cx, mBoundPixelPackBuffer.get(), rv); + + case LOCAL_GL_PIXEL_UNPACK_BUFFER_BINDING: + return WebGLObjectAsJSValue(cx, mBoundPixelUnpackBuffer.get(), rv); + + case LOCAL_GL_TRANSFORM_FEEDBACK_BUFFER_BINDING: + return WebGLObjectAsJSValue(cx, mBoundTransformFeedbackBuffer.get(), rv); + + case LOCAL_GL_UNIFORM_BUFFER_BINDING: + return WebGLObjectAsJSValue(cx, mBoundUniformBuffer.get(), rv); + + // DRAW_FRAMEBUFFER_BINDING is the same as FRAMEBUFFER_BINDING. + case LOCAL_GL_READ_FRAMEBUFFER_BINDING: + return WebGLObjectAsJSValue(cx, mBoundReadFramebuffer.get(), rv); + + case LOCAL_GL_SAMPLER_BINDING: + return WebGLObjectAsJSValue(cx, mBoundSamplers[mActiveTexture].get(), rv); + + case LOCAL_GL_TEXTURE_BINDING_2D_ARRAY: + // TODO: Implement gl.TEXTURE_2D_ARRAY + // return WebGLObjectAsJSValue(cx, mBound2DTextureArrays[mActiveTexture].get(), rv); + return JS::NullValue(); + + case LOCAL_GL_TEXTURE_BINDING_3D: + return WebGLObjectAsJSValue(cx, mBound3DTextures[mActiveTexture].get(), rv); + + case LOCAL_GL_TRANSFORM_FEEDBACK_BINDING: { + WebGLTransformFeedback* tf = + (mBoundTransformFeedback != mDefaultTransformFeedback) ? mBoundTransformFeedback.get() : nullptr; + return WebGLObjectAsJSValue(cx, tf, rv); + } + + case LOCAL_GL_VERTEX_ARRAY_BINDING: { + WebGLVertexArray* vao = + (mBoundVertexArray != mDefaultVertexArray) ? mBoundVertexArray.get() : nullptr; + return WebGLObjectAsJSValue(cx, vao, rv); + } + + case LOCAL_GL_VERSION: + return StringValue(cx, "WebGL 2.0", rv); + + case LOCAL_GL_SHADING_LANGUAGE_VERSION: + return StringValue(cx, "WebGL GLSL ES 3.00", rv); + + default: + return WebGLContext::GetParameter(cx, pname, rv); + } +} + +} // namespace mozilla diff --git a/dom/canvas/WebGL2ContextSync.cpp b/dom/canvas/WebGL2ContextSync.cpp index 5e19dcf7f5..960dc67b7c 100644 --- a/dom/canvas/WebGL2ContextSync.cpp +++ b/dom/canvas/WebGL2ContextSync.cpp @@ -4,7 +4,9 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "WebGL2Context.h" + #include "GLContext.h" +#include "WebGLSync.h" using namespace mozilla; using namespace mozilla::dom; @@ -15,38 +17,117 @@ using namespace mozilla::dom; already_AddRefed WebGL2Context::FenceSync(GLenum condition, GLbitfield flags) { - MOZ_CRASH("Not Implemented."); - return nullptr; + if (IsContextLost()) + return nullptr; + + if (condition != LOCAL_GL_SYNC_GPU_COMMANDS_COMPLETE) { + ErrorInvalidEnum("fenceSync: condition must be SYNC_GPU_COMMANDS_COMPLETE"); + return nullptr; + } + + if (flags != 0) { + ErrorInvalidValue("fenceSync: flags must be 0"); + return nullptr; + } + + MakeContextCurrent(); + nsRefPtr globj = new WebGLSync(this, condition, flags); + return globj.forget(); } bool WebGL2Context::IsSync(WebGLSync* sync) { - MOZ_CRASH("Not Implemented."); - return false; + if (IsContextLost()) + return false; + + return ValidateObjectAllowDeleted("isSync", sync) && !sync->IsDeleted(); } void WebGL2Context::DeleteSync(WebGLSync* sync) { - MOZ_CRASH("Not Implemented."); + if (IsContextLost()) + return; + + if (!ValidateObjectAllowDeletedOrNull("deleteSync", sync)) + return; + + if (!sync || sync->IsDeleted()) + return; + + sync->RequestDelete(); } GLenum WebGL2Context::ClientWaitSync(WebGLSync* sync, GLbitfield flags, GLuint64 timeout) { - MOZ_CRASH("Not Implemented."); - return LOCAL_GL_FALSE; + if (IsContextLost()) + return LOCAL_GL_WAIT_FAILED; + + if (!sync || sync->IsDeleted()) { + ErrorInvalidValue("clientWaitSync: sync is not a sync object."); + return LOCAL_GL_WAIT_FAILED; + } + + if (flags != 0 && flags != LOCAL_GL_SYNC_FLUSH_COMMANDS_BIT) { + ErrorInvalidValue("clientWaitSync: flag must be SYNC_FLUSH_COMMANDS_BIT or 0"); + return LOCAL_GL_WAIT_FAILED; + } + + MakeContextCurrent(); + return gl->fClientWaitSync(sync->mGLName, flags, timeout); } void WebGL2Context::WaitSync(WebGLSync* sync, GLbitfield flags, GLuint64 timeout) { - MOZ_CRASH("Not Implemented."); + if (IsContextLost()) + return; + + if (!sync || sync->IsDeleted()) { + ErrorInvalidValue("waitSync: sync is not a sync object."); + return; + } + + if (flags != 0) { + ErrorInvalidValue("waitSync: flags must be 0"); + return; + } + + if (timeout != LOCAL_GL_TIMEOUT_IGNORED) { + ErrorInvalidValue("waitSync: timeout must be TIMEOUT_IGNORED"); + return; + } + + MakeContextCurrent(); + gl->fWaitSync(sync->mGLName, flags, timeout); } void WebGL2Context::GetSyncParameter(JSContext*, WebGLSync* sync, GLenum pname, JS::MutableHandleValue retval) { - MOZ_CRASH("Not Implemented."); + if (IsContextLost()) + return; + + if (!sync || sync->IsDeleted()) { + ErrorInvalidValue("getSyncParameter: sync is not a sync object."); + return; + } + + retval.set(JS::NullValue()); + + GLint result = 0; + switch (pname) { + case LOCAL_GL_OBJECT_TYPE: + case LOCAL_GL_SYNC_STATUS: + case LOCAL_GL_SYNC_CONDITION: + case LOCAL_GL_SYNC_FLAGS: + MakeContextCurrent(); + gl->fGetSynciv(sync->mGLName, pname, 1, nullptr, &result); + retval.set(JS::Int32Value(result)); + break; + } + + ErrorInvalidEnum("getSyncParameter: Invalid pname 0x%04x", pname); } diff --git a/dom/canvas/WebGL2ContextTransformFeedback.cpp b/dom/canvas/WebGL2ContextTransformFeedback.cpp index 9dd96f9464..a1db81b78c 100644 --- a/dom/canvas/WebGL2ContextTransformFeedback.cpp +++ b/dom/canvas/WebGL2ContextTransformFeedback.cpp @@ -202,18 +202,7 @@ WebGL2Context::TransformFeedbackVaryings(WebGLProgram* program, if (!ValidateObject("transformFeedbackVaryings: program", program)) return; - GLsizei count = varyings.Length(); - GLchar** tmpVaryings = (GLchar**) moz_xmalloc(count * sizeof(GLchar*)); - - for (GLsizei n = 0; n < count; n++) { - tmpVaryings[n] = (GLchar*) ToNewCString(varyings[n]); - } - - GLuint progname = program->mGLName; - MakeContextCurrent(); - gl->fTransformFeedbackVaryings(progname, count, tmpVaryings, bufferMode); - - NS_FREE_XPCOM_ALLOCATED_POINTER_ARRAY(count, tmpVaryings); + program->TransformFeedbackVaryings(varyings, bufferMode); } already_AddRefed @@ -225,29 +214,5 @@ WebGL2Context::GetTransformFeedbackVarying(WebGLProgram* program, GLuint index) if (!ValidateObject("getTransformFeedbackVarying: program", program)) return nullptr; - MakeContextCurrent(); - - GLint len = 0; - GLuint progname = program->mGLName; - gl->fGetProgramiv(progname, LOCAL_GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH, &len); - if (!len) - return nullptr; - - UniquePtr name(new char[len]); - GLint tfsize = 0; - GLuint tftype = 0; - - gl->fGetTransformFeedbackVarying(progname, index, len, &len, &tfsize, &tftype, name.get()); - if (len == 0 || tfsize == 0 || tftype == 0) - return nullptr; - - MOZ_CRASH("todo"); - /* - // Reverse lookup of name - nsCString reverseMappedName; - prog->ReverveMapIdentifier(nsDependentCString(name), &reverseMappedName); - - nsRefPtr result = new WebGLActiveInfo(tfsize, tftype, nsDependentCString(name.get())); - return result.forget(); - */ + return program->GetTransformFeedbackVarying(index); } diff --git a/dom/canvas/WebGL2ContextUniforms.cpp b/dom/canvas/WebGL2ContextUniforms.cpp index 549285a222..7d35684354 100644 --- a/dom/canvas/WebGL2ContextUniforms.cpp +++ b/dom/canvas/WebGL2ContextUniforms.cpp @@ -11,8 +11,7 @@ #include "WebGLVertexAttribData.h" #include "mozilla/dom/WebGL2RenderingContextBinding.h" -using namespace mozilla; -using namespace mozilla::dom; +namespace mozilla { typedef union { GLint i; GLfloat f; GLuint u; } fi_t; @@ -74,6 +73,12 @@ WebGL2Context::ValidateAttribPointerType(bool integerMode, GLenum type, return false; } +bool +WebGL2Context::ValidateUniformMatrixTranspose(bool /*transpose*/, const char* /*info*/) +{ + return true; +} + // ------------------------------------------------------------------------- // Uniforms and attributes @@ -113,140 +118,222 @@ WebGL2Context::VertexAttribIPointer(GLuint index, GLint size, GLenum type, GLsiz } void -WebGL2Context::Uniform1ui(WebGLUniformLocation* location, GLuint v0) +WebGL2Context::Uniform1ui(WebGLUniformLocation* loc, GLuint v0) { - MOZ_CRASH("Not Implemented."); + GLuint rawLoc; + if (!ValidateUniformSetter(loc, 1, LOCAL_GL_UNSIGNED_INT, "uniform1ui", &rawLoc)) + return; + + MakeContextCurrent(); + gl->fUniform1ui(rawLoc, v0); } void -WebGL2Context::Uniform2ui(WebGLUniformLocation* location, GLuint v0, GLuint v1) +WebGL2Context::Uniform2ui(WebGLUniformLocation* loc, GLuint v0, GLuint v1) { - MOZ_CRASH("Not Implemented."); + GLuint rawLoc; + if (!ValidateUniformSetter(loc, 2, LOCAL_GL_UNSIGNED_INT, "uniform2ui", &rawLoc)) + return; + + MakeContextCurrent(); + gl->fUniform2ui(rawLoc, v0, v1); } void -WebGL2Context::Uniform3ui(WebGLUniformLocation* location, GLuint v0, GLuint v1, GLuint v2) +WebGL2Context::Uniform3ui(WebGLUniformLocation* loc, GLuint v0, GLuint v1, GLuint v2) { - MOZ_CRASH("Not Implemented."); + GLuint rawLoc; + if (!ValidateUniformSetter(loc, 3, LOCAL_GL_UNSIGNED_INT, "uniform3ui", &rawLoc)) + return; + + MakeContextCurrent(); + gl->fUniform3ui(rawLoc, v0, v1, v2); } void -WebGL2Context::Uniform4ui(WebGLUniformLocation* location, GLuint v0, GLuint v1, - GLuint v2, GLuint v3) +WebGL2Context::Uniform4ui(WebGLUniformLocation* loc, GLuint v0, GLuint v1, GLuint v2, GLuint v3) { - MOZ_CRASH("Not Implemented."); + GLuint rawLoc; + if (!ValidateUniformSetter(loc, 4, LOCAL_GL_UNSIGNED_INT, "uniform4ui", &rawLoc)) + return; + + MakeContextCurrent(); + gl->fUniform4ui(rawLoc, v0, v1, v2, v3); } void -WebGL2Context::Uniform1uiv(WebGLUniformLocation* location, - const dom::Sequence& value) +WebGL2Context::Uniform1uiv_base(WebGLUniformLocation* loc, size_t arrayLength, + const GLuint* data) { - MOZ_CRASH("Not Implemented."); + GLuint rawLoc; + GLsizei numElementsToUpload; + + if (!ValidateUniformArraySetter(loc, 1, LOCAL_GL_UNSIGNED_INT, arrayLength, + "uniform1uiv", &rawLoc, &numElementsToUpload)) + { + return; + } + + MakeContextCurrent(); + gl->fUniform1uiv(rawLoc, numElementsToUpload, data); } void -WebGL2Context::Uniform2uiv(WebGLUniformLocation* location, - const dom::Sequence& value) +WebGL2Context::Uniform2uiv_base(WebGLUniformLocation* loc, size_t arrayLength, + const GLuint* data) { - MOZ_CRASH("Not Implemented."); + GLuint rawLoc; + GLsizei numElementsToUpload; + + if (!ValidateUniformArraySetter(loc, 2, LOCAL_GL_UNSIGNED_INT, arrayLength, + "uniform2uiv", &rawLoc, &numElementsToUpload)) + { + return; + } + + MakeContextCurrent(); + gl->fUniform2uiv(rawLoc, numElementsToUpload, data); } void -WebGL2Context::Uniform3uiv(WebGLUniformLocation* location, - const dom::Sequence& value) +WebGL2Context::Uniform3uiv_base(WebGLUniformLocation* loc, size_t arrayLength, + const GLuint* data) { - MOZ_CRASH("Not Implemented."); + GLuint rawLoc; + GLsizei numElementsToUpload; + + if (!ValidateUniformArraySetter(loc, 3, LOCAL_GL_UNSIGNED_INT, arrayLength, + "uniform3uiv", &rawLoc, &numElementsToUpload)) + { + return; + } + + MakeContextCurrent(); + gl->fUniform1uiv(rawLoc, numElementsToUpload, data); } void -WebGL2Context::Uniform4uiv(WebGLUniformLocation* location, - const dom::Sequence& value) +WebGL2Context::Uniform4uiv_base(WebGLUniformLocation* loc, size_t arrayLength, + const GLuint* data) { - MOZ_CRASH("Not Implemented."); + GLuint rawLoc; + GLsizei numElementsToUpload; + + if (!ValidateUniformArraySetter(loc, 4, LOCAL_GL_UNSIGNED_INT, arrayLength, + "uniform4uiv", &rawLoc, &numElementsToUpload)) { + return; + } + + MakeContextCurrent(); + gl->fUniform4uiv(rawLoc, numElementsToUpload, data); } void -WebGL2Context::UniformMatrix2x3fv(WebGLUniformLocation* location, bool transpose, - const dom::Float32Array& value) +WebGL2Context::UniformMatrix2x3fv_base(WebGLUniformLocation* loc, bool transpose, + size_t arrayLength, const GLfloat* data) { - MOZ_CRASH("Not Implemented."); + GLuint rawLoc; + GLsizei numElementsToUpload; + + if (!ValidateUniformMatrixArraySetter(loc, 2, 3, LOCAL_GL_FLOAT, arrayLength, + transpose, "uniformMatrix2x3fv", + &rawLoc, &numElementsToUpload)) + { + return; + } + + MakeContextCurrent(); + gl->fUniformMatrix2x3fv(rawLoc, numElementsToUpload, transpose, data); } void -WebGL2Context::UniformMatrix2x3fv(WebGLUniformLocation* location, bool transpose, - const dom::Sequence& value) +WebGL2Context::UniformMatrix2x4fv_base(WebGLUniformLocation* loc, bool transpose, + size_t arrayLength, const GLfloat* data) { - MOZ_CRASH("Not Implemented."); + GLuint rawLoc; + GLsizei numElementsToUpload; + + if (!ValidateUniformMatrixArraySetter(loc, 2, 4, LOCAL_GL_FLOAT, arrayLength, + transpose, "uniformMatrix2x4fv", + &rawLoc, &numElementsToUpload)) + { + return; + } + + MakeContextCurrent(); + gl->fUniformMatrix2x4fv(rawLoc, numElementsToUpload, transpose, data); } void -WebGL2Context::UniformMatrix3x2fv(WebGLUniformLocation* location, bool transpose, - const dom::Float32Array& value) +WebGL2Context::UniformMatrix3x2fv_base(WebGLUniformLocation* loc, bool transpose, + size_t arrayLength, const GLfloat* data) { - MOZ_CRASH("Not Implemented."); + GLuint rawLoc; + GLsizei numElementsToUpload; + + if (!ValidateUniformMatrixArraySetter(loc, 3, 2, LOCAL_GL_FLOAT, arrayLength, + transpose, "uniformMatrix3x2fv", + &rawLoc, &numElementsToUpload)) + { + return; + } + + MakeContextCurrent(); + gl->fUniformMatrix3x2fv(rawLoc, numElementsToUpload, transpose, data); } void -WebGL2Context::UniformMatrix3x2fv(WebGLUniformLocation* location, bool transpose, - const dom::Sequence& value) +WebGL2Context::UniformMatrix3x4fv_base(WebGLUniformLocation* loc, bool transpose, + size_t arrayLength, const GLfloat* data) { - MOZ_CRASH("Not Implemented."); + GLuint rawLoc; + GLsizei numElementsToUpload; + + if (!ValidateUniformMatrixArraySetter(loc, 3, 4, LOCAL_GL_FLOAT, arrayLength, + transpose, "uniformMatrix3x4fv", + &rawLoc, &numElementsToUpload)) + { + return; + } + + MakeContextCurrent(); + gl->fUniformMatrix3x4fv(rawLoc, numElementsToUpload, transpose, data); } void -WebGL2Context::UniformMatrix2x4fv(WebGLUniformLocation* location, bool transpose, - const dom::Float32Array& value) +WebGL2Context::UniformMatrix4x2fv_base(WebGLUniformLocation* loc, bool transpose, + size_t arrayLength, const GLfloat* data) { - MOZ_CRASH("Not Implemented."); + GLuint rawLoc; + GLsizei numElementsToUpload; + + if (!ValidateUniformMatrixArraySetter(loc, 4, 2, LOCAL_GL_FLOAT, arrayLength, + transpose, "uniformMatrix4x2fv", + &rawLoc, &numElementsToUpload)) + { + return; + } + + MakeContextCurrent(); + gl->fUniformMatrix4x2fv(rawLoc, numElementsToUpload, transpose, data); } void -WebGL2Context::UniformMatrix2x4fv(WebGLUniformLocation* location, bool transpose, - const dom::Sequence& value) +WebGL2Context::UniformMatrix4x3fv_base(WebGLUniformLocation* loc, bool transpose, + size_t arrayLength, const GLfloat* data) { - MOZ_CRASH("Not Implemented."); -} + GLuint rawLoc; + GLsizei numElementsToUpload; -void -WebGL2Context::UniformMatrix4x2fv(WebGLUniformLocation* location, bool transpose, - const dom::Float32Array& value) -{ - MOZ_CRASH("Not Implemented."); -} + if (!ValidateUniformMatrixArraySetter(loc, 4, 3, LOCAL_GL_FLOAT, arrayLength, + transpose, "uniformMatrix4x3fv", + &rawLoc, &numElementsToUpload)) + { + return; + } -void -WebGL2Context::UniformMatrix4x2fv(WebGLUniformLocation* location, bool transpose, - const dom::Sequence& value) -{ - MOZ_CRASH("Not Implemented."); -} - -void -WebGL2Context::UniformMatrix3x4fv(WebGLUniformLocation* location, bool transpose, - const dom::Float32Array& value) -{ - MOZ_CRASH("Not Implemented."); -} - -void -WebGL2Context::UniformMatrix3x4fv(WebGLUniformLocation* location, bool transpose, - const dom::Sequence& value) -{ - MOZ_CRASH("Not Implemented."); -} - -void -WebGL2Context::UniformMatrix4x3fv(WebGLUniformLocation* location, bool transpose, - const dom::Float32Array& value) -{ - MOZ_CRASH("Not Implemented."); -} - -void -WebGL2Context::UniformMatrix4x3fv(WebGLUniformLocation* location, bool transpose, - const dom::Sequence& value) -{ - MOZ_CRASH("Not Implemented."); + MakeContextCurrent(); + gl->fUniformMatrix4x3fv(rawLoc, numElementsToUpload, transpose, data); } void @@ -450,39 +537,7 @@ WebGL2Context::GetUniformBlockIndex(WebGLProgram* program, if (!ValidateObject("getUniformBlockIndex: program", program)) return 0; - // Leave this unchecked for now. - - const NS_LossyConvertUTF16toASCII cname(uniformBlockName); - - GLuint progname = program->mGLName; - - MakeContextCurrent(); - return gl->fGetUniformBlockIndex(progname, cname.BeginReading()); -} - -static bool -GetUniformBlockActiveUniforms(gl::GLContext* gl, JSContext* cx, - WebGL2Context* owner, GLuint progname, - GLuint uniformBlockIndex, - JS::MutableHandleObject out_array) -{ - GLint length = 0; - gl->fGetActiveUniformBlockiv(progname, uniformBlockIndex, - LOCAL_GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS, &length); - JS::RootedObject obj(cx, Uint32Array::Create(cx, owner, length, nullptr)); - if (!obj) - return false; - - Uint32Array result; - DebugOnly inited = result.Init(obj); - MOZ_ASSERT(inited); - result.ComputeLengthAndData(); - gl->fGetActiveUniformBlockiv(progname, uniformBlockIndex, - LOCAL_GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES, - (GLint*) result.Data()); - - out_array.set(obj); - return true; + return program->GetUniformBlockIndex(uniformBlockName); } void @@ -498,46 +553,25 @@ WebGL2Context::GetActiveUniformBlockParameter(JSContext* cx, WebGLProgram* progr if (!ValidateObject("getActiveUniformBlockParameter: program", program)) return; - GLuint progname = program->mGLName; - GLint param = 0; - MakeContextCurrent(); switch(pname) { case LOCAL_GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER: case LOCAL_GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER: - gl->fGetActiveUniformBlockiv(progname, uniformBlockIndex, pname, ¶m); - retval.SetValue().SetAsBoolean() = (param != 0); - return; - case LOCAL_GL_UNIFORM_BLOCK_BINDING: case LOCAL_GL_UNIFORM_BLOCK_DATA_SIZE: - case LOCAL_GL_UNIFORM_BLOCK_NAME_LENGTH: case LOCAL_GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS: - gl->fGetActiveUniformBlockiv(progname, uniformBlockIndex, pname, ¶m); - retval.SetValue().SetAsUnsignedLong() = param; + program->GetActiveUniformBlockParam(uniformBlockIndex, pname, retval); return; case LOCAL_GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES: - JS::RootedObject array(cx); - if (!GetUniformBlockActiveUniforms(gl, cx, this, progname, uniformBlockIndex, - &array)) - { - rv = NS_ERROR_OUT_OF_MEMORY; - return; - } - - DebugOnly inited = retval.SetValue().SetAsUint32Array().Init(array); - MOZ_ASSERT(inited); - + program->GetActiveUniformBlockActiveUniforms(cx, uniformBlockIndex, retval, rv); return; } ErrorInvalidEnumInfo("getActiveUniformBlockParameter: parameter", pname); } -#define WEBGL_MAX_UNIFORM_BLOCK_NAME_LENGTH 256 - void WebGL2Context::GetActiveUniformBlockName(WebGLProgram* program, GLuint uniformBlockIndex, nsAString& retval) @@ -548,19 +582,9 @@ WebGL2Context::GetActiveUniformBlockName(WebGLProgram* program, GLuint uniformBl if (!ValidateObject("getActiveUniformBlockName: program", program)) return; - GLuint progname = program->mGLName; - GLchar nameBuffer[WEBGL_MAX_UNIFORM_BLOCK_NAME_LENGTH]; - GLsizei length = 0; - - MakeContextCurrent(); - gl->fGetActiveUniformBlockName(progname, uniformBlockIndex, - WEBGL_MAX_UNIFORM_BLOCK_NAME_LENGTH, &length, - nameBuffer); - retval.Assign(NS_ConvertASCIItoUTF16(nsDependentCString(nameBuffer))); + program->GetActiveUniformBlockName(uniformBlockIndex, retval); } -#undef WEBGL_MAX_UNIFORM_BLOCK_NAME_LENGTH - void WebGL2Context::UniformBlockBinding(WebGLProgram* program, GLuint uniformBlockIndex, GLuint uniformBlockBinding) @@ -571,8 +595,7 @@ WebGL2Context::UniformBlockBinding(WebGLProgram* program, GLuint uniformBlockInd if (!ValidateObject("uniformBlockBinding: program", program)) return; - GLuint progname = program->mGLName; - - MakeContextCurrent(); - gl->fUniformBlockBinding(progname, uniformBlockIndex, uniformBlockBinding); + program->UniformBlockBinding(uniformBlockIndex, uniformBlockBinding); } + +} // namespace mozilla diff --git a/dom/canvas/WebGLActiveInfo.cpp b/dom/canvas/WebGLActiveInfo.cpp index e0a1e06b8f..afa4569898 100644 --- a/dom/canvas/WebGLActiveInfo.cpp +++ b/dom/canvas/WebGLActiveInfo.cpp @@ -16,37 +16,41 @@ ElemSizeFromType(GLenum elemType) case LOCAL_GL_BOOL: case LOCAL_GL_FLOAT: case LOCAL_GL_INT: - case LOCAL_GL_INT_SAMPLER_2D: - case LOCAL_GL_INT_SAMPLER_2D_ARRAY: - case LOCAL_GL_INT_SAMPLER_3D: - case LOCAL_GL_INT_SAMPLER_CUBE: + case LOCAL_GL_UNSIGNED_INT: case LOCAL_GL_SAMPLER_2D: + case LOCAL_GL_SAMPLER_3D: + case LOCAL_GL_SAMPLER_CUBE: + case LOCAL_GL_SAMPLER_2D_SHADOW: case LOCAL_GL_SAMPLER_2D_ARRAY: case LOCAL_GL_SAMPLER_2D_ARRAY_SHADOW: - case LOCAL_GL_SAMPLER_2D_SHADOW: - case LOCAL_GL_SAMPLER_CUBE: case LOCAL_GL_SAMPLER_CUBE_SHADOW: + case LOCAL_GL_INT_SAMPLER_2D: + case LOCAL_GL_INT_SAMPLER_3D: + case LOCAL_GL_INT_SAMPLER_CUBE: + case LOCAL_GL_INT_SAMPLER_2D_ARRAY: case LOCAL_GL_UNSIGNED_INT_SAMPLER_2D: - case LOCAL_GL_UNSIGNED_INT_SAMPLER_2D_ARRAY: case LOCAL_GL_UNSIGNED_INT_SAMPLER_3D: case LOCAL_GL_UNSIGNED_INT_SAMPLER_CUBE: + case LOCAL_GL_UNSIGNED_INT_SAMPLER_2D_ARRAY: return 1; case LOCAL_GL_BOOL_VEC2: case LOCAL_GL_FLOAT_VEC2: case LOCAL_GL_INT_VEC2: + case LOCAL_GL_UNSIGNED_INT_VEC2: return 2; case LOCAL_GL_BOOL_VEC3: case LOCAL_GL_FLOAT_VEC3: case LOCAL_GL_INT_VEC3: + case LOCAL_GL_UNSIGNED_INT_VEC3: return 3; - case LOCAL_GL_BOOL_VEC4: - case LOCAL_GL_FLOAT_MAT2: case LOCAL_GL_FLOAT_VEC4: case LOCAL_GL_INT_VEC4: + case LOCAL_GL_UNSIGNED_INT_VEC4: + case LOCAL_GL_FLOAT_MAT2: return 4; case LOCAL_GL_FLOAT_MAT2x3: diff --git a/dom/canvas/WebGLBindableName.h b/dom/canvas/WebGLBindableName.h deleted file mode 100644 index d92616fb29..0000000000 --- a/dom/canvas/WebGLBindableName.h +++ /dev/null @@ -1,70 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * 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/. */ - -#ifndef WEBGLBINDABLENAME_H_ -#define WEBGLBINDABLENAME_H_ - -#include "WebGLTypes.h" - -#include "GLDefs.h" -#include "mozilla/TypeTraits.h" -#include "mozilla/Assertions.h" - -namespace mozilla { - -/** Represents a binding to a GL binding point - */ -template -class WebGLBindable -{ -public: - WebGLBindable() : mTarget(LOCAL_GL_NONE) { } - bool HasEverBeenBound() const { return mTarget != LOCAL_GL_NONE; } - - void BindTo(T target) { - MOZ_ASSERT(target != LOCAL_GL_NONE, "Can't bind to GL_NONE."); - MOZ_ASSERT(!HasEverBeenBound() || mTarget == target, "Rebinding is illegal."); - - bool targetChanged = (target != mTarget); - mTarget = target; - if (targetChanged) - OnTargetChanged(); - } - - T Target() const { - MOZ_ASSERT(HasEverBeenBound()); - return mTarget; - } - -protected: - //! Called after mTarget has been changed by BindTo(target). - virtual void OnTargetChanged() {} - - T mTarget; -}; - - -/** Represents a GL name that can be bound to a target. - */ -template -class WebGLBindableName - : public WebGLBindable -{ -public: - - explicit WebGLBindableName(GLuint aName) - : WebGLBindable() - , mGLName(aName) - { } - GLuint GLName() const { return mGLName; } - -protected: - const GLuint mGLName; -}; - - -} // namespace mozilla - -#endif // !WEBGLBINDABLENAME_H_ diff --git a/dom/canvas/WebGLContext.cpp b/dom/canvas/WebGLContext.cpp index 745b361785..b8b51f63b9 100644 --- a/dom/canvas/WebGLContext.cpp +++ b/dom/canvas/WebGLContext.cpp @@ -324,6 +324,7 @@ WebGLContext::DestroyResourcesAndContext() mBound2DTextures.Clear(); mBoundCubeMapTextures.Clear(); mBound3DTextures.Clear(); + mBoundSamplers.Clear(); mBoundArrayBuffer = nullptr; mBoundCopyReadBuffer = nullptr; mBoundCopyWriteBuffer = nullptr; @@ -1944,6 +1945,7 @@ NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(WebGLContext, mBound2DTextures, mBoundCubeMapTextures, mBound3DTextures, + mBoundSamplers, mBoundArrayBuffer, mBoundCopyReadBuffer, mBoundCopyWriteBuffer, diff --git a/dom/canvas/WebGLContext.h b/dom/canvas/WebGLContext.h index 7d27ec3f6e..08f969a439 100644 --- a/dom/canvas/WebGLContext.h +++ b/dom/canvas/WebGLContext.h @@ -65,6 +65,16 @@ class nsIDocShell; #define MINVALUE_GL_MAX_RENDERBUFFER_SIZE 1024 // Different from the spec, which sets it to 1 on page 164 #define MINVALUE_GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS 8 // Page 164 +/* + * WebGL-only GLenums + */ +#define LOCAL_GL_BROWSER_DEFAULT_WEBGL 0x9244 +#define LOCAL_GL_CONTEXT_LOST_WEBGL 0x9242 +#define LOCAL_GL_MAX_CLIENT_WAIT_TIMEOUT_WEBGL 0x9247 +#define LOCAL_GL_UNPACK_COLORSPACE_CONVERSION_WEBGL 0x9243 +#define LOCAL_GL_UNPACK_FLIP_Y_WEBGL 0x9240 +#define LOCAL_GL_UNPACK_PREMULTIPLY_ALPHA_WEBGL 0x9241 + namespace mozilla { class WebGLActiveInfo; @@ -170,6 +180,7 @@ class WebGLContext friend class WebGLExtensionCompressedTexturePVRTC; friend class WebGLExtensionCompressedTextureS3TC; friend class WebGLExtensionDepthTexture; + friend class WebGLExtensionDisjointTimerQuery; friend class WebGLExtensionDrawBuffers; friend class WebGLExtensionLoseContext; friend class WebGLExtensionVertexArray; @@ -815,9 +826,8 @@ public: UniformMatrix2fv_base(loc, transpose, value.Length(), value.Elements()); } - void UniformMatrix2fv_base(WebGLUniformLocation* loc, - WebGLboolean transpose, size_t arrayLength, - const float* data); + void UniformMatrix2fv_base(WebGLUniformLocation* loc, bool transpose, + size_t arrayLength, const float* data); void UniformMatrix3fv(WebGLUniformLocation* loc, WebGLboolean transpose, const dom::Float32Array& value) @@ -830,9 +840,8 @@ public: { UniformMatrix3fv_base(loc, transpose, value.Length(), value.Elements()); } - void UniformMatrix3fv_base(WebGLUniformLocation* loc, - WebGLboolean transpose, size_t arrayLength, - const float* data); + void UniformMatrix3fv_base(WebGLUniformLocation* loc, bool transpose, + size_t arrayLength, const float* data); void UniformMatrix4fv(WebGLUniformLocation* loc, WebGLboolean transpose, const dom::Float32Array& value) @@ -840,15 +849,14 @@ public: value.ComputeLengthAndData(); UniformMatrix4fv_base(loc, transpose, value.Length(), value.Data()); } - void UniformMatrix4fv(WebGLUniformLocation* loc, WebGLboolean transpose, + void UniformMatrix4fv(WebGLUniformLocation* loc, bool transpose, const dom::Sequence& value) { UniformMatrix4fv_base(loc, transpose, value.Length(), value.Elements()); } - void UniformMatrix4fv_base(WebGLUniformLocation* loc, - WebGLboolean transpose, size_t arrayLength, - const float* data); + void UniformMatrix4fv_base(WebGLUniformLocation* loc, bool transpose, + size_t arrayLength, const float* data); void UseProgram(WebGLProgram* prog); @@ -864,10 +872,13 @@ public: GLuint* out_rawLoc, GLsizei* out_numElementsToUpload); bool ValidateUniformMatrixArraySetter(WebGLUniformLocation* loc, - uint8_t setterDims, GLenum setterType, + uint8_t setterCols, + uint8_t setterRows, + GLenum setterType, size_t setterArraySize, bool setterTranspose, - const char* info, GLuint* out_rawLoc, + const char* info, + GLuint* out_rawLoc, GLsizei* out_numElementsToUpload); void ValidateProgram(WebGLProgram* prog); bool ValidateUniformLocation(const char* info, WebGLUniformLocation* loc); @@ -932,12 +943,11 @@ protected: WebGLRefPtr& GetBufferSlotByTarget(GLenum target); WebGLRefPtr& GetBufferSlotByTargetIndexed(GLenum target, GLuint index); - bool ValidateBufferUsageEnum(GLenum target, const char* info); // ----------------------------------------------------------------------------- // Queries (WebGL2ContextQueries.cpp) protected: - WebGLRefPtr* GetQueryTargetSlot(GLenum target); + WebGLRefPtr& GetQuerySlotByTarget(GLenum target); WebGLRefPtr mActiveOcclusionQuery; WebGLRefPtr mActiveTransformFeedbackQuery; @@ -948,7 +958,7 @@ public: void Disable(GLenum cap); void Enable(GLenum cap); bool GetStencilBits(GLint* out_stencilBits); - JS::Value GetParameter(JSContext* cx, GLenum pname, ErrorResult& rv); + virtual JS::Value GetParameter(JSContext* cx, GLenum pname, ErrorResult& rv); void GetParameter(JSContext* cx, GLenum pname, JS::MutableHandle retval, ErrorResult& rv) @@ -1391,6 +1401,9 @@ private: virtual bool ValidateBufferTarget(GLenum target, const char* info) = 0; virtual bool ValidateBufferIndexedTarget(GLenum target, const char* info) = 0; virtual bool ValidateBufferForTarget(GLenum target, WebGLBuffer* buffer, const char* info) = 0; + virtual bool ValidateBufferUsageEnum(GLenum usage, const char* info) = 0; + virtual bool ValidateQueryTarget(GLenum usage, const char* info) = 0; + virtual bool ValidateUniformMatrixTranspose(bool transpose, const char* info) = 0; protected: int32_t MaxTextureSizeForTarget(TexTarget target) const { @@ -1425,6 +1438,9 @@ protected: nsTArray > mBound2DTextures; nsTArray > mBoundCubeMapTextures; nsTArray > mBound3DTextures; + nsTArray > mBoundSamplers; + + void ResolveTexturesForDraw() const; WebGLRefPtr mCurrentProgram; RefPtr mActiveProgramLinkInfo; @@ -1593,6 +1609,8 @@ public: friend class WebGLBuffer; friend class WebGLSampler; friend class WebGLShader; + friend class WebGLSync; + friend class WebGLTimerQuery; friend class WebGLTransformFeedback; friend class WebGLUniformLocation; friend class WebGLVertexArray; diff --git a/dom/canvas/WebGLContextBuffers.cpp b/dom/canvas/WebGLContextBuffers.cpp index 3b6f84d000..606111a91c 100644 --- a/dom/canvas/WebGLContextBuffers.cpp +++ b/dom/canvas/WebGLContextBuffers.cpp @@ -93,11 +93,13 @@ WebGLContext::BindBufferBase(GLenum target, GLuint index, WebGLBuffer* buffer) if (index >= mGLMaxTransformFeedbackSeparateAttribs) return ErrorInvalidValue("bindBufferBase: index should be less than " "MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS"); + break; case LOCAL_GL_UNIFORM_BUFFER: if (index >= mGLMaxUniformBufferBindings) return ErrorInvalidValue("bindBufferBase: index should be less than " "MAX_UNIFORM_BUFFER_BINDINGS"); + break; default: return ErrorInvalidEnumInfo("bindBufferBase: target", target); @@ -131,11 +133,14 @@ WebGLContext::BindBufferRange(GLenum target, GLuint index, WebGLBuffer* buffer, if (index >= mGLMaxTransformFeedbackSeparateAttribs) return ErrorInvalidValue("bindBufferRange: index should be less than " "MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS"); + break; case LOCAL_GL_UNIFORM_BUFFER: if (index >= mGLMaxUniformBufferBindings) return ErrorInvalidValue("bindBufferRange: index should be less than " "MAX_UNIFORM_BUFFER_BINDINGS"); + break; + default: return ErrorInvalidEnumInfo("bindBufferRange: target", target); } @@ -509,6 +514,7 @@ WebGLContext::GetBufferSlotByTargetIndexed(GLenum target, GLuint index) case LOCAL_GL_TRANSFORM_FEEDBACK_BUFFER: MOZ_ASSERT(index < mGLMaxTransformFeedbackSeparateAttribs); return mBoundTransformFeedbackBuffers[index]; + case LOCAL_GL_UNIFORM_BUFFER: MOZ_ASSERT(index < mGLMaxUniformBufferBindings); return mBoundUniformBuffers[index]; diff --git a/dom/canvas/WebGLContextDraw.cpp b/dom/canvas/WebGLContextDraw.cpp index 2110de5d70..f78a0d71be 100644 --- a/dom/canvas/WebGLContextDraw.cpp +++ b/dom/canvas/WebGLContextDraw.cpp @@ -48,7 +48,9 @@ WebGLContext::DrawInstanced_check(const char* info) return true; } -bool WebGLContext::DrawArrays_check(GLint first, GLsizei count, GLsizei primcount, const char* info) +bool +WebGLContext::DrawArrays_check(GLint first, GLsizei count, GLsizei primcount, + const char* info) { if (first < 0 || count < 0) { ErrorInvalidValue("%s: negative first or count", info); diff --git a/dom/canvas/WebGLContextExtensions.cpp b/dom/canvas/WebGLContextExtensions.cpp index 56cedb6760..a8f1a6bd9c 100644 --- a/dom/canvas/WebGLContextExtensions.cpp +++ b/dom/canvas/WebGLContextExtensions.cpp @@ -36,6 +36,7 @@ WebGLContext::GetExtensionString(WebGLExtensionID ext) WEBGL_EXTENSION_IDENTIFIER(EXT_shader_texture_lod) WEBGL_EXTENSION_IDENTIFIER(EXT_sRGB) WEBGL_EXTENSION_IDENTIFIER(EXT_texture_filter_anisotropic) + WEBGL_EXTENSION_IDENTIFIER(EXT_disjoint_timer_query) WEBGL_EXTENSION_IDENTIFIER(OES_element_index_uint) WEBGL_EXTENSION_IDENTIFIER(OES_standard_derivatives) WEBGL_EXTENSION_IDENTIFIER(OES_texture_float) @@ -179,13 +180,13 @@ WebGLContext::IsExtensionSupported(WebGLExtensionID ext) const if (Preferences::GetBool("webgl.enable-draft-extensions", false) || IsWebGL2()) { - /* None for now. switch (ext) { + case WebGLExtensionID::EXT_disjoint_timer_query: + return WebGLExtensionDisjointTimerQuery::IsSupported(this); default: // For warnings-as-errors. break; } - */ } return false; @@ -312,6 +313,9 @@ WebGLContext::EnableExtension(WebGLExtensionID ext) case WebGLExtensionID::EXT_color_buffer_half_float: obj = new WebGLExtensionColorBufferHalfFloat(this); break; + case WebGLExtensionID::EXT_disjoint_timer_query: + obj = new WebGLExtensionDisjointTimerQuery(this); + break; case WebGLExtensionID::EXT_frag_depth: obj = new WebGLExtensionFragDepth(this); break; diff --git a/dom/canvas/WebGLContextGL.cpp b/dom/canvas/WebGLContextGL.cpp index c67a360085..76aa516c8d 100644 --- a/dom/canvas/WebGLContextGL.cpp +++ b/dom/canvas/WebGLContextGL.cpp @@ -243,6 +243,7 @@ WebGLContext::BindTexture(GLenum rawTarget, WebGLTexture* newTex) default: return ErrorInvalidEnumInfo("bindTexture: target", rawTarget); } + const TexTarget target(rawTarget); if (newTex) { // silently ignore a deleted texture @@ -253,29 +254,16 @@ WebGLContext::BindTexture(GLenum rawTarget, WebGLTexture* newTex) return ErrorInvalidOperation("bindTexture: this texture has already been bound to a different target"); } - const TexTarget target(rawTarget); - - WebGLTextureFakeBlackStatus currentTexFakeBlackStatus = WebGLTextureFakeBlackStatus::NotNeeded; - if (*currentTexPtr) { - currentTexFakeBlackStatus = (*currentTexPtr)->ResolvedFakeBlackStatus(); - } - WebGLTextureFakeBlackStatus newTexFakeBlackStatus = WebGLTextureFakeBlackStatus::NotNeeded; - if (newTex) { - newTexFakeBlackStatus = newTex->ResolvedFakeBlackStatus(); - } - *currentTexPtr = newTex; - if (currentTexFakeBlackStatus != newTexFakeBlackStatus) { - SetFakeBlackStatus(WebGLContextFakeBlackStatus::Unknown); - } - MakeContextCurrent(); - if (newTex) + if (newTex) { + SetFakeBlackStatus(WebGLContextFakeBlackStatus::Unknown); newTex->Bind(target); - else - gl->fBindTexture(target.get(), 0 /* == texturename */); + } else { + gl->fBindTexture(target.get(), 0); + } } void WebGLContext::BlendEquation(GLenum mode) @@ -2830,7 +2818,7 @@ WebGLContext::UniformMatrix2fv_base(WebGLUniformLocation* loc, bool transpose, { GLuint rawLoc; GLsizei numElementsToUpload; - if (!ValidateUniformMatrixArraySetter(loc, 2, LOCAL_GL_FLOAT, arrayLength, + if (!ValidateUniformMatrixArraySetter(loc, 2, 2, LOCAL_GL_FLOAT, arrayLength, transpose, "uniformMatrix2fv", &rawLoc, &numElementsToUpload)) { @@ -2847,7 +2835,7 @@ WebGLContext::UniformMatrix3fv_base(WebGLUniformLocation* loc, bool transpose, { GLuint rawLoc; GLsizei numElementsToUpload; - if (!ValidateUniformMatrixArraySetter(loc, 3, LOCAL_GL_FLOAT, arrayLength, + if (!ValidateUniformMatrixArraySetter(loc, 3, 3, LOCAL_GL_FLOAT, arrayLength, transpose, "uniformMatrix3fv", &rawLoc, &numElementsToUpload)) { @@ -2864,7 +2852,7 @@ WebGLContext::UniformMatrix4fv_base(WebGLUniformLocation* loc, bool transpose, { GLuint rawLoc; GLsizei numElementsToUpload; - if (!ValidateUniformMatrixArraySetter(loc, 4, LOCAL_GL_FLOAT, arrayLength, + if (!ValidateUniformMatrixArraySetter(loc, 4, 4, LOCAL_GL_FLOAT, arrayLength, transpose, "uniformMatrix4fv", &rawLoc, &numElementsToUpload)) { @@ -3239,6 +3227,9 @@ GLenum WebGLContext::CheckedTexImage2D(TexImageTarget texImageTarget, gl->fTexImage2D(texImageTarget.get(), level, driverInternalFormat, width, height, border, driverFormat, driverType, data); + if (effectiveInternalFormat != driverInternalFormat) + SetLegacyTextureSwizzle(gl, texImageTarget.get(), internalformat.get()); + GLenum error = LOCAL_GL_NO_ERROR; if (sizeMayChange) { error = GetAndFlushUnderlyingGLErrors(); diff --git a/dom/canvas/WebGLContextState.cpp b/dom/canvas/WebGLContextState.cpp index ea956e1d6b..b24a3ba82f 100644 --- a/dom/canvas/WebGLContextState.cpp +++ b/dom/canvas/WebGLContextState.cpp @@ -58,18 +58,6 @@ WebGLContext::Enable(GLenum cap) gl->fEnable(cap); } -static JS::Value -StringValue(JSContext* cx, const char* chars, ErrorResult& rv) -{ - JSString* str = JS_NewStringCopyZ(cx, chars); - if (!str) { - rv.Throw(NS_ERROR_OUT_OF_MEMORY); - return JS::NullValue(); - } - - return JS::StringValue(str); -} - bool WebGLContext::GetStencilBits(GLint* out_stencilBits) { @@ -150,18 +138,15 @@ WebGLContext::GetParameter(JSContext* cx, GLenum pname, ErrorResult& rv) } else if (pname >= LOCAL_GL_DRAW_BUFFER0 && pname < GLenum(LOCAL_GL_DRAW_BUFFER0 + mGLMaxDrawBuffers)) { - if (mBoundDrawFramebuffer) { - GLint iv = 0; - gl->fGetIntegerv(pname, &iv); - return JS::Int32Value(iv); - } - GLint iv = 0; gl->fGetIntegerv(pname, &iv); - if (iv == GLint(LOCAL_GL_COLOR_ATTACHMENT0 + pname - LOCAL_GL_DRAW_BUFFER0)) { + if (mBoundDrawFramebuffer) + return JS::Int32Value(iv); + + const GLint index = (pname - LOCAL_GL_DRAW_BUFFER0); + if (iv == LOCAL_GL_COLOR_ATTACHMENT0 + index) return JS::Int32Value(LOCAL_GL_BACK); - } return JS::Int32Value(LOCAL_GL_NONE); } @@ -169,31 +154,58 @@ WebGLContext::GetParameter(JSContext* cx, GLenum pname, ErrorResult& rv) if (IsExtensionEnabled(WebGLExtensionID::OES_vertex_array_object)) { if (pname == LOCAL_GL_VERTEX_ARRAY_BINDING) { - if (mBoundVertexArray == mDefaultVertexArray){ - return WebGLObjectAsJSValue(cx, (WebGLVertexArray *) nullptr, rv); - } - - return WebGLObjectAsJSValue(cx, mBoundVertexArray.get(), rv); + WebGLVertexArray* vao = + (mBoundVertexArray != mDefaultVertexArray) ? mBoundVertexArray.get() : nullptr; + return WebGLObjectAsJSValue(cx, vao, rv); } } - if (IsWebGL2()) { + if (IsExtensionEnabled(WebGLExtensionID::EXT_disjoint_timer_query)) { + if (pname == LOCAL_GL_TIMESTAMP_EXT) { + GLuint64 iv = 0; + gl->fGetInteger64v(pname, (GLint64*) &iv); + // TODO: JS doesn't support 64-bit integers. Be lossy and + // cast to double (53 bits) + return JS::NumberValue(static_cast(iv)); + } else if (pname == LOCAL_GL_GPU_DISJOINT_EXT) { + // When disjoint isn't supported, leave as false. + realGLboolean disjoint = LOCAL_GL_FALSE; + if (gl->IsExtensionSupported(gl::GLContext::EXT_disjoint_timer_query)) { + gl->fGetBooleanv(pname, &disjoint); + } + return JS::BooleanValue(bool(disjoint)); + } + } + + // Privileged string params exposed by WEBGL_debug_renderer_info: + if (IsExtensionEnabled(WebGLExtensionID::WEBGL_debug_renderer_info)) { switch (pname) { - case LOCAL_GL_MAX_SAMPLES: - case LOCAL_GL_MAX_UNIFORM_BLOCK_SIZE: - case LOCAL_GL_MAX_VERTEX_UNIFORM_COMPONENTS: { - GLint val; - gl->fGetIntegerv(pname, &val); - return JS::NumberValue(uint32_t(val)); + case UNMASKED_VENDOR_WEBGL: + case UNMASKED_RENDERER_WEBGL: + GLenum glstringname = LOCAL_GL_NONE; + if (pname == UNMASKED_VENDOR_WEBGL) { + glstringname = LOCAL_GL_VENDOR; + } else if (pname == UNMASKED_RENDERER_WEBGL) { + glstringname = LOCAL_GL_RENDERER; } + const GLchar* string = (const GLchar*) gl->fGetString(glstringname); + return StringValue(cx, string, rv); + } + } - case LOCAL_GL_TEXTURE_BINDING_3D: { - return WebGLObjectAsJSValue(cx, mBound3DTextures[mActiveTexture].get(), rv); - } + if (IsExtensionEnabled(WebGLExtensionID::OES_standard_derivatives)) { + if (pname == LOCAL_GL_FRAGMENT_SHADER_DERIVATIVE_HINT) { + GLint i = 0; + gl->fGetIntegerv(pname, &i); + return JS::Int32Value(i); + } + } - // DRAW_FRAMEBUFFER_BINDING is the same as FRAMEBUFFER_BINDING. - case LOCAL_GL_READ_FRAMEBUFFER_BINDING: - return WebGLObjectAsJSValue(cx, mBoundReadFramebuffer.get(), rv); + if (IsExtensionEnabled(WebGLExtensionID::EXT_texture_filter_anisotropic)) { + if (pname == LOCAL_GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT) { + GLfloat f = 0.f; + gl->fGetFloatv(pname, &f); + return JS::NumberValue(f); } } @@ -202,42 +214,13 @@ WebGLContext::GetParameter(JSContext* cx, GLenum pname, ErrorResult& rv) // String params // case LOCAL_GL_VENDOR: - return StringValue(cx, "Mozilla", rv); case LOCAL_GL_RENDERER: return StringValue(cx, "Mozilla", rv); - case LOCAL_GL_VERSION: { - const char* version = 0; - - if (IsWebGL2()) { - version = "WebGL 2.0"; - } else { - version = "WebGL 1.0"; - } - - MOZ_ASSERT(version != 0); - return StringValue(cx, version, rv); - } + case LOCAL_GL_VERSION: + return StringValue(cx, "WebGL 1.0", rv); case LOCAL_GL_SHADING_LANGUAGE_VERSION: return StringValue(cx, "WebGL GLSL ES 1.0", rv); - // Privileged string params exposed by WEBGL_debug_renderer_info: - case UNMASKED_VENDOR_WEBGL: - case UNMASKED_RENDERER_WEBGL: { - // The privilege check is done in WebGLContext::IsExtensionSupported. - // So here we just have to check that the extension is enabled. - if (!IsExtensionEnabled(WebGLExtensionID::WEBGL_debug_renderer_info)) { - break; - } - GLenum glstringname = LOCAL_GL_NONE; - if (pname == UNMASKED_VENDOR_WEBGL) { - glstringname = LOCAL_GL_VENDOR; - } else if (pname == UNMASKED_RENDERER_WEBGL) { - glstringname = LOCAL_GL_RENDERER; - } - const char* string = reinterpret_cast(gl->fGetString(glstringname)); - return StringValue(cx, string, rv); - } - //////////////////////////////// // Single-value params @@ -348,15 +331,6 @@ WebGLContext::GetParameter(JSContext* cx, GLenum pname, ErrorResult& rv) } return JS::Int32Value(i); } - case LOCAL_GL_FRAGMENT_SHADER_DERIVATIVE_HINT: { - if (IsExtensionEnabled(WebGLExtensionID::OES_standard_derivatives)) { - GLint i = 0; - gl->fGetIntegerv(pname, &i); - return JS::Int32Value(i); - } else { - break; - } - } case LOCAL_GL_MAX_TEXTURE_SIZE: return JS::Int32Value(mGLMaxTextureSize); @@ -385,36 +359,22 @@ WebGLContext::GetParameter(JSContext* cx, GLenum pname, ErrorResult& rv) } return JS::ObjectOrNullValue(obj); } - case LOCAL_GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS: { - if (!IsWebGL2()) { - break; - } - return JS::Int32Value(mGLMaxTransformFeedbackSeparateAttribs); - } // unsigned int. here we may have to return very large values like 2^32-1 that can't be represented as // javascript integer values. We just return them as doubles and javascript doesn't care. case LOCAL_GL_STENCIL_BACK_VALUE_MASK: + return JS::DoubleValue(mStencilValueMaskBack); // pass as FP value to allow large values such as 2^32-1. + case LOCAL_GL_STENCIL_BACK_WRITEMASK: + return JS::DoubleValue(mStencilWriteMaskBack); + case LOCAL_GL_STENCIL_VALUE_MASK: - case LOCAL_GL_STENCIL_WRITEMASK: { - GLint i = 0; // the GL api (glGetIntegerv) only does signed ints - gl->fGetIntegerv(pname, &i); - GLuint i_unsigned(i); // this is where -1 becomes 2^32-1 - double i_double(i_unsigned); // pass as FP value to allow large values such as 2^32-1. - return JS::DoubleValue(i_double); - } + return JS::DoubleValue(mStencilValueMaskFront); + + case LOCAL_GL_STENCIL_WRITEMASK: + return JS::DoubleValue(mStencilWriteMaskFront); // float - case LOCAL_GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT: { - if (IsExtensionEnabled(WebGLExtensionID::EXT_texture_filter_anisotropic)) { - GLfloat f = 0.f; - gl->fGetFloatv(pname, &f); - return JS::DoubleValue(f); - } else { - break; - } - } case LOCAL_GL_DEPTH_CLEAR_VALUE: case LOCAL_GL_LINE_WIDTH: case LOCAL_GL_POLYGON_OFFSET_FACTOR: @@ -518,13 +478,6 @@ WebGLContext::GetParameter(JSContext* cx, GLenum pname, ErrorResult& rv) return WebGLObjectAsJSValue(cx, mBoundArrayBuffer.get(), rv); } - case LOCAL_GL_TRANSFORM_FEEDBACK_BUFFER_BINDING: { - if (!IsWebGL2()) { - break; - } - return WebGLObjectAsJSValue(cx, mBoundTransformFeedbackBuffer.get(), rv); - } - case LOCAL_GL_ELEMENT_ARRAY_BUFFER_BINDING: { return WebGLObjectAsJSValue(cx, mBoundVertexArray->mElementArrayBuffer.get(), rv); } diff --git a/dom/canvas/WebGLContextUtils.cpp b/dom/canvas/WebGLContextUtils.cpp index 8a67cfcce3..6eca1a1fc7 100644 --- a/dom/canvas/WebGLContextUtils.cpp +++ b/dom/canvas/WebGLContextUtils.cpp @@ -75,6 +75,18 @@ TexImageTargetToTexTarget(TexImageTarget texImageTarget) } } +JS::Value +StringValue(JSContext* cx, const char* chars, ErrorResult& rv) +{ + JSString* str = JS_NewStringCopyZ(cx, chars); + if (!str) { + rv.Throw(NS_ERROR_OUT_OF_MEMORY); + return JS::NullValue(); + } + + return JS::StringValue(str); +} + GLComponents::GLComponents(TexInternalFormat internalformat) { TexInternalFormat unsizedformat = UnsizedInternalFormatFromInternalFormat(internalformat); @@ -249,7 +261,7 @@ DriverFormatsFromEffectiveInternalFormat(gl::GLContext* gl, // in some cases we must pass a different value. On ES, they are equal by definition // as it is an error to pass internalformat!=format. GLenum driverInternalFormat = driverFormat; - if (!gl->IsGLES()) { + if (gl->IsCompatibilityProfile()) { // Cases where desktop OpenGL requires a tweak to 'format' if (driverFormat == LOCAL_GL_SRGB) driverFormat = LOCAL_GL_RGB; @@ -284,11 +296,64 @@ DriverFormatsFromEffectiveInternalFormat(gl::GLContext* gl, } } + // OpenGL core profile removed texture formats ALPHA, LUMINANCE and LUMINANCE_ALPHA + if (gl->IsCoreProfile()) { + switch (driverFormat) { + case LOCAL_GL_ALPHA: + case LOCAL_GL_LUMINANCE: + driverInternalFormat = driverFormat = LOCAL_GL_RED; + break; + + case LOCAL_GL_LUMINANCE_ALPHA: + driverInternalFormat = driverFormat = LOCAL_GL_RG; + break; + } + } + *out_driverInternalFormat = driverInternalFormat; *out_driverFormat = driverFormat; *out_driverType = driverType; } +// Map R to A +static const GLenum kLegacyAlphaSwizzle[4] = { + LOCAL_GL_ZERO, LOCAL_GL_ZERO, LOCAL_GL_ZERO, LOCAL_GL_RED +}; +// Map R to RGB +static const GLenum kLegacyLuminanceSwizzle[4] = { + LOCAL_GL_RED, LOCAL_GL_RED, LOCAL_GL_RED, LOCAL_GL_ONE +}; +// Map R to RGB, G to A +static const GLenum kLegacyLuminanceAlphaSwizzle[4] = { + LOCAL_GL_RED, LOCAL_GL_RED, LOCAL_GL_RED, LOCAL_GL_GREEN +}; + +void +SetLegacyTextureSwizzle(gl::GLContext* gl, GLenum target, GLenum internalformat) +{ + MOZ_RELEASE_ASSERT(gl->IsSupported(gl::GLFeature::texture_swizzle)); + /* Only support swizzling on core profiles. */ + if (!gl->IsCoreProfile()) + return; + + switch (internalformat) { + case LOCAL_GL_ALPHA: + gl->fTexParameteriv(target, LOCAL_GL_TEXTURE_SWIZZLE_RGBA, + (GLint*) kLegacyAlphaSwizzle); + break; + + case LOCAL_GL_LUMINANCE: + gl->fTexParameteriv(target, LOCAL_GL_TEXTURE_SWIZZLE_RGBA, + (GLint*) kLegacyLuminanceSwizzle); + break; + + case LOCAL_GL_LUMINANCE_ALPHA: + gl->fTexParameteriv(target, LOCAL_GL_TEXTURE_SWIZZLE_RGBA, + (GLint*) kLegacyLuminanceAlphaSwizzle); + break; + } +} + /** * Return the bits per texel for format & type combination. * Assumes that format & type are a valid combination as checked with @@ -1152,12 +1217,11 @@ WebGLContext::AssertCachedState() // supported by the GL implementation. const int maxStencilBits = 8; const GLuint maxStencilBitsMask = (1 << maxStencilBits) - 1; - AssertMaskedUintParamCorrect(gl, LOCAL_GL_STENCIL_VALUE_MASK, maxStencilBitsMask, mStencilValueMaskFront); AssertMaskedUintParamCorrect(gl, LOCAL_GL_STENCIL_BACK_VALUE_MASK, maxStencilBitsMask, mStencilValueMaskBack); - AssertUintParamCorrect(gl, LOCAL_GL_STENCIL_WRITEMASK, mStencilWriteMaskFront); - AssertUintParamCorrect(gl, LOCAL_GL_STENCIL_BACK_WRITEMASK, mStencilWriteMaskBack); + AssertMaskedUintParamCorrect(gl, LOCAL_GL_STENCIL_WRITEMASK, maxStencilBitsMask, mStencilWriteMaskFront); + AssertMaskedUintParamCorrect(gl, LOCAL_GL_STENCIL_BACK_WRITEMASK, maxStencilBitsMask, mStencilWriteMaskBack); // Viewport GLint int4[4] = {0, 0, 0, 0}; diff --git a/dom/canvas/WebGLContextUtils.h b/dom/canvas/WebGLContextUtils.h index 89c9c61720..5535ee9fc6 100644 --- a/dom/canvas/WebGLContextUtils.h +++ b/dom/canvas/WebGLContextUtils.h @@ -38,6 +38,8 @@ TexType TypeFromInternalFormat(TexInternalFormat internalformat); TexInternalFormat UnsizedInternalFormatFromInternalFormat(TexInternalFormat internalformat); +void SetLegacyTextureSwizzle(gl::GLContext* gl, GLenum target, GLenum internalformat); + size_t GetBitsPerTexel(TexInternalFormat effectiveinternalformat); // For use with the different texture calls, i.e. @@ -54,6 +56,9 @@ size_t GetBitsPerTexel(TexInternalFormat effectiveinternalformat); // Returns GL_NONE if passed an invalid texture image target TexTarget TexImageTargetToTexTarget(TexImageTarget texImageTarget); +// Helper function to create a JS::Value from a C string +JS::Value StringValue(JSContext* cx, const char* str, ErrorResult& rv); + struct GLComponents { unsigned char mComponents; diff --git a/dom/canvas/WebGLContextValidate.cpp b/dom/canvas/WebGLContextValidate.cpp index 703fd0f11b..ef71627c0c 100644 --- a/dom/canvas/WebGLContextValidate.cpp +++ b/dom/canvas/WebGLContextValidate.cpp @@ -1539,7 +1539,8 @@ WebGLContext::ValidateUniformArraySetter(WebGLUniformLocation* loc, bool WebGLContext::ValidateUniformMatrixArraySetter(WebGLUniformLocation* loc, - uint8_t setterDims, + uint8_t setterCols, + uint8_t setterRows, GLenum setterType, size_t setterArraySize, bool setterTranspose, @@ -1547,7 +1548,7 @@ WebGLContext::ValidateUniformMatrixArraySetter(WebGLUniformLocation* loc, GLuint* const out_rawLoc, GLsizei* const out_numElementsToUpload) { - uint8_t setterElemSize = setterDims * setterDims; + uint8_t setterElemSize = setterCols * setterRows; if (IsContextLost()) return false; @@ -1561,10 +1562,8 @@ WebGLContext::ValidateUniformMatrixArraySetter(WebGLUniformLocation* loc, if (!loc->ValidateArrayLength(setterElemSize, setterArraySize, this, funcName)) return false; - if (setterTranspose) { - ErrorInvalidValue("%s: `transpose` must be false.", funcName); + if (!ValidateUniformMatrixTranspose(setterTranspose, funcName)) return false; - } *out_rawLoc = loc->mLoc; *out_numElementsToUpload = std::min((size_t)loc->mActiveInfo->mElemCount, @@ -1754,6 +1753,7 @@ WebGLContext::InitAndValidateGL() mBound2DTextures.Clear(); mBoundCubeMapTextures.Clear(); mBound3DTextures.Clear(); + mBoundSamplers.Clear(); mBoundArrayBuffer = nullptr; mBoundTransformFeedbackBuffer = nullptr; @@ -1797,6 +1797,7 @@ WebGLContext::InitAndValidateGL() mBound2DTextures.SetLength(mGLMaxTextureUnits); mBoundCubeMapTextures.SetLength(mGLMaxTextureUnits); mBound3DTextures.SetLength(mGLMaxTextureUnits); + mBoundSamplers.SetLength(mGLMaxTextureUnits); if (MinCapabilityMode()) { mGLMaxTextureSize = MINVALUE_GL_MAX_TEXTURE_SIZE; diff --git a/dom/canvas/WebGLExtensionBlendMinMax.cpp b/dom/canvas/WebGLExtensionBlendMinMax.cpp index f2ca63e52e..b62f870152 100644 --- a/dom/canvas/WebGLExtensionBlendMinMax.cpp +++ b/dom/canvas/WebGLExtensionBlendMinMax.cpp @@ -26,6 +26,6 @@ WebGLExtensionBlendMinMax::IsSupported(const WebGLContext* webgl) return webgl->GL()->IsSupported(gl::GLFeature::blend_minmax); } -IMPL_WEBGL_EXTENSION_GOOP(WebGLExtensionBlendMinMax) +IMPL_WEBGL_EXTENSION_GOOP(WebGLExtensionBlendMinMax, EXT_blend_minmax) } // namespace mozilla diff --git a/dom/canvas/WebGLExtensionColorBufferFloat.cpp b/dom/canvas/WebGLExtensionColorBufferFloat.cpp index 6258d13ed0..542494d2dd 100644 --- a/dom/canvas/WebGLExtensionColorBufferFloat.cpp +++ b/dom/canvas/WebGLExtensionColorBufferFloat.cpp @@ -32,6 +32,6 @@ WebGLExtensionColorBufferFloat::IsSupported(const WebGLContext* webgl) gl->IsANGLE(); } -IMPL_WEBGL_EXTENSION_GOOP(WebGLExtensionColorBufferFloat) +IMPL_WEBGL_EXTENSION_GOOP(WebGLExtensionColorBufferFloat, WEBGL_color_buffer_float) } // namespace mozilla diff --git a/dom/canvas/WebGLExtensionColorBufferHalfFloat.cpp b/dom/canvas/WebGLExtensionColorBufferHalfFloat.cpp index 7148ef4290..89d06cdb50 100644 --- a/dom/canvas/WebGLExtensionColorBufferHalfFloat.cpp +++ b/dom/canvas/WebGLExtensionColorBufferHalfFloat.cpp @@ -30,6 +30,6 @@ WebGLExtensionColorBufferHalfFloat::IsSupported(const WebGLContext* webgl) gl->IsANGLE(); } -IMPL_WEBGL_EXTENSION_GOOP(WebGLExtensionColorBufferHalfFloat) +IMPL_WEBGL_EXTENSION_GOOP(WebGLExtensionColorBufferHalfFloat, EXT_color_buffer_half_float) } // namespace mozilla diff --git a/dom/canvas/WebGLExtensionCompressedTextureATC.cpp b/dom/canvas/WebGLExtensionCompressedTextureATC.cpp index bdc3933998..dfc4884e83 100644 --- a/dom/canvas/WebGLExtensionCompressedTextureATC.cpp +++ b/dom/canvas/WebGLExtensionCompressedTextureATC.cpp @@ -21,6 +21,6 @@ WebGLExtensionCompressedTextureATC::~WebGLExtensionCompressedTextureATC() { } -IMPL_WEBGL_EXTENSION_GOOP(WebGLExtensionCompressedTextureATC) +IMPL_WEBGL_EXTENSION_GOOP(WebGLExtensionCompressedTextureATC, WEBGL_compressed_texture_atc) } // namespace mozilla diff --git a/dom/canvas/WebGLExtensionCompressedTextureETC1.cpp b/dom/canvas/WebGLExtensionCompressedTextureETC1.cpp index a26450961f..7367e0f22a 100644 --- a/dom/canvas/WebGLExtensionCompressedTextureETC1.cpp +++ b/dom/canvas/WebGLExtensionCompressedTextureETC1.cpp @@ -19,6 +19,6 @@ WebGLExtensionCompressedTextureETC1::~WebGLExtensionCompressedTextureETC1() { } -IMPL_WEBGL_EXTENSION_GOOP(WebGLExtensionCompressedTextureETC1) +IMPL_WEBGL_EXTENSION_GOOP(WebGLExtensionCompressedTextureETC1, WEBGL_compressed_texture_etc1) } // namespace mozilla diff --git a/dom/canvas/WebGLExtensionCompressedTexturePVRTC.cpp b/dom/canvas/WebGLExtensionCompressedTexturePVRTC.cpp index bdd6f629af..7af2e1fc35 100644 --- a/dom/canvas/WebGLExtensionCompressedTexturePVRTC.cpp +++ b/dom/canvas/WebGLExtensionCompressedTexturePVRTC.cpp @@ -22,6 +22,6 @@ WebGLExtensionCompressedTexturePVRTC::~WebGLExtensionCompressedTexturePVRTC() { } -IMPL_WEBGL_EXTENSION_GOOP(WebGLExtensionCompressedTexturePVRTC) +IMPL_WEBGL_EXTENSION_GOOP(WebGLExtensionCompressedTexturePVRTC, WEBGL_compressed_texture_pvrtc) } // namespace mozilla diff --git a/dom/canvas/WebGLExtensionCompressedTextureS3TC.cpp b/dom/canvas/WebGLExtensionCompressedTextureS3TC.cpp index d18f1870c4..042385a98e 100644 --- a/dom/canvas/WebGLExtensionCompressedTextureS3TC.cpp +++ b/dom/canvas/WebGLExtensionCompressedTextureS3TC.cpp @@ -22,6 +22,6 @@ WebGLExtensionCompressedTextureS3TC::~WebGLExtensionCompressedTextureS3TC() { } -IMPL_WEBGL_EXTENSION_GOOP(WebGLExtensionCompressedTextureS3TC) +IMPL_WEBGL_EXTENSION_GOOP(WebGLExtensionCompressedTextureS3TC, WEBGL_compressed_texture_s3tc) } // namespace mozilla diff --git a/dom/canvas/WebGLExtensionDebugRendererInfo.cpp b/dom/canvas/WebGLExtensionDebugRendererInfo.cpp index 00b369142c..44f2334de8 100644 --- a/dom/canvas/WebGLExtensionDebugRendererInfo.cpp +++ b/dom/canvas/WebGLExtensionDebugRendererInfo.cpp @@ -19,6 +19,6 @@ WebGLExtensionDebugRendererInfo::~WebGLExtensionDebugRendererInfo() { } -IMPL_WEBGL_EXTENSION_GOOP(WebGLExtensionDebugRendererInfo) +IMPL_WEBGL_EXTENSION_GOOP(WebGLExtensionDebugRendererInfo, WEBGL_debug_renderer_info) } // namespace mozilla diff --git a/dom/canvas/WebGLExtensionDebugShaders.cpp b/dom/canvas/WebGLExtensionDebugShaders.cpp index cc3753b893..ae01b1cde3 100644 --- a/dom/canvas/WebGLExtensionDebugShaders.cpp +++ b/dom/canvas/WebGLExtensionDebugShaders.cpp @@ -38,6 +38,6 @@ WebGLExtensionDebugShaders::GetTranslatedShaderSource(WebGLShader* shader, mContext->GetShaderTranslatedSource(shader, retval); } -IMPL_WEBGL_EXTENSION_GOOP(WebGLExtensionDebugShaders) +IMPL_WEBGL_EXTENSION_GOOP(WebGLExtensionDebugShaders, WEBGL_debug_shaders) } // namespace mozilla diff --git a/dom/canvas/WebGLExtensionDepthTexture.cpp b/dom/canvas/WebGLExtensionDepthTexture.cpp index 6c22e0d20e..00bf189353 100644 --- a/dom/canvas/WebGLExtensionDepthTexture.cpp +++ b/dom/canvas/WebGLExtensionDepthTexture.cpp @@ -19,6 +19,6 @@ WebGLExtensionDepthTexture::~WebGLExtensionDepthTexture() { } -IMPL_WEBGL_EXTENSION_GOOP(WebGLExtensionDepthTexture) +IMPL_WEBGL_EXTENSION_GOOP(WebGLExtensionDepthTexture, WEBGL_depth_texture) } // namespace mozilla diff --git a/dom/canvas/WebGLExtensionDisjointTimerQuery.cpp b/dom/canvas/WebGLExtensionDisjointTimerQuery.cpp new file mode 100644 index 0000000000..4be7e8a806 --- /dev/null +++ b/dom/canvas/WebGLExtensionDisjointTimerQuery.cpp @@ -0,0 +1,247 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * 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/. */ + +#include "WebGLExtensions.h" + +#include "mozilla/dom/ToJSValue.h" +#include "mozilla/dom/WebGLRenderingContextBinding.h" +#include "mozilla/dom/BindingUtils.h" +#include "GLContext.h" +#include "WebGLContext.h" +#include "WebGLTimerQuery.h" + +namespace mozilla { + +WebGLExtensionDisjointTimerQuery::WebGLExtensionDisjointTimerQuery(WebGLContext* webgl) + : WebGLExtensionBase(webgl) + , mActiveQuery(nullptr) +{ + MOZ_ASSERT(IsSupported(webgl), "Don't construct extension if unsupported."); +} + +WebGLExtensionDisjointTimerQuery::~WebGLExtensionDisjointTimerQuery() +{ +} + +already_AddRefed +WebGLExtensionDisjointTimerQuery::CreateQueryEXT() +{ + if (mIsLost) + return nullptr; + + nsRefPtr query = WebGLTimerQuery::Create(mContext); + return query.forget(); +} + +void +WebGLExtensionDisjointTimerQuery::DeleteQueryEXT(WebGLTimerQuery* query) +{ + if (mIsLost) + return; + + if (!mContext->ValidateObject("deleteQueryEXT", query)) + return; + + query->RequestDelete(); +} + +bool +WebGLExtensionDisjointTimerQuery::IsQueryEXT(WebGLTimerQuery* query) +{ + if (!query) + return false; + + if (!mContext->ValidateObjectAllowDeleted("isQueryEXT", query)) + return false; + + if (query->IsDeleted()) + return false; + + return true; +} + +void +WebGLExtensionDisjointTimerQuery::BeginQueryEXT(GLenum target, + WebGLTimerQuery* query) +{ + if (mIsLost) + return; + + if (!mContext->ValidateObject("beginQueryEXT", query)) + return; + + if (query->HasEverBeenBound() && query->Target() != target) { + mContext->ErrorInvalidOperation("beginQueryEXT: Query is already bound" + " to a different target."); + return; + } + + if (target != LOCAL_GL_TIME_ELAPSED_EXT) { + mContext->ErrorInvalidEnumInfo("beginQueryEXT: Can only begin on target" + " TIME_ELAPSED_EXT.", target); + return; + } + + if (mActiveQuery) { + mContext->ErrorInvalidOperation("beginQueryEXT: A query is already" + " active."); + return; + } + + mContext->MakeContextCurrent(); + gl::GLContext* gl = mContext->GL(); + gl->fBeginQuery(target, query->mGLName); + query->mTarget = LOCAL_GL_TIME_ELAPSED_EXT; + mActiveQuery = query; +} + +void +WebGLExtensionDisjointTimerQuery::EndQueryEXT(GLenum target) +{ + if (mIsLost) + return; + + if (target != LOCAL_GL_TIME_ELAPSED_EXT) { + mContext->ErrorInvalidEnumInfo("endQueryEXT: Can only end on" + " TIME_ELAPSED_EXT.", target); + return; + } + + if (!mActiveQuery) { + mContext->ErrorInvalidOperation("endQueryEXT: A query is not active."); + return; + } + + mContext->MakeContextCurrent(); + mContext->GL()->fEndQuery(target); + mActiveQuery = nullptr; +} + +void +WebGLExtensionDisjointTimerQuery::QueryCounterEXT(WebGLTimerQuery* query, + GLenum target) +{ + if (mIsLost) + return; + + if (!mContext->ValidateObject("queryCounterEXT", query)) + return; + + if (target != LOCAL_GL_TIMESTAMP_EXT) { + mContext->ErrorInvalidEnumInfo("queryCounterEXT: requires" + " TIMESTAMP_EXT.", target); + return; + } + + mContext->MakeContextCurrent(); + mContext->GL()->fQueryCounter(query->mGLName, target); + query->mTarget = LOCAL_GL_TIMESTAMP_EXT; +} + +void +WebGLExtensionDisjointTimerQuery::GetQueryEXT(JSContext* cx, GLenum target, + GLenum pname, + JS::MutableHandle retval) +{ + if (mIsLost) + return; + + mContext->MakeContextCurrent(); + switch (pname) { + case LOCAL_GL_CURRENT_QUERY_EXT: { + if (target != LOCAL_GL_TIME_ELAPSED_EXT) { + mContext->ErrorInvalidEnumInfo("getQueryEXT: Invalid query target.", + target); + return; + } + if (mActiveQuery) { + JS::Rooted v(cx); + dom::GetOrCreateDOMReflector(cx, mActiveQuery.get(), &v); + retval.set(v); + } else { + retval.set(JS::NullValue()); + } + break; + } + case LOCAL_GL_QUERY_COUNTER_BITS_EXT: { + if (target != LOCAL_GL_TIME_ELAPSED_EXT && + target != LOCAL_GL_TIMESTAMP_EXT) { + mContext->ErrorInvalidEnumInfo("getQueryEXT: Invalid query target.", + target); + return; + } + GLint bits = 0; + mContext->GL()->fGetQueryiv(target, pname, &bits); + retval.set(JS::Int32Value(int32_t(bits))); + break; + } + default: + mContext->ErrorInvalidEnumInfo("getQueryEXT: Invalid query property.", + pname); + break; + } +} + +void +WebGLExtensionDisjointTimerQuery::GetQueryObjectEXT(JSContext* cx, + WebGLTimerQuery* query, + GLenum pname, + JS::MutableHandle retval) +{ + if (mIsLost) + return; + + if (!mContext->ValidateObject("getQueryObjectEXT", query)) + return; + + if (query == mActiveQuery.get()) { + mContext->ErrorInvalidOperation("getQueryObjectEXT: Query must not be" + " active."); + } + + mContext->MakeContextCurrent(); + // XXX: Note that the query result *may change* within the same task! + // This does not follow the specification, which states that all calls + // checking query results must return the same value until the event loop + // is empty. + switch (pname) { + case LOCAL_GL_QUERY_RESULT_EXT: { + GLuint64 result = 0; + mContext->GL()->fGetQueryObjectui64v(query->mGLName, + LOCAL_GL_QUERY_RESULT_EXT, + &result); + retval.set(JS::NumberValue(result)); + break; + } + case LOCAL_GL_QUERY_RESULT_AVAILABLE_EXT: { + GLuint avail = 0; + mContext->GL()->fGetQueryObjectuiv(query->mGLName, + LOCAL_GL_QUERY_RESULT_AVAILABLE_EXT, + &avail); + retval.set(JS::BooleanValue(bool(avail))); + break; + } + default: + mContext->ErrorInvalidEnumInfo("getQueryObjectEXT: Invalid query" + " property.", pname); + break; + } +} + +bool +WebGLExtensionDisjointTimerQuery::IsSupported(const WebGLContext* webgl) +{ + webgl->MakeContextCurrent(); + gl::GLContext* gl = webgl->GL(); + return gl->IsSupported(gl::GLFeature::query_objects) && + gl->IsSupported(gl::GLFeature::get_query_object_i64v) && + gl->IsSupported(gl::GLFeature::query_counter); // provides GL_TIMESTAMP +} + + +IMPL_WEBGL_EXTENSION_GOOP(WebGLExtensionDisjointTimerQuery, EXT_disjoint_timer_query) + +} // namespace mozilla diff --git a/dom/canvas/WebGLExtensionDrawBuffers.cpp b/dom/canvas/WebGLExtensionDrawBuffers.cpp index ca04a2be9e..4be99124ac 100644 --- a/dom/canvas/WebGLExtensionDrawBuffers.cpp +++ b/dom/canvas/WebGLExtensionDrawBuffers.cpp @@ -83,6 +83,6 @@ WebGLExtensionDrawBuffers::IsSupported(const WebGLContext* webgl) return true; } -IMPL_WEBGL_EXTENSION_GOOP(WebGLExtensionDrawBuffers) +IMPL_WEBGL_EXTENSION_GOOP(WebGLExtensionDrawBuffers, WEBGL_draw_buffers) } // namespace mozilla diff --git a/dom/canvas/WebGLExtensionElementIndexUint.cpp b/dom/canvas/WebGLExtensionElementIndexUint.cpp index 1ff22e593d..080d71eb06 100644 --- a/dom/canvas/WebGLExtensionElementIndexUint.cpp +++ b/dom/canvas/WebGLExtensionElementIndexUint.cpp @@ -19,6 +19,6 @@ WebGLExtensionElementIndexUint::~WebGLExtensionElementIndexUint() { } -IMPL_WEBGL_EXTENSION_GOOP(WebGLExtensionElementIndexUint) +IMPL_WEBGL_EXTENSION_GOOP(WebGLExtensionElementIndexUint, OES_element_index_uint) } // namespace mozilla diff --git a/dom/canvas/WebGLExtensionFragDepth.cpp b/dom/canvas/WebGLExtensionFragDepth.cpp index 51faffb335..130a3dedef 100644 --- a/dom/canvas/WebGLExtensionFragDepth.cpp +++ b/dom/canvas/WebGLExtensionFragDepth.cpp @@ -29,6 +29,6 @@ WebGLExtensionFragDepth::IsSupported(const WebGLContext* webgl) } -IMPL_WEBGL_EXTENSION_GOOP(WebGLExtensionFragDepth) +IMPL_WEBGL_EXTENSION_GOOP(WebGLExtensionFragDepth, EXT_frag_depth) } // namespace mozilla diff --git a/dom/canvas/WebGLExtensionInstancedArrays.cpp b/dom/canvas/WebGLExtensionInstancedArrays.cpp index b8dfa93902..10d0533fe4 100644 --- a/dom/canvas/WebGLExtensionInstancedArrays.cpp +++ b/dom/canvas/WebGLExtensionInstancedArrays.cpp @@ -73,6 +73,6 @@ WebGLExtensionInstancedArrays::IsSupported(const WebGLContext* webgl) gl->IsSupported(gl::GLFeature::instanced_arrays); } -IMPL_WEBGL_EXTENSION_GOOP(WebGLExtensionInstancedArrays) +IMPL_WEBGL_EXTENSION_GOOP(WebGLExtensionInstancedArrays, ANGLE_instanced_arrays) } // namespace mozilla diff --git a/dom/canvas/WebGLExtensionLoseContext.cpp b/dom/canvas/WebGLExtensionLoseContext.cpp index 609eed7a97..020731e636 100644 --- a/dom/canvas/WebGLExtensionLoseContext.cpp +++ b/dom/canvas/WebGLExtensionLoseContext.cpp @@ -31,6 +31,6 @@ WebGLExtensionLoseContext::RestoreContext() mContext->RestoreContext(); } -IMPL_WEBGL_EXTENSION_GOOP(WebGLExtensionLoseContext) +IMPL_WEBGL_EXTENSION_GOOP(WebGLExtensionLoseContext, WEBGL_lose_context) } // namespace mozilla diff --git a/dom/canvas/WebGLExtensionSRGB.cpp b/dom/canvas/WebGLExtensionSRGB.cpp index b1e3e15595..d7526147fc 100644 --- a/dom/canvas/WebGLExtensionSRGB.cpp +++ b/dom/canvas/WebGLExtensionSRGB.cpp @@ -34,10 +34,11 @@ WebGLExtensionSRGB::IsSupported(const WebGLContext* webgl) { gl::GLContext* gl = webgl->GL(); - return gl->IsSupported(gl::GLFeature::sRGB); + return gl->IsSupported(gl::GLFeature::sRGB_framebuffer) && + gl->IsSupported(gl::GLFeature::sRGB_texture); } -IMPL_WEBGL_EXTENSION_GOOP(WebGLExtensionSRGB) +IMPL_WEBGL_EXTENSION_GOOP(WebGLExtensionSRGB, EXT_sRGB) } // namespace mozilla diff --git a/dom/canvas/WebGLExtensionShaderTextureLod.cpp b/dom/canvas/WebGLExtensionShaderTextureLod.cpp index 2af8557ced..219cbfba52 100644 --- a/dom/canvas/WebGLExtensionShaderTextureLod.cpp +++ b/dom/canvas/WebGLExtensionShaderTextureLod.cpp @@ -19,6 +19,6 @@ WebGLExtensionShaderTextureLod::~WebGLExtensionShaderTextureLod() { } -IMPL_WEBGL_EXTENSION_GOOP(WebGLExtensionShaderTextureLod) +IMPL_WEBGL_EXTENSION_GOOP(WebGLExtensionShaderTextureLod, EXT_shader_texture_lod) } // namespace mozilla diff --git a/dom/canvas/WebGLExtensionStandardDerivatives.cpp b/dom/canvas/WebGLExtensionStandardDerivatives.cpp index ffbda05baf..948aa536e5 100644 --- a/dom/canvas/WebGLExtensionStandardDerivatives.cpp +++ b/dom/canvas/WebGLExtensionStandardDerivatives.cpp @@ -19,6 +19,6 @@ WebGLExtensionStandardDerivatives::~WebGLExtensionStandardDerivatives() { } -IMPL_WEBGL_EXTENSION_GOOP(WebGLExtensionStandardDerivatives) +IMPL_WEBGL_EXTENSION_GOOP(WebGLExtensionStandardDerivatives, OES_standard_derivatives) } // namespace mozilla diff --git a/dom/canvas/WebGLExtensionTextureFilterAnisotropic.cpp b/dom/canvas/WebGLExtensionTextureFilterAnisotropic.cpp index 6ad2bef1bc..a1cb8abfd6 100644 --- a/dom/canvas/WebGLExtensionTextureFilterAnisotropic.cpp +++ b/dom/canvas/WebGLExtensionTextureFilterAnisotropic.cpp @@ -19,6 +19,6 @@ WebGLExtensionTextureFilterAnisotropic::~WebGLExtensionTextureFilterAnisotropic( { } -IMPL_WEBGL_EXTENSION_GOOP(WebGLExtensionTextureFilterAnisotropic) +IMPL_WEBGL_EXTENSION_GOOP(WebGLExtensionTextureFilterAnisotropic, EXT_texture_filter_anisotropic) } // namespace mozilla diff --git a/dom/canvas/WebGLExtensionTextureFloat.cpp b/dom/canvas/WebGLExtensionTextureFloat.cpp index 6f1befe1ae..b85a75b14a 100644 --- a/dom/canvas/WebGLExtensionTextureFloat.cpp +++ b/dom/canvas/WebGLExtensionTextureFloat.cpp @@ -18,6 +18,6 @@ WebGLExtensionTextureFloat::~WebGLExtensionTextureFloat() { } -IMPL_WEBGL_EXTENSION_GOOP(WebGLExtensionTextureFloat) +IMPL_WEBGL_EXTENSION_GOOP(WebGLExtensionTextureFloat, OES_texture_float) } // namespace mozilla diff --git a/dom/canvas/WebGLExtensionTextureFloatLinear.cpp b/dom/canvas/WebGLExtensionTextureFloatLinear.cpp index e5d408c79c..69459dc742 100644 --- a/dom/canvas/WebGLExtensionTextureFloatLinear.cpp +++ b/dom/canvas/WebGLExtensionTextureFloatLinear.cpp @@ -18,6 +18,6 @@ WebGLExtensionTextureFloatLinear::~WebGLExtensionTextureFloatLinear() { } -IMPL_WEBGL_EXTENSION_GOOP(WebGLExtensionTextureFloatLinear) +IMPL_WEBGL_EXTENSION_GOOP(WebGLExtensionTextureFloatLinear, OES_texture_float_linear) } // namespace mozilla diff --git a/dom/canvas/WebGLExtensionTextureHalfFloat.cpp b/dom/canvas/WebGLExtensionTextureHalfFloat.cpp index eaabf7637e..27f80c6700 100644 --- a/dom/canvas/WebGLExtensionTextureHalfFloat.cpp +++ b/dom/canvas/WebGLExtensionTextureHalfFloat.cpp @@ -18,6 +18,6 @@ WebGLExtensionTextureHalfFloat::~WebGLExtensionTextureHalfFloat() { } -IMPL_WEBGL_EXTENSION_GOOP(WebGLExtensionTextureHalfFloat) +IMPL_WEBGL_EXTENSION_GOOP(WebGLExtensionTextureHalfFloat, OES_texture_half_float) } // namespace mozilla diff --git a/dom/canvas/WebGLExtensionTextureHalfFloatLinear.cpp b/dom/canvas/WebGLExtensionTextureHalfFloatLinear.cpp index f97eb39b22..21912069ef 100644 --- a/dom/canvas/WebGLExtensionTextureHalfFloatLinear.cpp +++ b/dom/canvas/WebGLExtensionTextureHalfFloatLinear.cpp @@ -18,6 +18,6 @@ WebGLExtensionTextureHalfFloatLinear::~WebGLExtensionTextureHalfFloatLinear() { } -IMPL_WEBGL_EXTENSION_GOOP(WebGLExtensionTextureHalfFloatLinear) +IMPL_WEBGL_EXTENSION_GOOP(WebGLExtensionTextureHalfFloatLinear, OES_texture_half_float_linear) } // namespace mozilla diff --git a/dom/canvas/WebGLExtensionVertexArray.cpp b/dom/canvas/WebGLExtensionVertexArray.cpp index 0b75bd1e07..86da6945a6 100644 --- a/dom/canvas/WebGLExtensionVertexArray.cpp +++ b/dom/canvas/WebGLExtensionVertexArray.cpp @@ -70,6 +70,6 @@ WebGLExtensionVertexArray::BindVertexArrayOES(WebGLVertexArray* array) mContext->BindVertexArray(array); } -IMPL_WEBGL_EXTENSION_GOOP(WebGLExtensionVertexArray) +IMPL_WEBGL_EXTENSION_GOOP(WebGLExtensionVertexArray, OES_vertex_array_object) } // namespace mozilla diff --git a/dom/canvas/WebGLExtensions.h b/dom/canvas/WebGLExtensions.h index b41f0186d1..60eb30092a 100644 --- a/dom/canvas/WebGLExtensions.h +++ b/dom/canvas/WebGLExtensions.h @@ -16,6 +16,8 @@ namespace mozilla { class WebGLContext; class WebGLShader; +class WebGLQuery; +class WebGLTimerQuery; class WebGLVertexArray; class WebGLExtensionBase @@ -43,10 +45,10 @@ protected: #define DECL_WEBGL_EXTENSION_GOOP \ virtual JSObject* WrapObject(JSContext* cx, JS::Handle aGivenProto) override; -#define IMPL_WEBGL_EXTENSION_GOOP(WebGLExtensionType) \ +#define IMPL_WEBGL_EXTENSION_GOOP(WebGLExtensionType, WebGLBindingType)\ JSObject* \ WebGLExtensionType::WrapObject(JSContext* cx, JS::Handle aGivenProto) { \ - return dom::WebGLExtensionType##Binding::Wrap(cx, this, aGivenProto); \ + return dom::WebGLBindingType##Binding::Wrap(cx, this, aGivenProto); \ } class WebGLExtensionCompressedTextureATC @@ -329,6 +331,36 @@ public: DECL_WEBGL_EXTENSION_GOOP }; +class WebGLExtensionDisjointTimerQuery + : public WebGLExtensionBase +{ +public: + explicit WebGLExtensionDisjointTimerQuery(WebGLContext* webgl); + virtual ~WebGLExtensionDisjointTimerQuery(); + + already_AddRefed CreateQueryEXT(); + void DeleteQueryEXT(WebGLTimerQuery* query); + bool IsQueryEXT(WebGLTimerQuery* query); + void BeginQueryEXT(GLenum target, WebGLTimerQuery* query); + void EndQueryEXT(GLenum target); + void QueryCounterEXT(WebGLTimerQuery* query, GLenum target); + void GetQueryEXT(JSContext *cx, GLenum target, GLenum pname, + JS::MutableHandle retval); + void GetQueryObjectEXT(JSContext *cx, WebGLTimerQuery* query, + GLenum pname, + JS::MutableHandle retval); + + static bool IsSupported(const WebGLContext*); + + DECL_WEBGL_EXTENSION_GOOP + +private: + /** + * An active TIME_ELAPSED query participating in a begin/end block. + */ + WebGLRefPtr mActiveQuery; +}; + } // namespace mozilla #endif // WEBGL_EXTENSIONS_H_ diff --git a/dom/canvas/WebGLProgram.cpp b/dom/canvas/WebGLProgram.cpp index 577618c8f9..1dece60fe6 100644 --- a/dom/canvas/WebGLProgram.cpp +++ b/dom/canvas/WebGLProgram.cpp @@ -78,6 +78,16 @@ AddActiveInfo(WebGLContext* webgl, GLint elemCount, GLenum elemType, bool isArra infoLocMap->insert(std::make_pair(info->mBaseUserName, info.get())); } +static void +AddActiveBlockInfo(const nsACString& baseUserName, + const nsACString& baseMappedName, + std::vector>* activeInfoList) +{ + RefPtr info = new webgl::UniformBlockInfo(baseUserName, baseMappedName); + + activeInfoList->push_back(info); +} + //#define DUMP_SHADERVAR_MAPPINGS static already_AddRefed @@ -97,9 +107,18 @@ QueryProgramInfo(WebGLProgram* prog, gl::GLContext* gl) if (maxUniformLenWithNull < 1) maxUniformLenWithNull = 1; + GLuint maxUniformBlockLenWithNull = 0; + if (gl->IsSupported(gl::GLFeature::uniform_buffer_object)) { + gl->fGetProgramiv(prog->mGLName, LOCAL_GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH, + (GLint*)&maxUniformBlockLenWithNull); + if (maxUniformBlockLenWithNull < 1) + maxUniformBlockLenWithNull = 1; + } + #ifdef DUMP_SHADERVAR_MAPPINGS printf_stderr("maxAttribLenWithNull: %d\n", maxAttribLenWithNull); printf_stderr("maxUniformLenWithNull: %d\n", maxUniformLenWithNull); + printf_stderr("maxUniformBlockLenWithNull: %d\n", maxUniformBlockLenWithNull); #endif // Attribs @@ -204,6 +223,54 @@ QueryProgramInfo(WebGLProgram* prog, gl::GLContext* gl) baseMappedName, &info->activeUniforms, &info->uniformMap); } + // Uniform Blocks + + if (gl->IsSupported(gl::GLFeature::uniform_buffer_object)) { + GLuint numActiveUniformBlocks = 0; + gl->fGetProgramiv(prog->mGLName, LOCAL_GL_ACTIVE_UNIFORM_BLOCKS, + (GLint*)&numActiveUniformBlocks); + + for (GLuint i = 0; i < numActiveUniformBlocks; i++) { + nsAutoCString mappedName; + mappedName.SetLength(maxUniformBlockLenWithNull - 1); + + GLint lengthWithoutNull; + gl->fGetActiveUniformBlockiv(prog->mGLName, i, LOCAL_GL_UNIFORM_BLOCK_NAME_LENGTH, &lengthWithoutNull); + gl->fGetActiveUniformBlockName(prog->mGLName, i, maxUniformBlockLenWithNull, &lengthWithoutNull, mappedName.BeginWriting()); + mappedName.SetLength(lengthWithoutNull); + + nsAutoCString baseMappedName; + bool isArray; + size_t arrayIndex; + if (!ParseName(mappedName, &baseMappedName, &isArray, &arrayIndex)) + MOZ_CRASH("Failed to parse `mappedName` received from driver."); + + nsAutoCString baseUserName; + if (!prog->FindUniformBlockByMappedName(baseMappedName, &baseUserName, &isArray)) { + baseUserName = baseMappedName; + + if (needsCheckForArrays && !isArray) { + std::string mappedName = baseMappedName.BeginReading(); + mappedName += "[0]"; + + GLuint loc = gl->fGetUniformBlockIndex(prog->mGLName, mappedName.c_str()); + if (loc != LOCAL_GL_INVALID_INDEX) + isArray = true; + } + } + +#ifdef DUMP_SHADERVAR_MAPPINGS + printf_stderr("[uniform block %i] %s/%i/%s/%s\n", i, mappedName.BeginReading(), + (int)isArray, baseMappedName.BeginReading(), + baseUserName.BeginReading()); + printf_stderr(" lengthWithoutNull: %d\n", lengthWithoutNull); + printf_stderr(" isArray: %d\n", (int)isArray); +#endif + + AddActiveBlockInfo(baseUserName, baseMappedName, &info->uniformBlocks); + } + } + return info.forget(); } @@ -228,6 +295,7 @@ CreateProgram(gl::GLContext* gl) WebGLProgram::WebGLProgram(WebGLContext* webgl) : WebGLContextBoundObject(webgl) , mGLName(CreateProgram(webgl->GL())) + , mTransformFeedbackBufferMode(LOCAL_GL_NONE) { mContext->mPrograms.insertBack(this); } @@ -365,6 +433,7 @@ already_AddRefed WebGLProgram::GetActiveUniform(GLuint index) const { if (!mMostRecentLinkInfo) { + // According to the spec, this can return null. nsRefPtr ret = WebGLActiveInfo::CreateInvalid(mContext); return ret.forget(); } @@ -465,9 +534,11 @@ WebGLProgram::GetProgramParameter(GLenum pname) const switch (pname) { case LOCAL_GL_ACTIVE_UNIFORM_BLOCKS: return JS::Int32Value(GetProgramiv(gl, mGLName, pname)); - } - } + case LOCAL_GL_TRANSFORM_FEEDBACK_VARYINGS: + return JS::Int32Value(mTransformFeedbackVaryings.size()); + } + } switch (pname) { case LOCAL_GL_ATTACHED_SHADERS: @@ -496,6 +567,141 @@ WebGLProgram::GetProgramParameter(GLenum pname) const } } +GLuint +WebGLProgram::GetUniformBlockIndex(const nsAString& userName_wide) const +{ + if (!ValidateGLSLVariableName(userName_wide, mContext, "getUniformBlockIndex")) + return LOCAL_GL_INVALID_INDEX; + + if (!IsLinked()) { + mContext->ErrorInvalidOperation("getUniformBlockIndex: `program` must be linked."); + return LOCAL_GL_INVALID_INDEX; + } + + const NS_LossyConvertUTF16toASCII userName(userName_wide); + + nsDependentCString baseUserName; + bool isArray; + size_t arrayIndex; + if (!ParseName(userName, &baseUserName, &isArray, &arrayIndex)) + return LOCAL_GL_INVALID_INDEX; + + RefPtr info; + if (!LinkInfo()->FindUniformBlock(baseUserName, &info)) { + return LOCAL_GL_INVALID_INDEX; + } + + const nsCString& baseMappedName = info->mBaseMappedName; + nsAutoCString mappedName(baseMappedName); + if (isArray) { + mappedName.AppendLiteral("["); + mappedName.AppendInt(uint32_t(arrayIndex)); + mappedName.AppendLiteral("]"); + } + + gl::GLContext* gl = mContext->GL(); + gl->MakeCurrent(); + + return gl->fGetUniformBlockIndex(mGLName, mappedName.BeginReading()); +} + +void +WebGLProgram::GetActiveUniformBlockName(GLuint uniformBlockIndex, nsAString& retval) const +{ + if (!IsLinked()) { + mContext->ErrorInvalidOperation("getActiveUniformBlockName: `program` must be linked."); + return; + } + + const webgl::LinkedProgramInfo* linkInfo = LinkInfo(); + GLuint uniformBlockCount = (GLuint) linkInfo->uniformBlocks.size(); + if (uniformBlockIndex >= uniformBlockCount) { + mContext->ErrorInvalidValue("getActiveUniformBlockName: index %u invalid.", uniformBlockIndex); + return; + } + + const webgl::UniformBlockInfo* blockInfo = linkInfo->uniformBlocks[uniformBlockIndex]; + + retval.Assign(NS_ConvertASCIItoUTF16(blockInfo->mBaseUserName)); +} + +void +WebGLProgram::GetActiveUniformBlockParam(GLuint uniformBlockIndex, GLenum pname, + Nullable& retval) const +{ + retval.SetNull(); + if (!IsLinked()) { + mContext->ErrorInvalidOperation("getActiveUniformBlockParameter: `program` must be linked."); + return; + } + + const webgl::LinkedProgramInfo* linkInfo = LinkInfo(); + GLuint uniformBlockCount = (GLuint)linkInfo->uniformBlocks.size(); + if (uniformBlockIndex >= uniformBlockCount) { + mContext->ErrorInvalidValue("getActiveUniformBlockParameter: index %u invalid.", uniformBlockIndex); + return; + } + + gl::GLContext* gl = mContext->GL(); + GLint param = 0; + + switch (pname) { + case LOCAL_GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER: + case LOCAL_GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER: + gl->fGetActiveUniformBlockiv(mGLName, uniformBlockIndex, pname, ¶m); + retval.SetValue().SetAsBoolean() = (param != 0); + return; + + case LOCAL_GL_UNIFORM_BLOCK_BINDING: + case LOCAL_GL_UNIFORM_BLOCK_DATA_SIZE: + case LOCAL_GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS: + gl->fGetActiveUniformBlockiv(mGLName, uniformBlockIndex, pname, ¶m); + retval.SetValue().SetAsUnsignedLong() = param; + return; + } +} + +void +WebGLProgram::GetActiveUniformBlockActiveUniforms(JSContext* cx, GLuint uniformBlockIndex, + Nullable& retval, + ErrorResult& rv) const +{ + if (!IsLinked()) { + mContext->ErrorInvalidOperation("getActiveUniformBlockParameter: `program` must be linked."); + return; + } + + const webgl::LinkedProgramInfo* linkInfo = LinkInfo(); + GLuint uniformBlockCount = (GLuint)linkInfo->uniformBlocks.size(); + if (uniformBlockIndex >= uniformBlockCount) { + mContext->ErrorInvalidValue("getActiveUniformBlockParameter: index %u invalid.", uniformBlockIndex); + return; + } + + gl::GLContext* gl = mContext->GL(); + GLint activeUniformCount = 0; + gl->fGetActiveUniformBlockiv(mGLName, uniformBlockIndex, + LOCAL_GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS, + &activeUniformCount); + JS::RootedObject obj(cx, dom::Uint32Array::Create(cx, mContext, activeUniformCount, + nullptr)); + if (!obj) { + rv = NS_ERROR_OUT_OF_MEMORY; + return; + } + + dom::Uint32Array result; + DebugOnly inited = result.Init(obj); + MOZ_ASSERT(inited); + result.ComputeLengthAndData(); + gl->fGetActiveUniformBlockiv(mGLName, uniformBlockIndex, + LOCAL_GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES, + (GLint*)result.Data()); + + inited = retval.SetValue().SetAsUint32Array().Init(obj); + MOZ_ASSERT(inited); +} + already_AddRefed WebGLProgram::GetUniformLocation(const nsAString& userName_wide) const { @@ -540,6 +746,31 @@ WebGLProgram::GetUniformLocation(const nsAString& userName_wide) const return locObj.forget(); } +void +WebGLProgram::UniformBlockBinding(GLuint uniformBlockIndex, GLuint uniformBlockBinding) const +{ + if (!IsLinked()) { + mContext->ErrorInvalidOperation("getActiveUniformBlockName: `program` must be linked."); + return; + } + + const webgl::LinkedProgramInfo* linkInfo = LinkInfo(); + GLuint uniformBlockCount = (GLuint)linkInfo->uniformBlocks.size(); + if (uniformBlockIndex >= uniformBlockCount) { + mContext->ErrorInvalidValue("getActiveUniformBlockName: index %u invalid.", uniformBlockIndex); + return; + } + + if (uniformBlockBinding > mContext->mGLMaxUniformBufferBindings) { + mContext->ErrorInvalidEnum("getActiveUniformBlockName: binding %u invalid.", uniformBlockBinding); + return; + } + + gl::GLContext* gl = mContext->GL(); + gl->MakeCurrent(); + gl->fUniformBlockBinding(mGLName, uniformBlockIndex, uniformBlockBinding); +} + bool WebGLProgram::LinkProgram() { @@ -600,6 +831,15 @@ WebGLProgram::LinkProgram() mVertShader->BindAttribLocation(mGLName, name, index); } + if (!mTransformFeedbackVaryings.empty()) { + // Bind the transform feedback varyings. + // This can't be done trivially, because we have to deal with mapped names too. + mVertShader->ApplyTransformFeedbackVaryings(mGLName, + mTransformFeedbackVaryings, + mTransformFeedbackBufferMode, + &mTempMappedVaryings); + } + if (LinkAndUpdate()) return true; @@ -677,6 +917,11 @@ WebGLProgram::LinkAndUpdate() mLinkLog.SetLength(0); } + // Post link, temporary mapped varying names for transform feedback can be discarded. + // The memory can only be deleted after log is queried or the link status will fail. + std::vector empty; + empty.swap(mTempMappedVaryings); + GLint ok = 0; gl->fGetProgramiv(mGLName, LOCAL_GL_LINK_STATUS, &ok); if (!ok) @@ -715,6 +960,85 @@ WebGLProgram::FindUniformByMappedName(const nsACString& mappedName, return false; } +void +WebGLProgram::TransformFeedbackVaryings(const dom::Sequence& varyings, + GLenum bufferMode) +{ + if (bufferMode != LOCAL_GL_INTERLEAVED_ATTRIBS && + bufferMode != LOCAL_GL_SEPARATE_ATTRIBS) + { + mContext->ErrorInvalidEnum("transformFeedbackVaryings: `bufferMode` %s is " + "invalid. Must be one of gl.INTERLEAVED_ATTRIBS or " + "gl.SEPARATE_ATTRIBS.", + mContext->EnumName(bufferMode)); + return; + } + + size_t varyingsCount = varyings.Length(); + if (bufferMode == LOCAL_GL_SEPARATE_ATTRIBS && + varyingsCount >= mContext->mGLMaxTransformFeedbackSeparateAttribs) + { + mContext->ErrorInvalidValue("transformFeedbackVaryings: Number of `varyings` exc" + "eeds gl.MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS."); + return; + } + + std::vector asciiVaryings; + for (size_t i = 0; i < varyingsCount; i++) { + if (!ValidateGLSLVariableName(varyings[i], mContext, "transformFeedbackVaryings")) + return; + + NS_LossyConvertUTF16toASCII asciiName(varyings[i]); + asciiVaryings.push_back(asciiName); + } + + // All validated. Translate the strings and store them until + // program linking. + mTransformFeedbackBufferMode = bufferMode; + mTransformFeedbackVaryings.swap(asciiVaryings); +} + +already_AddRefed +WebGLProgram::GetTransformFeedbackVarying(GLuint index) +{ + // No docs in the WebGL 2 spec for this function. Taking the language for + // getActiveAttrib, which states that the function returns null on any error. + if (!IsLinked()) { + mContext->ErrorInvalidOperation("getTransformFeedbackVarying: `program` must be " + "linked."); + return nullptr; + } + + if (index >= mTransformFeedbackVaryings.size()) { + mContext->ErrorInvalidValue("getTransformFeedbackVarying: `index` is greater or " + "equal to TRANSFORM_FEEDBACK_VARYINGS."); + return nullptr; + } + + const nsCString& varyingUserName = mTransformFeedbackVaryings[index]; + + WebGLActiveInfo* info; + LinkInfo()->FindAttrib(varyingUserName, (const WebGLActiveInfo**) &info); + MOZ_ASSERT(info); + + nsRefPtr ret(info); + return ret.forget(); +} + +bool +WebGLProgram::FindUniformBlockByMappedName(const nsACString& mappedName, + nsCString* const out_userName, + bool* const out_isArray) const +{ + if (mVertShader->FindUniformBlockByMappedName(mappedName, out_userName, out_isArray)) + return true; + + if (mFragShader->FindUniformBlockByMappedName(mappedName, out_userName, out_isArray)) + return true; + + return false; +} + //////////////////////////////////////////////////////////////////////////////// JSObject* diff --git a/dom/canvas/WebGLProgram.h b/dom/canvas/WebGLProgram.h index 8a6c0a843c..05e2dd74fd 100644 --- a/dom/canvas/WebGLProgram.h +++ b/dom/canvas/WebGLProgram.h @@ -9,6 +9,7 @@ #include #include "mozilla/CheckedInt.h" #include "mozilla/LinkedList.h" +#include "mozilla/dom/WebGL2RenderingContextBinding.h" #include "nsString.h" #include "nsWrapperCache.h" #include @@ -24,6 +25,21 @@ class WebGLUniformLocation; namespace webgl { +struct UniformBlockInfo final + : public RefCounted +{ + MOZ_DECLARE_REFCOUNTED_TYPENAME(UniformBlockInfo); + + const nsCString mBaseUserName; + const nsCString mBaseMappedName; + + UniformBlockInfo(const nsACString& baseUserName, + const nsACString& baseMappedName) + : mBaseUserName(baseUserName) + , mBaseMappedName(baseMappedName) + {} +}; + struct LinkedProgramInfo final : public RefCounted , public SupportsWeakPtr @@ -41,6 +57,8 @@ struct LinkedProgramInfo final std::map uniformMap; std::map* fragDataMap; + std::vector> uniformBlocks; + // Needed for draw call validation. std::set activeAttribLocs; @@ -68,6 +86,20 @@ struct LinkedProgramInfo final return true; } + bool FindUniformBlock(const nsCString& baseUserName, + RefPtr* const out_info) const + { + const size_t count = uniformBlocks.size(); + for (size_t i = 0; i < count; i++) { + if (baseUserName == uniformBlocks[i]->mBaseUserName) { + *out_info = uniformBlocks[i].get(); + return true; + } + } + + return false; + } + bool FindFragData(const nsCString& baseUserName, nsCString* const out_baseMappedName) const { @@ -116,7 +148,16 @@ public: GLint GetFragDataLocation(const nsAString& name) const; void GetProgramInfoLog(nsAString* const out) const; JS::Value GetProgramParameter(GLenum pname) const; + GLuint GetUniformBlockIndex(const nsAString& name) const; + void GetActiveUniformBlockName(GLuint uniformBlockIndex, nsAString& name) const; + void GetActiveUniformBlockParam(GLuint uniformBlockIndex, GLenum pname, + Nullable& retval) const; + void GetActiveUniformBlockActiveUniforms(JSContext* cx, GLuint uniformBlockIndex, + Nullable& retval, + ErrorResult& rv) const; already_AddRefed GetUniformLocation(const nsAString& name) const; + void UniformBlockBinding(GLuint uniformBlockIndex, GLuint uniformBlockBinding) const; + bool LinkProgram(); bool UseProgram() const; void ValidateProgram() const; @@ -128,6 +169,13 @@ public: bool FindUniformByMappedName(const nsACString& mappedName, nsCString* const out_userName, bool* const out_isArray) const; + bool FindUniformBlockByMappedName(const nsACString& mappedName, + nsCString* const out_userName, + bool* const out_isArray) const; + + void TransformFeedbackVaryings(const dom::Sequence& varyings, + GLenum bufferMode); + already_AddRefed GetTransformFeedbackVarying(GLuint index); bool IsLinked() const { return mMostRecentLinkInfo; } @@ -155,8 +203,13 @@ private: WebGLRefPtr mVertShader; WebGLRefPtr mFragShader; std::map mBoundAttribLocs; + std::vector mTransformFeedbackVaryings; + GLenum mTransformFeedbackBufferMode; nsCString mLinkLog; RefPtr mMostRecentLinkInfo; + // Storage for transform feedback varyings before link. + // (Work around for bug seen on nVidia drivers.) + std::vector mTempMappedVaryings; }; } // namespace mozilla diff --git a/dom/canvas/WebGLQuery.cpp b/dom/canvas/WebGLQuery.cpp index afa2940d10..a17bd04163 100644 --- a/dom/canvas/WebGLQuery.cpp +++ b/dom/canvas/WebGLQuery.cpp @@ -40,10 +40,9 @@ WebGLQuery::Delete() bool WebGLQuery::IsActive() const { - WebGLRefPtr* targetSlot = mContext->GetQueryTargetSlot(mType); + WebGLRefPtr& targetSlot = mContext->GetQuerySlotByTarget(mType); - MOZ_ASSERT(targetSlot, "unknown query object's type"); - return targetSlot && *targetSlot == this; + return targetSlot.get() == this; } NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE_0(WebGLQuery) diff --git a/dom/canvas/WebGLShader.cpp b/dom/canvas/WebGLShader.cpp index fe3cb6eaea..a99c3fc316 100644 --- a/dom/canvas/WebGLShader.cpp +++ b/dom/canvas/WebGLShader.cpp @@ -92,6 +92,11 @@ TranslateWithoutValidation(const nsACString& sourceNS, bool isWebGL2, switch (glesslVersion) { case 100: + if (!versionStrLen) { + /* According to ARB_ES2_compatibility extension glsl + * should accept #version 100 for ES 2 shaders. */ + reversionedSource.insert(versionStrStart, "#version 100\n"); + } break; case 300: reversionedSource.insert(versionStrStart, "#version 330\n"); @@ -355,6 +360,53 @@ WebGLShader::FindUniformByMappedName(const nsACString& mappedName, return true; } +bool +WebGLShader::FindUniformBlockByMappedName(const nsACString& mappedName, + nsCString* const out_userName, + bool* const out_isArray) const +{ + // TODO: Extract block information from shader validator. + return false; +} + +void +WebGLShader::ApplyTransformFeedbackVaryings(GLuint prog, + const std::vector& varyings, + GLenum bufferMode, + std::vector* out_mappedVaryings) const +{ + MOZ_ASSERT(mType == LOCAL_GL_VERTEX_SHADER); + MOZ_ASSERT(!varyings.empty()); + MOZ_ASSERT(out_mappedVaryings); + + const size_t varyingsCount = varyings.size(); + std::vector mappedVaryings; + + for (size_t i = 0; i < varyingsCount; i++) { + const nsCString& userName = varyings[i]; + std::string userNameStr(userName.BeginReading()); + + const std::string* mappedNameStr = &userNameStr; + // TODO: Are vertex->fragment shader varyings listed under attribs? + if (mValidator) + mValidator->FindAttribMappedNameByUserName(userNameStr, &mappedNameStr); + + mappedVaryings.push_back(*mappedNameStr); + } + + // Temporary, tight packed array of string pointers into mappedVaryings. + std::vector strings; + strings.resize(varyingsCount); + for (size_t i = 0; i < varyingsCount; i++) { + strings[i] = mappedVaryings[i].c_str(); + } + + mContext->MakeContextCurrent(); + mContext->gl->fTransformFeedbackVaryings(prog, varyingsCount, &strings[0], bufferMode); + + out_mappedVaryings->swap(mappedVaryings); +} + //////////////////////////////////////////////////////////////////////////////// // Boilerplate diff --git a/dom/canvas/WebGLShader.h b/dom/canvas/WebGLShader.h index c3080978a3..d45c4c384a 100644 --- a/dom/canvas/WebGLShader.h +++ b/dom/canvas/WebGLShader.h @@ -52,11 +52,19 @@ public: bool FindUniformByMappedName(const nsACString& mappedName, nsCString* const out_userName, bool* const out_isArray) const; + bool FindUniformBlockByMappedName(const nsACString& mappedName, + nsCString* const out_userName, + bool* const out_isArray) const; bool IsCompiled() const { return mTranslationSuccessful && mCompilationSuccessful; } + void ApplyTransformFeedbackVaryings(GLuint prog, + const std::vector& varyings, + GLenum bufferMode, + std::vector* out_mappedVaryings) const; + // Other funcs size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const; void Delete(); diff --git a/dom/canvas/WebGLStrongTypes.h b/dom/canvas/WebGLStrongTypes.h index 41feaba4ae..10591e1a9f 100644 --- a/dom/canvas/WebGLStrongTypes.h +++ b/dom/canvas/WebGLStrongTypes.h @@ -445,9 +445,19 @@ STRONG_GLENUM_BEGIN(VAOBinding) STRONG_GLENUM_END(VAOBinding) STRONG_GLENUM_BEGIN(BufferBinding) - STRONG_GLENUM_VALUE(NONE), - STRONG_GLENUM_VALUE(ARRAY_BUFFER), - STRONG_GLENUM_VALUE(ELEMENT_ARRAY_BUFFER), + STRONG_GLENUM_VALUE(NONE), // 0x0000 + STRONG_GLENUM_VALUE(ARRAY_BUFFER), // 0x8892 + STRONG_GLENUM_VALUE(ELEMENT_ARRAY_BUFFER), // 0x8893 + STRONG_GLENUM_VALUE(PIXEL_PACK_BUFFER), // 0x88EB + STRONG_GLENUM_VALUE(PIXEL_UNPACK_BUFFER), // 0x88EC + STRONG_GLENUM_VALUE(UNIFORM_BUFFER), // 0x8A11 + STRONG_GLENUM_VALUE(TRANSFORM_FEEDBACK_BUFFER), // 0x8C8E STRONG_GLENUM_END(BufferBinding) +STRONG_GLENUM_BEGIN(QueryBinding) + STRONG_GLENUM_VALUE(NONE), + STRONG_GLENUM_VALUE(TIME_ELAPSED_EXT), + STRONG_GLENUM_VALUE(TIMESTAMP_EXT), +STRONG_GLENUM_END(QueryBinding) + #endif // WEBGL_STRONG_TYPES_H_ diff --git a/dom/canvas/WebGLSync.cpp b/dom/canvas/WebGLSync.cpp index 3701db3888..42dfb9f3c5 100644 --- a/dom/canvas/WebGLSync.cpp +++ b/dom/canvas/WebGLSync.cpp @@ -9,26 +9,30 @@ namespace mozilla { -WebGLSync::WebGLSync(WebGLContext* webgl): - WebGLContextBoundObject(webgl) +WebGLSync::WebGLSync(WebGLContext* webgl, GLenum condition, GLbitfield flags) + : WebGLContextBoundObject(webgl) { - MOZ_CRASH("Not Implemented."); + mGLName = mContext->gl->fFenceSync(condition, flags); } WebGLSync::~WebGLSync() -{} +{ + DeleteOnce(); +} void WebGLSync::Delete() { - MOZ_CRASH("Not Implemented."); + mContext->MakeContextCurrent(); + mContext->gl->fDeleteSync(mGLName); + mGLName = 0; + LinkedListElement::remove(); } WebGLContext* WebGLSync::GetParentObject() const { - MOZ_CRASH("Not Implemented."); - return nullptr; + return Context(); } // ------------------------------------------------------------------------- diff --git a/dom/canvas/WebGLSync.h b/dom/canvas/WebGLSync.h index 6abc1a19d7..7a5ab083b8 100644 --- a/dom/canvas/WebGLSync.h +++ b/dom/canvas/WebGLSync.h @@ -21,7 +21,7 @@ class WebGLSync final friend class WebGL2Context; public: - explicit WebGLSync(WebGLContext* webgl); + WebGLSync(WebGLContext* webgl, GLenum condition, GLbitfield flags); void Delete(); WebGLContext* GetParentObject() const; @@ -33,6 +33,8 @@ public: private: ~WebGLSync(); + + GLsync mGLName; }; } // namespace mozilla diff --git a/dom/canvas/WebGLTimerQuery.cpp b/dom/canvas/WebGLTimerQuery.cpp new file mode 100644 index 0000000000..e10fdfd495 --- /dev/null +++ b/dom/canvas/WebGLTimerQuery.cpp @@ -0,0 +1,62 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * 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/. */ + +#include "WebGLTimerQuery.h" + +#include "GLContext.h" +#include "mozilla/dom/WebGLRenderingContextBinding.h" +#include "nsContentUtils.h" +#include "WebGLContext.h" + +namespace mozilla { + +JSObject* +WebGLTimerQuery::WrapObject(JSContext* cx, JS::Handle aGivenProto) +{ + return dom::WebGLTimerQueryEXTBinding::Wrap(cx, this, aGivenProto); +} + +WebGLTimerQuery::WebGLTimerQuery(WebGLContext* webgl, GLuint aName) + : WebGLContextBoundObject(webgl) + , mGLName(aName) + , mTarget(LOCAL_GL_NONE) +{ +} + +WebGLTimerQuery::~WebGLTimerQuery() +{ + DeleteOnce(); +} + +WebGLTimerQuery* +WebGLTimerQuery::Create(WebGLContext* webgl) +{ + GLuint name = 0; + webgl->MakeContextCurrent(); + webgl->gl->fGenQueries(1, &name); + return new WebGLTimerQuery(webgl, name); +} + +void +WebGLTimerQuery::Delete() +{ + mContext->MakeContextCurrent(); + mContext->gl->fDeleteQueries(1, &mGLName); +} + +WebGLContext* +WebGLTimerQuery::GetParentObject() const +{ + return Context(); +} + + +NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE_0(WebGLTimerQuery) + +NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(WebGLTimerQuery, AddRef) +NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(WebGLTimerQuery, Release) + +} // namespace mozilla diff --git a/dom/canvas/WebGLTimerQuery.h b/dom/canvas/WebGLTimerQuery.h new file mode 100644 index 0000000000..9f6205e9e1 --- /dev/null +++ b/dom/canvas/WebGLTimerQuery.h @@ -0,0 +1,50 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * 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/. */ + +#ifndef WEBGL_TIMER_QUERY_H_ +#define WEBGL_TIMER_QUERY_H_ + +#include "GLConsts.h" +#include "nsWrapperCache.h" +#include "WebGLObjectModel.h" + +namespace mozilla { + +class WebGLTimerQuery final + : public nsWrapperCache + , public WebGLRefCountedObject + , public WebGLContextBoundObject +{ +public: + static WebGLTimerQuery* Create(WebGLContext* webgl); + + void Delete(); + + bool HasEverBeenBound() const { return mTarget != LOCAL_GL_NONE; } + GLenum Target() const { return mTarget; } + + WebGLContext* GetParentObject() const; + + // NS + virtual JSObject* WrapObject(JSContext* cx, JS::Handle aGivenProto) override; + + const GLenum mGLName; + + NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(WebGLTimerQuery) + NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_NATIVE_CLASS(WebGLTimerQuery) + +private: + explicit WebGLTimerQuery(WebGLContext* webgl, GLuint aName); + ~WebGLTimerQuery(); + + GLenum mTarget; + + friend class WebGLExtensionDisjointTimerQuery; +}; + +} // namespace mozilla + +#endif // WEBGL_TIMER_QUERY_H_ diff --git a/dom/canvas/WebGLTypes.h b/dom/canvas/WebGLTypes.h index 5e828776ff..c0aa29c722 100644 --- a/dom/canvas/WebGLTypes.h +++ b/dom/canvas/WebGLTypes.h @@ -151,6 +151,7 @@ enum class WebGLExtensionID : uint8_t { EXT_sRGB, EXT_shader_texture_lod, EXT_texture_filter_anisotropic, + EXT_disjoint_timer_query, OES_element_index_uint, OES_standard_derivatives, OES_texture_float, diff --git a/dom/canvas/WebGLUniformLocation.cpp b/dom/canvas/WebGLUniformLocation.cpp index 95cd5b3a2b..14f7e774e6 100644 --- a/dom/canvas/WebGLUniformLocation.cpp +++ b/dom/canvas/WebGLUniformLocation.cpp @@ -50,49 +50,67 @@ WebGLUniformLocation::ValidateForProgram(WebGLProgram* prog, WebGLContext* webgl static bool IsUniformSetterTypeValid(GLenum setterType, GLenum uniformType) { + // The order in this switch matches table 2.10 from OpenGL ES + // 3.0.4 (Aug 27, 2014) es_spec_3.0.4.pdf switch (uniformType) { - case LOCAL_GL_BOOL: - case LOCAL_GL_BOOL_VEC2: - case LOCAL_GL_BOOL_VEC3: - case LOCAL_GL_BOOL_VEC4: - return setterType == LOCAL_GL_INT || - setterType == LOCAL_GL_FLOAT; // GLfloat(0.0) sets a bool to false. - - case LOCAL_GL_INT: - case LOCAL_GL_INT_SAMPLER_2D: - case LOCAL_GL_INT_SAMPLER_2D_ARRAY: - case LOCAL_GL_INT_SAMPLER_3D: - case LOCAL_GL_INT_SAMPLER_CUBE: - case LOCAL_GL_INT_VEC2: - case LOCAL_GL_INT_VEC3: - case LOCAL_GL_INT_VEC4: - case LOCAL_GL_SAMPLER_2D: - case LOCAL_GL_SAMPLER_2D_ARRAY: - case LOCAL_GL_SAMPLER_2D_ARRAY_SHADOW: - case LOCAL_GL_SAMPLER_2D_SHADOW: - case LOCAL_GL_SAMPLER_CUBE: - case LOCAL_GL_SAMPLER_CUBE_SHADOW: - case LOCAL_GL_UNSIGNED_INT_SAMPLER_2D: - case LOCAL_GL_UNSIGNED_INT_SAMPLER_2D_ARRAY: - case LOCAL_GL_UNSIGNED_INT_SAMPLER_3D: - case LOCAL_GL_UNSIGNED_INT_SAMPLER_CUBE: - return setterType == LOCAL_GL_INT; - case LOCAL_GL_FLOAT: - case LOCAL_GL_FLOAT_MAT2: - case LOCAL_GL_FLOAT_MAT2x3: - case LOCAL_GL_FLOAT_MAT2x4: - case LOCAL_GL_FLOAT_MAT3: - case LOCAL_GL_FLOAT_MAT3x2: - case LOCAL_GL_FLOAT_MAT3x4: - case LOCAL_GL_FLOAT_MAT4: - case LOCAL_GL_FLOAT_MAT4x2: - case LOCAL_GL_FLOAT_MAT4x3: case LOCAL_GL_FLOAT_VEC2: case LOCAL_GL_FLOAT_VEC3: case LOCAL_GL_FLOAT_VEC4: return setterType == LOCAL_GL_FLOAT; + case LOCAL_GL_INT: + case LOCAL_GL_INT_VEC2: + case LOCAL_GL_INT_VEC3: + case LOCAL_GL_INT_VEC4: + return setterType == LOCAL_GL_INT; + + case LOCAL_GL_UNSIGNED_INT: + case LOCAL_GL_UNSIGNED_INT_VEC2: + case LOCAL_GL_UNSIGNED_INT_VEC3: + case LOCAL_GL_UNSIGNED_INT_VEC4: + return setterType == LOCAL_GL_UNSIGNED_INT; + + /* bool can be set via any function: 0, 0.0f -> FALSE, _ -> TRUE */ + case LOCAL_GL_BOOL: + case LOCAL_GL_BOOL_VEC2: + case LOCAL_GL_BOOL_VEC3: + case LOCAL_GL_BOOL_VEC4: + return (setterType == LOCAL_GL_INT || + setterType == LOCAL_GL_FLOAT || + setterType == LOCAL_GL_UNSIGNED_INT); + + case LOCAL_GL_FLOAT_MAT2: + case LOCAL_GL_FLOAT_MAT3: + case LOCAL_GL_FLOAT_MAT4: + case LOCAL_GL_FLOAT_MAT2x3: + case LOCAL_GL_FLOAT_MAT2x4: + case LOCAL_GL_FLOAT_MAT3x2: + case LOCAL_GL_FLOAT_MAT3x4: + case LOCAL_GL_FLOAT_MAT4x2: + case LOCAL_GL_FLOAT_MAT4x3: + return setterType == LOCAL_GL_FLOAT; + + /* Samplers can only be set via Uniform1i */ + case LOCAL_GL_SAMPLER_2D: + case LOCAL_GL_SAMPLER_3D: + case LOCAL_GL_SAMPLER_CUBE: + case LOCAL_GL_SAMPLER_2D_SHADOW: + case LOCAL_GL_SAMPLER_2D_ARRAY: + case LOCAL_GL_SAMPLER_2D_ARRAY_SHADOW: + case LOCAL_GL_SAMPLER_CUBE_SHADOW: + + case LOCAL_GL_INT_SAMPLER_2D: + case LOCAL_GL_INT_SAMPLER_3D: + case LOCAL_GL_INT_SAMPLER_CUBE: + case LOCAL_GL_INT_SAMPLER_2D_ARRAY: + + case LOCAL_GL_UNSIGNED_INT_SAMPLER_2D: + case LOCAL_GL_UNSIGNED_INT_SAMPLER_3D: + case LOCAL_GL_UNSIGNED_INT_SAMPLER_CUBE: + case LOCAL_GL_UNSIGNED_INT_SAMPLER_2D_ARRAY: + return setterType == LOCAL_GL_INT; + default: MOZ_CRASH("Bad `uniformType`."); } @@ -195,7 +213,20 @@ WebGLUniformLocation::GetUniform(JSContext* js, WebGLContext* webgl) const case LOCAL_GL_INT_VEC3: case LOCAL_GL_INT_VEC4: case LOCAL_GL_SAMPLER_2D: + case LOCAL_GL_SAMPLER_3D: case LOCAL_GL_SAMPLER_CUBE: + case LOCAL_GL_SAMPLER_2D_SHADOW: + case LOCAL_GL_SAMPLER_2D_ARRAY: + case LOCAL_GL_SAMPLER_2D_ARRAY_SHADOW: + case LOCAL_GL_SAMPLER_CUBE_SHADOW: + case LOCAL_GL_INT_SAMPLER_2D: + case LOCAL_GL_INT_SAMPLER_3D: + case LOCAL_GL_INT_SAMPLER_CUBE: + case LOCAL_GL_INT_SAMPLER_2D_ARRAY: + case LOCAL_GL_UNSIGNED_INT_SAMPLER_2D: + case LOCAL_GL_UNSIGNED_INT_SAMPLER_3D: + case LOCAL_GL_UNSIGNED_INT_SAMPLER_CUBE: + case LOCAL_GL_UNSIGNED_INT_SAMPLER_2D_ARRAY: { GLint buffer[kMaxElemSize] = {0}; gl->fGetUniformiv(prog, mLoc, buffer); @@ -242,6 +273,12 @@ WebGLUniformLocation::GetUniform(JSContext* js, WebGLContext* webgl) const case LOCAL_GL_FLOAT_MAT2: case LOCAL_GL_FLOAT_MAT3: case LOCAL_GL_FLOAT_MAT4: + case LOCAL_GL_FLOAT_MAT2x3: + case LOCAL_GL_FLOAT_MAT2x4: + case LOCAL_GL_FLOAT_MAT3x2: + case LOCAL_GL_FLOAT_MAT3x4: + case LOCAL_GL_FLOAT_MAT4x2: + case LOCAL_GL_FLOAT_MAT4x3: { GLfloat buffer[16] = {0.0f}; gl->fGetUniformfv(prog, mLoc, buffer); @@ -257,6 +294,25 @@ WebGLUniformLocation::GetUniform(JSContext* js, WebGLContext* webgl) const return JS::ObjectOrNullValue(obj); } + case LOCAL_GL_UNSIGNED_INT: + case LOCAL_GL_UNSIGNED_INT_VEC2: + case LOCAL_GL_UNSIGNED_INT_VEC3: + case LOCAL_GL_UNSIGNED_INT_VEC4: + { + GLuint buffer[kMaxElemSize] = {0}; + gl->fGetUniformuiv(prog, mLoc, buffer); + + if (elemSize == 1) + return JS::DoubleValue(buffer[0]); // This is Double because only Int32 is special cased. + + JSObject* obj = dom::Uint32Array::Create(js, webgl, elemSize, buffer); + if (!obj) { + webgl->ErrorOutOfMemory("getUniform: out of memory"); + return JS::NullValue(); + } + return JS::ObjectOrNullValue(obj); + } + default: MOZ_CRASH("Invalid elemType."); } diff --git a/dom/canvas/WebGLVertexArray.cpp b/dom/canvas/WebGLVertexArray.cpp index 4776322142..ab7abfd434 100644 --- a/dom/canvas/WebGLVertexArray.cpp +++ b/dom/canvas/WebGLVertexArray.cpp @@ -17,7 +17,7 @@ namespace mozilla { JSObject* WebGLVertexArray::WrapObject(JSContext* cx, JS::Handle aGivenProto) { - return dom::WebGLVertexArrayBinding::Wrap(cx, this, aGivenProto); + return dom::WebGLVertexArrayObjectOESBinding::Wrap(cx, this, aGivenProto); } WebGLVertexArray::WebGLVertexArray(WebGLContext* webgl) diff --git a/dom/canvas/moz.build b/dom/canvas/moz.build index 84ffa64e2d..628aaed3c8 100644 --- a/dom/canvas/moz.build +++ b/dom/canvas/moz.build @@ -63,6 +63,7 @@ UNIFIED_SOURCES += [ 'WebGL2ContextPrograms.cpp', 'WebGL2ContextQueries.cpp', 'WebGL2ContextSamplers.cpp', + 'WebGL2ContextState.cpp', 'WebGL2ContextSync.cpp', 'WebGL2ContextTextures.cpp', 'WebGL2ContextTransformFeedback.cpp', @@ -96,6 +97,7 @@ UNIFIED_SOURCES += [ 'WebGLExtensionDebugRendererInfo.cpp', 'WebGLExtensionDebugShaders.cpp', 'WebGLExtensionDepthTexture.cpp', + 'WebGLExtensionDisjointTimerQuery.cpp', 'WebGLExtensionDrawBuffers.cpp', 'WebGLExtensionElementIndexUint.cpp', 'WebGLExtensionFragDepth.cpp', @@ -123,6 +125,7 @@ UNIFIED_SOURCES += [ 'WebGLSync.cpp', 'WebGLTexelConversions.cpp', 'WebGLTexture.cpp', + 'WebGLTimerQuery.cpp', 'WebGLTransformFeedback.cpp', 'WebGLUniformLocation.cpp', 'WebGLValidateStrings.cpp', diff --git a/dom/canvas/test/webgl-mochitest.ini b/dom/canvas/test/webgl-mochitest.ini index becb141854..6324ccb167 100644 --- a/dom/canvas/test/webgl-mochitest.ini +++ b/dom/canvas/test/webgl-mochitest.ini @@ -29,6 +29,7 @@ skip-if = toolkit == 'android' #bug 865443- seperate suite - the non_conf* tests # We haven't cleaned up the Try results yet, but let's get this on the books first. [webgl-mochitest/test_webgl_conformance.html] skip-if = buildapp == 'mulet' || toolkit == 'android' #bug 865443- seperate suite - the non_conf* tests pass except for one on armv6 tests +[webgl-mochitest/test_webgl_disjoint_timer_query.html] [webgl-mochitest/test_webgl_request_context.html] skip-if = toolkit == 'android' #bug 865443- seperate suite - the non_conf* tests pass except for one on armv6 tests [webgl-mochitest/test_webgl_request_mismatch.html] diff --git a/dom/canvas/test/webgl-mochitest/test_webgl_disjoint_timer_query.html b/dom/canvas/test/webgl-mochitest/test_webgl_disjoint_timer_query.html new file mode 100644 index 0000000000..fc5a1a1094 --- /dev/null +++ b/dom/canvas/test/webgl-mochitest/test_webgl_disjoint_timer_query.html @@ -0,0 +1,65 @@ + + + + +WebGL test: Test EXT_disjoint_timer_query. + + + + + + + + + + diff --git a/dom/tests/mochitest/general/test_interfaces.html b/dom/tests/mochitest/general/test_interfaces.html index b88d8a4c98..d940d59d59 100644 --- a/dom/tests/mochitest/general/test_interfaces.html +++ b/dom/tests/mochitest/general/test_interfaces.html @@ -1343,8 +1343,6 @@ var interfaceNamesInGlobalScope = "WebGLTexture", // IMPORTANT: Do not change this list without review from a DOM peer! "WebGLUniformLocation", -// IMPORTANT: Do not change this list without review from a DOM peer! - "WebGLVertexArray", // IMPORTANT: Do not change this list without review from a DOM peer! "WebSocket", // IMPORTANT: Do not change this list without review from a DOM peer! diff --git a/dom/webidl/WebGL2RenderingContext.webidl b/dom/webidl/WebGL2RenderingContext.webidl index 91bc49799c..69c8de3bb9 100644 --- a/dom/webidl/WebGL2RenderingContext.webidl +++ b/dom/webidl/WebGL2RenderingContext.webidl @@ -8,7 +8,7 @@ */ typedef long long GLint64; // Should this be int64? -typedef unsigned long long GLuint64; // Should this be uint64? +typedef unsigned long long GLuint64; [Pref="webgl.enable-prototype-webgl2"] interface WebGLQuery { @@ -317,6 +317,9 @@ interface WebGL2RenderingContext : WebGLRenderingContext const GLint64 TIMEOUT_IGNORED = -1; + /* WebGL-specific enums */ + const GLenum MAX_CLIENT_WAIT_TIMEOUT_WEBGL = 0x9247; + /* Buffer objects */ void copyBufferSubData(GLenum readTarget, GLenum writeTarget, GLintptr readOffset, GLintptr writeOffset, GLsizeiptr size); @@ -377,9 +380,13 @@ interface WebGL2RenderingContext : WebGLRenderingContext void uniform2ui(WebGLUniformLocation? location, GLuint v0, GLuint v1); void uniform3ui(WebGLUniformLocation? location, GLuint v0, GLuint v1, GLuint v2); void uniform4ui(WebGLUniformLocation? location, GLuint v0, GLuint v1, GLuint v2, GLuint v3); + void uniform1uiv(WebGLUniformLocation? location, Uint32Array value); void uniform1uiv(WebGLUniformLocation? location, sequence value); + void uniform2uiv(WebGLUniformLocation? location, Uint32Array value); void uniform2uiv(WebGLUniformLocation? location, sequence value); + void uniform3uiv(WebGLUniformLocation? location, Uint32Array value); void uniform3uiv(WebGLUniformLocation? location, sequence value); + void uniform4uiv(WebGLUniformLocation? location, Uint32Array value); void uniform4uiv(WebGLUniformLocation? location, sequence value); void uniformMatrix2x3fv(WebGLUniformLocation? location, GLboolean transpose, Float32Array value); void uniformMatrix2x3fv(WebGLUniformLocation? location, GLboolean transpose, sequence value); diff --git a/dom/webidl/WebGLRenderingContext.webidl b/dom/webidl/WebGLRenderingContext.webidl index 043e65e645..1421a0020f 100644 --- a/dom/webidl/WebGLRenderingContext.webidl +++ b/dom/webidl/WebGLRenderingContext.webidl @@ -30,6 +30,7 @@ typedef unsigned short GLushort; typedef unsigned long GLuint; typedef unrestricted float GLfloat; typedef unrestricted float GLclampf; +typedef unsigned long long GLuint64EXT; dictionary WebGLContextAttributes { // boolean alpha = true; @@ -65,7 +66,8 @@ interface WebGLTexture { interface WebGLUniformLocation { }; -interface WebGLVertexArray { +[NoInterfaceObject] +interface WebGLVertexArrayObjectOES { }; interface WebGLActiveInfo { @@ -778,7 +780,7 @@ interface WebGLContextEvent : Event { // specific extension interfaces [NoInterfaceObject] -interface WebGLExtensionCompressedTextureS3TC +interface WEBGL_compressed_texture_s3tc { const GLenum COMPRESSED_RGB_S3TC_DXT1_EXT = 0x83F0; const GLenum COMPRESSED_RGBA_S3TC_DXT1_EXT = 0x83F1; @@ -787,7 +789,7 @@ interface WebGLExtensionCompressedTextureS3TC }; [NoInterfaceObject] -interface WebGLExtensionCompressedTextureATC +interface WEBGL_compressed_texture_atc { const GLenum COMPRESSED_RGB_ATC_WEBGL = 0x8C92; const GLenum COMPRESSED_RGBA_ATC_EXPLICIT_ALPHA_WEBGL = 0x8C93; @@ -795,13 +797,13 @@ interface WebGLExtensionCompressedTextureATC }; [NoInterfaceObject] -interface WebGLExtensionCompressedTextureETC1 +interface WEBGL_compressed_texture_etc1 { const GLenum COMPRESSED_RGB_ETC1_WEBGL = 0x8D64; }; [NoInterfaceObject] -interface WebGLExtensionCompressedTexturePVRTC +interface WEBGL_compressed_texture_pvrtc { const GLenum COMPRESSED_RGB_PVRTC_4BPPV1_IMG = 0x8C00; const GLenum COMPRESSED_RGB_PVRTC_2BPPV1_IMG = 0x8C01; @@ -810,49 +812,49 @@ interface WebGLExtensionCompressedTexturePVRTC }; [NoInterfaceObject] -interface WebGLExtensionDebugRendererInfo +interface WEBGL_debug_renderer_info { const GLenum UNMASKED_VENDOR_WEBGL = 0x9245; const GLenum UNMASKED_RENDERER_WEBGL = 0x9246; }; [NoInterfaceObject] -interface WebGLExtensionDebugShaders +interface WEBGL_debug_shaders { DOMString getTranslatedShaderSource(WebGLShader? shader); }; [NoInterfaceObject] -interface WebGLExtensionDepthTexture +interface WEBGL_depth_texture { const GLenum UNSIGNED_INT_24_8_WEBGL = 0x84FA; }; [NoInterfaceObject] -interface WebGLExtensionElementIndexUint +interface OES_element_index_uint { }; [NoInterfaceObject] -interface WebGLExtensionFragDepth +interface EXT_frag_depth { }; [NoInterfaceObject] -interface WebGLExtensionLoseContext { +interface WEBGL_lose_context { void loseContext(); void restoreContext(); }; [NoInterfaceObject] -interface WebGLExtensionTextureFilterAnisotropic +interface EXT_texture_filter_anisotropic { const GLenum TEXTURE_MAX_ANISOTROPY_EXT = 0x84FE; const GLenum MAX_TEXTURE_MAX_ANISOTROPY_EXT = 0x84FF; }; [NoInterfaceObject] -interface WebGLExtensionSRGB +interface EXT_sRGB { const GLenum SRGB_EXT = 0x8C40; const GLenum SRGB_ALPHA_EXT = 0x8C42; @@ -861,17 +863,17 @@ interface WebGLExtensionSRGB }; [NoInterfaceObject] -interface WebGLExtensionStandardDerivatives { +interface OES_standard_derivatives { const GLenum FRAGMENT_SHADER_DERIVATIVE_HINT_OES = 0x8B8B; }; [NoInterfaceObject] -interface WebGLExtensionTextureFloat +interface OES_texture_float { }; [NoInterfaceObject] -interface WebGLExtensionDrawBuffers { +interface WEBGL_draw_buffers { const GLenum COLOR_ATTACHMENT0_WEBGL = 0x8CE0; const GLenum COLOR_ATTACHMENT1_WEBGL = 0x8CE1; const GLenum COLOR_ATTACHMENT2_WEBGL = 0x8CE2; @@ -913,28 +915,28 @@ interface WebGLExtensionDrawBuffers { }; [NoInterfaceObject] -interface WebGLExtensionTextureFloatLinear +interface OES_texture_float_linear { }; [NoInterfaceObject] -interface WebGLExtensionShaderTextureLod +interface EXT_shader_texture_lod { }; [NoInterfaceObject] -interface WebGLExtensionTextureHalfFloat +interface OES_texture_half_float { const GLenum HALF_FLOAT_OES = 0x8D61; }; [NoInterfaceObject] -interface WebGLExtensionTextureHalfFloatLinear +interface OES_texture_half_float_linear { }; [NoInterfaceObject] -interface WebGLExtensionColorBufferFloat +interface WEBGL_color_buffer_float { const GLenum RGBA32F_EXT = 0x8814; const GLenum RGB32F_EXT = 0x8815; @@ -943,7 +945,7 @@ interface WebGLExtensionColorBufferFloat }; [NoInterfaceObject] -interface WebGLExtensionColorBufferHalfFloat +interface EXT_color_buffer_half_float { const GLenum RGBA16F_EXT = 0x881A; const GLenum RGB16F_EXT = 0x881B; @@ -952,17 +954,17 @@ interface WebGLExtensionColorBufferHalfFloat }; [NoInterfaceObject] -interface WebGLExtensionVertexArray { +interface OES_vertex_array_object { const GLenum VERTEX_ARRAY_BINDING_OES = 0x85B5; - WebGLVertexArray? createVertexArrayOES(); - void deleteVertexArrayOES(WebGLVertexArray? arrayObject); - [WebGLHandlesContextLoss] GLboolean isVertexArrayOES(WebGLVertexArray? arrayObject); - void bindVertexArrayOES(WebGLVertexArray? arrayObject); + WebGLVertexArrayObjectOES? createVertexArrayOES(); + void deleteVertexArrayOES(WebGLVertexArrayObjectOES? arrayObject); + [WebGLHandlesContextLoss] GLboolean isVertexArrayOES(WebGLVertexArrayObjectOES? arrayObject); + void bindVertexArrayOES(WebGLVertexArrayObjectOES? arrayObject); }; [NoInterfaceObject] -interface WebGLExtensionInstancedArrays { +interface ANGLE_instanced_arrays { const GLenum VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE = 0x88FE; void drawArraysInstancedANGLE(GLenum mode, GLint first, GLsizei count, GLsizei primcount); @@ -971,7 +973,31 @@ interface WebGLExtensionInstancedArrays { }; [NoInterfaceObject] -interface WebGLExtensionBlendMinMax { +interface EXT_blend_minmax { const GLenum MIN_EXT = 0x8007; const GLenum MAX_EXT = 0x8008; }; + +[NoInterfaceObject] +interface WebGLTimerQueryEXT { +}; + +[NoInterfaceObject] +interface EXT_disjoint_timer_query { + const GLenum QUERY_COUNTER_BITS_EXT = 0x8864; + const GLenum CURRENT_QUERY_EXT = 0x8865; + const GLenum QUERY_RESULT_EXT = 0x8866; + const GLenum QUERY_RESULT_AVAILABLE_EXT = 0x8867; + const GLenum TIME_ELAPSED_EXT = 0x88BF; + const GLenum TIMESTAMP_EXT = 0x8E28; + const GLenum GPU_DISJOINT_EXT = 0x8FBB; + + WebGLTimerQueryEXT? createQueryEXT(); + void deleteQueryEXT(WebGLTimerQueryEXT? query); + [WebGLHandlesContextLoss] boolean isQueryEXT(WebGLTimerQueryEXT? query); + void beginQueryEXT(GLenum target, WebGLTimerQueryEXT? query); + void endQueryEXT(GLenum target); + void queryCounterEXT(WebGLTimerQueryEXT? query, GLenum target); + any getQueryEXT(GLenum target, GLenum pname); + any getQueryObjectEXT(WebGLTimerQueryEXT? query, GLenum pname); +}; diff --git a/gfx/gl/GLConsts.h b/gfx/gl/GLConsts.h index c2830deb77..fb43c745af 100644 --- a/gfx/gl/GLConsts.h +++ b/gfx/gl/GLConsts.h @@ -283,7 +283,6 @@ #define LOCAL_GL_BOOL_VEC4_ARB 0x8B59 #define LOCAL_GL_BOUNDING_BOX_NV 0x908D #define LOCAL_GL_BOUNDING_BOX_OF_BOUNDING_BOXES_NV 0x909C -#define LOCAL_GL_BROWSER_DEFAULT_WEBGL 0x9244 #define LOCAL_GL_BUFFER 0x82E0 #define LOCAL_GL_BUFFER_ACCESS 0x88BB #define LOCAL_GL_BUFFER_ACCESS_ARB 0x88BB @@ -731,7 +730,6 @@ #define LOCAL_GL_CONTEXT_FLAG_DEBUG_BIT_KHR 0x00000002 #define LOCAL_GL_CONTEXT_FLAG_FORWARD_COMPATIBLE_BIT 0x00000001 #define LOCAL_GL_CONTEXT_FLAG_ROBUST_ACCESS_BIT_ARB 0x00000004 -#define LOCAL_GL_CONTEXT_LOST_WEBGL 0x9242 #define LOCAL_GL_CONTEXT_PROFILE_MASK 0x9126 #define LOCAL_GL_CONTEXT_ROBUST_ACCESS_EXT 0x90F3 #define LOCAL_GL_CONTINUOUS_AMD 0x9007 @@ -4680,19 +4678,16 @@ #define LOCAL_GL_UNPACK_ALIGNMENT 0x0CF5 #define LOCAL_GL_UNPACK_CLIENT_STORAGE_APPLE 0x85B2 #define LOCAL_GL_UNPACK_CMYK_HINT_EXT 0x800F -#define LOCAL_GL_UNPACK_COLORSPACE_CONVERSION_WEBGL 0x9243 #define LOCAL_GL_UNPACK_COMPRESSED_BLOCK_DEPTH 0x9129 #define LOCAL_GL_UNPACK_COMPRESSED_BLOCK_HEIGHT 0x9128 #define LOCAL_GL_UNPACK_COMPRESSED_BLOCK_SIZE 0x912A #define LOCAL_GL_UNPACK_COMPRESSED_BLOCK_WIDTH 0x9127 #define LOCAL_GL_UNPACK_COMPRESSED_SIZE_SGIX 0x831A #define LOCAL_GL_UNPACK_CONSTANT_DATA_SUNX 0x81D5 -#define LOCAL_GL_UNPACK_FLIP_Y_WEBGL 0x9240 #define LOCAL_GL_UNPACK_IMAGE_DEPTH_SGIS 0x8133 #define LOCAL_GL_UNPACK_IMAGE_HEIGHT 0x806E #define LOCAL_GL_UNPACK_IMAGE_HEIGHT_EXT 0x806E #define LOCAL_GL_UNPACK_LSB_FIRST 0x0CF1 -#define LOCAL_GL_UNPACK_PREMULTIPLY_ALPHA_WEBGL 0x9241 #define LOCAL_GL_UNPACK_RESAMPLE_OML 0x8985 #define LOCAL_GL_UNPACK_RESAMPLE_SGIX 0x842D #define LOCAL_GL_UNPACK_ROW_BYTES_APPLE 0x8A16 diff --git a/gfx/gl/GLContext.cpp b/gfx/gl/GLContext.cpp index 1bc41e09b4..a54aac38d5 100644 --- a/gfx/gl/GLContext.cpp +++ b/gfx/gl/GLContext.cpp @@ -69,6 +69,7 @@ static const char *sExtensionNames[] = { "GL_ANGLE_instanced_arrays", "GL_ANGLE_texture_compression_dxt3", "GL_ANGLE_texture_compression_dxt5", + "GL_ANGLE_timer_query", "GL_APPLE_client_storage", "GL_APPLE_texture_range", "GL_APPLE_vertex_array_object", @@ -95,6 +96,8 @@ static const char *sExtensionNames[] = { "GL_ARB_texture_non_power_of_two", "GL_ARB_texture_rectangle", "GL_ARB_texture_storage", + "GL_ARB_texture_swizzle", + "GL_ARB_timer_query", "GL_ARB_transform_feedback2", "GL_ARB_uniform_buffer_object", "GL_ARB_vertex_array_object", @@ -103,6 +106,7 @@ static const char *sExtensionNames[] = { "GL_EXT_color_buffer_float", "GL_EXT_color_buffer_half_float", "GL_EXT_copy_texture", + "GL_EXT_disjoint_timer_query", "GL_EXT_draw_buffers", "GL_EXT_draw_buffers2", "GL_EXT_draw_instanced", @@ -118,6 +122,7 @@ static const char *sExtensionNames[] = { "GL_EXT_read_format_bgra", "GL_EXT_robustness", "GL_EXT_sRGB", + "GL_EXT_sRGB_write_control", "GL_EXT_shader_texture_lod", "GL_EXT_texture3D", "GL_EXT_texture_compression_dxt1", @@ -126,6 +131,7 @@ static const char *sExtensionNames[] = { "GL_EXT_texture_format_BGRA8888", "GL_EXT_texture_sRGB", "GL_EXT_texture_storage", + "GL_EXT_timer_query", "GL_EXT_transform_feedback", "GL_EXT_unpack_subimage", "GL_IMG_read_format", @@ -784,7 +790,7 @@ GLContext::InitWithPrefix(const char *prefix, bool trygl) } } - if (IsExtensionSupported(ARB_sync)) { + if (IsSupported(GLFeature::sync)) { SymLoadStruct syncSymbols[] = { { (PRFuncPtr*) &mSymbols.fFenceSync, { "FenceSync", nullptr } }, { (PRFuncPtr*) &mSymbols.fIsSync, { "IsSync", nullptr } }, @@ -797,7 +803,7 @@ GLContext::InitWithPrefix(const char *prefix, bool trygl) }; if (!LoadSymbols(&syncSymbols[0], trygl, prefix)) { - NS_ERROR("GL supports ARB_sync without supplying its functions."); + NS_ERROR("GL supports sync without supplying its functions."); MarkExtensionUnsupported(ARB_sync); ClearSymbols(syncSymbols); @@ -1037,6 +1043,26 @@ GLContext::InitWithPrefix(const char *prefix, bool trygl) } } + if (IsSupported(GLFeature::query_counter)) { + SymLoadStruct coreSymbols[] = { + { (PRFuncPtr*) &mSymbols.fQueryCounter, { "QueryCounter", nullptr } }, + END_SYMBOLS + }; + SymLoadStruct extSymbols[] = { + { (PRFuncPtr*) &mSymbols.fQueryCounter, { "QueryCounterEXT", "QueryCounterANGLE", nullptr } }, + END_SYMBOLS + }; + + bool useCore = IsFeatureProvidedByCoreSymbols(GLFeature::query_counter); + + if (!LoadSymbols(useCore ? coreSymbols : extSymbols, trygl, prefix)) { + NS_ERROR("GL supports query counters without supplying its functions."); + + MarkUnsupported(GLFeature::query_counter); + ClearSymbols(coreSymbols); + } + } + if (IsSupported(GLFeature::query_objects)) { SymLoadStruct coreSymbols[] = { { (PRFuncPtr*) &mSymbols.fBeginQuery, { "BeginQuery", nullptr } }, @@ -1050,13 +1076,13 @@ GLContext::InitWithPrefix(const char *prefix, bool trygl) }; SymLoadStruct extSymbols[] = { - { (PRFuncPtr*) &mSymbols.fBeginQuery, { "BeginQueryEXT", nullptr } }, - { (PRFuncPtr*) &mSymbols.fGenQueries, { "GenQueriesEXT", nullptr } }, - { (PRFuncPtr*) &mSymbols.fDeleteQueries, { "DeleteQueriesEXT", nullptr } }, - { (PRFuncPtr*) &mSymbols.fEndQuery, { "EndQueryEXT", nullptr } }, - { (PRFuncPtr*) &mSymbols.fGetQueryiv, { "GetQueryivEXT", nullptr } }, - { (PRFuncPtr*) &mSymbols.fGetQueryObjectuiv, { "GetQueryObjectuivEXT", nullptr } }, - { (PRFuncPtr*) &mSymbols.fIsQuery, { "IsQueryEXT", nullptr } }, + { (PRFuncPtr*) &mSymbols.fBeginQuery, { "BeginQueryEXT", "BeginQueryANGLE", nullptr } }, + { (PRFuncPtr*) &mSymbols.fGenQueries, { "GenQueriesEXT", "GenQueriesANGLE", nullptr } }, + { (PRFuncPtr*) &mSymbols.fDeleteQueries, { "DeleteQueriesEXT", "DeleteQueriesANGLE", nullptr } }, + { (PRFuncPtr*) &mSymbols.fEndQuery, { "EndQueryEXT", "EndQueryANGLE", nullptr } }, + { (PRFuncPtr*) &mSymbols.fGetQueryiv, { "GetQueryivEXT", "GetQueryivANGLE", nullptr } }, + { (PRFuncPtr*) &mSymbols.fGetQueryObjectuiv, { "GetQueryObjectuivEXT", "GetQueryObjectuivANGLE", nullptr } }, + { (PRFuncPtr*) &mSymbols.fIsQuery, { "IsQueryEXT", "IsQueryANGLE", nullptr } }, END_SYMBOLS }; @@ -1066,6 +1092,7 @@ GLContext::InitWithPrefix(const char *prefix, bool trygl) NS_ERROR("GL supports query objects without supplying its functions."); MarkUnsupported(GLFeature::query_objects); + MarkUnsupported(GLFeature::get_query_object_i64v); MarkUnsupported(GLFeature::get_query_object_iv); MarkUnsupported(GLFeature::occlusion_query); MarkUnsupported(GLFeature::occlusion_query_boolean); @@ -1074,6 +1101,29 @@ GLContext::InitWithPrefix(const char *prefix, bool trygl) } } + if (IsSupported(GLFeature::get_query_object_i64v)) { + SymLoadStruct coreSymbols[] = { + { (PRFuncPtr*) &mSymbols.fGetQueryObjecti64v, { "GetQueryObjecti64v", nullptr } }, + { (PRFuncPtr*) &mSymbols.fGetQueryObjectui64v, { "GetQueryObjectui64v", nullptr } }, + END_SYMBOLS + }; + + SymLoadStruct extSymbols[] = { + { (PRFuncPtr*) &mSymbols.fGetQueryObjecti64v, { "GetQueryObjecti64vEXT", "GetQueryObjecti64vANGLE", nullptr } }, + { (PRFuncPtr*) &mSymbols.fGetQueryObjectui64v, { "GetQueryObjectui64vEXT", "GetQueryObjectui64vANGLE", nullptr } }, + END_SYMBOLS + }; + + bool useCore = IsFeatureProvidedByCoreSymbols(GLFeature::get_query_object_i64v); + if (!LoadSymbols(useCore ? coreSymbols : extSymbols, trygl, prefix)) { + NS_ERROR("GL supports 64 bit query object getters without supplying its functions."); + + MarkUnsupported(GLFeature::get_query_object_i64v); + MarkUnsupported(GLFeature::query_counter); + ClearSymbols(coreSymbols); + } + } + if (IsSupported(GLFeature::get_query_object_iv)) { SymLoadStruct coreSymbols[] = { { (PRFuncPtr*) &mSymbols.fGetQueryObjectiv, { "GetQueryObjectiv", nullptr } }, @@ -1081,7 +1131,7 @@ GLContext::InitWithPrefix(const char *prefix, bool trygl) }; SymLoadStruct extSymbols[] = { - { (PRFuncPtr*) &mSymbols.fGetQueryObjectiv, { "GetQueryObjectivEXT", nullptr } }, + { (PRFuncPtr*) &mSymbols.fGetQueryObjectiv, { "GetQueryObjectivEXT", "GetQueryObjectivANGLE", nullptr } }, END_SYMBOLS }; @@ -1219,6 +1269,7 @@ GLContext::InitWithPrefix(const char *prefix, bool trygl) { (PRFuncPtr*) &mSymbols.fUniform3uiv, { "Uniform3uiv", "Uniform3uivEXT", nullptr } }, { (PRFuncPtr*) &mSymbols.fUniform4uiv, { "Uniform4uiv", "Uniform4uivEXT", nullptr } }, { (PRFuncPtr*) &mSymbols.fGetFragDataLocation, { "GetFragDataLocation", "GetFragDataLocationEXT", nullptr } }, + { (PRFuncPtr*) &mSymbols.fGetUniformuiv, { "GetUniformuiv", "GetUniformuivEXT", nullptr } }, END_SYMBOLS }; diff --git a/gfx/gl/GLContext.h b/gfx/gl/GLContext.h index fee55db6a9..c76cb1f487 100644 --- a/gfx/gl/GLContext.h +++ b/gfx/gl/GLContext.h @@ -99,6 +99,7 @@ enum class GLFeature { framebuffer_object, get_integer_indexed, get_integer64_indexed, + get_query_object_i64v, get_query_object_iv, get_string_indexed, gpu_shader4, @@ -110,14 +111,18 @@ enum class GLFeature { occlusion_query_boolean, occlusion_query2, packed_depth_stencil, + query_counter, query_objects, + query_time_elapsed, read_buffer, renderbuffer_color_float, renderbuffer_color_half_float, robustness, - sRGB, + sRGB_framebuffer, + sRGB_texture, sampler_objects, standard_derivatives, + sync, texture_3D, texture_3D_compressed, texture_3D_copy, @@ -127,6 +132,7 @@ enum class GLFeature { texture_half_float_linear, texture_non_power_of_two, texture_storage, + texture_swizzle, transform_feedback2, uniform_buffer_object, uniform_matrix_nonsquare, @@ -362,6 +368,7 @@ public: ANGLE_instanced_arrays, ANGLE_texture_compression_dxt3, ANGLE_texture_compression_dxt5, + ANGLE_timer_query, APPLE_client_storage, APPLE_texture_range, APPLE_vertex_array_object, @@ -388,6 +395,8 @@ public: ARB_texture_non_power_of_two, ARB_texture_rectangle, ARB_texture_storage, + ARB_texture_swizzle, + ARB_timer_query, ARB_transform_feedback2, ARB_uniform_buffer_object, ARB_vertex_array_object, @@ -396,6 +405,7 @@ public: EXT_color_buffer_float, EXT_color_buffer_half_float, EXT_copy_texture, + EXT_disjoint_timer_query, EXT_draw_buffers, EXT_draw_buffers2, EXT_draw_instanced, @@ -411,6 +421,7 @@ public: EXT_read_format_bgra, EXT_robustness, EXT_sRGB, + EXT_sRGB_write_control, EXT_shader_texture_lod, EXT_texture3D, EXT_texture_compression_dxt1, @@ -419,6 +430,7 @@ public: EXT_texture_format_BGRA8888, EXT_texture_sRGB, EXT_texture_storage, + EXT_timer_query, EXT_transform_feedback, EXT_unpack_subimage, IMG_read_format, @@ -1407,6 +1419,13 @@ public: AFTER_GL_CALL; } + void fGetUniformuiv(GLuint program, GLint location, GLuint* params) { + BEFORE_GL_CALL; + ASSERT_SYMBOL_PRESENT(fGetUniformuiv); + mSymbols.fGetUniformuiv(program, location, params); + AFTER_GL_CALL; + } + GLint fGetUniformLocation (GLint programObj, const GLchar* name) { BEFORE_GL_CALL; GLint retval = mSymbols.fGetUniformLocation(programObj, name); @@ -2595,6 +2614,22 @@ public: AFTER_GL_CALL; } +// ----------------------------------------------------------------------------- +// Package XXX_query_counter +/** + * XXX_query_counter: + * - depends on XXX_query_objects + * - provide all followed entry points + * - provide GL_TIMESTAMP + */ +public: + void fQueryCounter(GLuint id, GLenum target) { + BEFORE_GL_CALL; + ASSERT_SYMBOL_PRESENT(fQueryCounter); + mSymbols.fQueryCounter(id, target); + AFTER_GL_CALL; + } + // ----------------------------------------------------------------------------- // Package XXX_query_objects @@ -2649,6 +2684,28 @@ public: return retval; } +// ----------------------------------------------------------------------------- +// Package XXX_get_query_object_i64v +/** + * XXX_get_query_object_i64v: + * - depends on XXX_query_objects + * - provide the followed entry point + */ +public: + void fGetQueryObjecti64v(GLuint id, GLenum pname, GLint64* params) { + BEFORE_GL_CALL; + ASSERT_SYMBOL_PRESENT(fGetQueryObjecti64v); + mSymbols.fGetQueryObjecti64v(id, pname, params); + AFTER_GL_CALL; + } + + void fGetQueryObjectui64v(GLuint id, GLenum pname, GLuint64* params) { + BEFORE_GL_CALL; + ASSERT_SYMBOL_PRESENT(fGetQueryObjectui64v); + mSymbols.fGetQueryObjectui64v(id, pname, params); + AFTER_GL_CALL; + } + // ----------------------------------------------------------------------------- // Package XXX_get_query_object_iv diff --git a/gfx/gl/GLContextFeatures.cpp b/gfx/gl/GLContextFeatures.cpp index 57e526bd2a..fefba7e388 100644 --- a/gfx/gl/GLContextFeatures.cpp +++ b/gfx/gl/GLContextFeatures.cpp @@ -3,7 +3,6 @@ * 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/. */ - #include "GLContext.h" #include "nsPrintfCString.h" @@ -261,6 +260,18 @@ static const FeatureInfo sFeatureInfoArr[] = { GLContext::Extensions_End } }, + { + "get_query_object_i64v", + GLVersion::GL3_3, + GLESVersion::NONE, + GLContext::ARB_timer_query, + { + GLContext::ANGLE_timer_query, + GLContext::EXT_disjoint_timer_query, + GLContext::EXT_timer_query, + GLContext::Extensions_End + } + }, { "get_query_object_iv", GLVersion::GL2, @@ -393,21 +404,48 @@ static const FeatureInfo sFeatureInfoArr[] = { GLContext::Extensions_End } }, + { + "query_counter", + GLVersion::GL3_3, + GLESVersion::NONE, + GLContext::ARB_timer_query, + { + GLContext::ANGLE_timer_query, + GLContext::EXT_disjoint_timer_query, + // EXT_timer_query does NOT support GL_TIMESTAMP retrieval with + // QueryCounter. + GLContext::Extensions_End + } + }, { "query_objects", GLVersion::GL2, GLESVersion::ES3, GLContext::Extension_None, { + GLContext::ANGLE_timer_query, + GLContext::EXT_disjoint_timer_query, GLContext::EXT_occlusion_query_boolean, GLContext::Extensions_End } /* * XXX_query_objects only provide entry points commonly supported by - * ARB_occlusion_query (added in OpenGL 2.0) and EXT_occlusion_query_boolean - * (added in OpenGL ES 3.0) + * ARB_occlusion_query (added in OpenGL 2.0), EXT_occlusion_query_boolean + * (added in OpenGL ES 3.0), and ARB_timer_query (added in OpenGL 3.3) */ }, + { + "query_time_elapsed", + GLVersion::GL3_3, + GLESVersion::NONE, + GLContext::ARB_timer_query, + { + GLContext::ANGLE_timer_query, + GLContext::EXT_disjoint_timer_query, + GLContext::EXT_timer_query, + GLContext::Extensions_End + } + }, { "read_buffer", GLVersion::GL2, @@ -451,12 +489,24 @@ static const FeatureInfo sFeatureInfoArr[] = { } }, { - "sRGB", + "sRGB_framebuffer", GLVersion::GL3, GLESVersion::ES3, + GLContext::ARB_framebuffer_sRGB, + { + GLContext::EXT_framebuffer_sRGB, + GLContext::EXT_sRGB_write_control, + GLContext::Extensions_End + } + }, + { + "sRGB_texture", + GLVersion::GL2_1, + GLESVersion::ES3, GLContext::Extension_None, { GLContext::EXT_sRGB, + GLContext::EXT_texture_sRGB, GLContext::Extensions_End } }, @@ -479,6 +529,15 @@ static const FeatureInfo sFeatureInfoArr[] = { GLContext::Extensions_End } }, + { + "sync", + GLVersion::GL3_2, + GLESVersion::ES3, + GLContext::ARB_sync, + { + GLContext::Extensions_End + } + }, { "texture_3D", GLVersion::GL1_2, @@ -592,6 +651,15 @@ static const FeatureInfo sFeatureInfoArr[] = { GLContext::Extensions_End } }, + { + "texture_swizzle", + GLVersion::GL3_3, + GLESVersion::ES3, + GLContext::ARB_texture_swizzle, + { + GLContext::Extensions_End + } + }, { "transform_feedback2", GLVersion::GL4, @@ -653,11 +721,10 @@ ProfileVersionForFeature(GLFeature feature, ContextProfile profile) const FeatureInfo& featureInfo = GetFeatureInfo(feature); - if (profile == ContextProfile::OpenGLES) { - return (uint32_t) featureInfo.mOpenGLESVersion; - } + if (profile == ContextProfile::OpenGLES) + return (uint32_t)featureInfo.mOpenGLESVersion; - return (uint32_t) featureInfo.mOpenGLVersion; + return (uint32_t)featureInfo.mOpenGLVersion; } bool @@ -691,72 +758,49 @@ GLContext::GetFeatureName(GLFeature feature) return GetFeatureInfo(feature).mName; } -static bool -CanReadSRGBFromFBOTexture(GLContext* gl) -{ - if (!gl->WorkAroundDriverBugs()) - return true; - -#ifdef XP_MACOSX - // Bug 843668: - // MacOSX 10.6 reports to support EXT_framebuffer_sRGB and - // EXT_texture_sRGB but fails to convert from sRGB to linear - // when writing to an sRGB texture attached to an FBO. - if (!nsCocoaFeatures::OnLionOrLater()) { - return false; - } -#endif // XP_MACOSX - return true; -} - void GLContext::InitFeatures() { - for (size_t feature_index = 0; feature_index < size_t(GLFeature::EnumMax); feature_index++) - { - GLFeature feature = GLFeature(feature_index); + for (size_t featureId = 0; featureId < size_t(GLFeature::EnumMax); featureId++) { + GLFeature feature = GLFeature(featureId); if (IsFeaturePartOfProfileVersion(feature, mProfile, mVersion)) { - mAvailableFeatures[feature_index] = true; + mAvailableFeatures[featureId] = true; continue; } - mAvailableFeatures[feature_index] = false; + mAvailableFeatures[featureId] = false; const FeatureInfo& featureInfo = GetFeatureInfo(feature); - if (IsExtensionSupported(featureInfo.mARBExtensionWithoutARBSuffix)) - { - mAvailableFeatures[feature_index] = true; + if (IsExtensionSupported(featureInfo.mARBExtensionWithoutARBSuffix)) { + mAvailableFeatures[featureId] = true; continue; } - for (size_t j = 0; true; j++) - { - MOZ_ASSERT(j < kMAX_EXTENSION_GROUP_SIZE, "kMAX_EXTENSION_GROUP_SIZE too small"); + for (size_t j = 0; true; j++) { + MOZ_ASSERT(j < kMAX_EXTENSION_GROUP_SIZE, + "kMAX_EXTENSION_GROUP_SIZE too small"); - if (featureInfo.mExtensions[j] == GLContext::Extensions_End) { + if (featureInfo.mExtensions[j] == GLContext::Extensions_End) break; - } if (IsExtensionSupported(featureInfo.mExtensions[j])) { - mAvailableFeatures[feature_index] = true; + mAvailableFeatures[featureId] = true; break; } } } - // Bug 843668: Work around limitation of the feature system. - // For sRGB support under OpenGL to match OpenGL ES spec, check for both - // EXT_texture_sRGB and EXT_framebuffer_sRGB is required. - const bool aresRGBExtensionsAvailable = - IsExtensionSupported(EXT_texture_sRGB) && - (IsExtensionSupported(ARB_framebuffer_sRGB) || - IsExtensionSupported(EXT_framebuffer_sRGB)); - - mAvailableFeatures[size_t(GLFeature::sRGB)] = - aresRGBExtensionsAvailable && - CanReadSRGBFromFBOTexture(this); + if (WorkAroundDriverBugs()) { +#ifdef XP_MACOSX + // MacOSX 10.6 reports to support EXT_framebuffer_sRGB and EXT_texture_sRGB but + // fails to convert from sRGB to linear when reading from an sRGB texture attached + // to an FBO. (bug 843668) + if (!nsCocoaFeatures::OnLionOrLater()) + MarkUnsupported(GLFeature::sRGB_framebuffer); +#endif // XP_MACOSX + } } void @@ -766,20 +810,19 @@ GLContext::MarkUnsupported(GLFeature feature) const FeatureInfo& featureInfo = GetFeatureInfo(feature); - for (size_t i = 0; true; i++) - { + for (size_t i = 0; true; i++) { MOZ_ASSERT(i < kMAX_EXTENSION_GROUP_SIZE, "kMAX_EXTENSION_GROUP_SIZE too small"); - if (featureInfo.mExtensions[i] == GLContext::Extensions_End) { + if (featureInfo.mExtensions[i] == GLContext::Extensions_End) break; - } MarkExtensionUnsupported(featureInfo.mExtensions[i]); } MOZ_ASSERT(!IsSupported(feature), "GLContext::MarkUnsupported has failed!"); - NS_WARNING(nsPrintfCString("%s marked as unsupported", GetFeatureName(feature)).get()); + NS_WARNING(nsPrintfCString("%s marked as unsupported", + GetFeatureName(feature)).get()); } } /* namespace gl */ diff --git a/gfx/gl/GLContextSymbols.h b/gfx/gl/GLContextSymbols.h index 5579358153..8606a2686d 100644 --- a/gfx/gl/GLContextSymbols.h +++ b/gfx/gl/GLContextSymbols.h @@ -145,6 +145,12 @@ struct GLContextSymbols PFNGLGETQUERYOBJECTIVPROC fGetQueryObjectiv; typedef void (GLAPIENTRY * PFNGLGETQUERYOBJECTUIVPROC) (GLuint id, GLenum pname, GLuint* params); PFNGLGETQUERYOBJECTUIVPROC fGetQueryObjectuiv; + typedef void (GLAPIENTRY * PFNGLGETQUERYOBJECTI64VPROC) (GLuint id, GLenum pname, GLint64* params); + PFNGLGETQUERYOBJECTI64VPROC fGetQueryObjecti64v; + typedef void (GLAPIENTRY * PFNGLGETQUERYOBJECTUI64VPROC) (GLuint id, GLenum pname, GLuint64* params); + PFNGLGETQUERYOBJECTUI64VPROC fGetQueryObjectui64v; + typedef void (GLAPIENTRY * PFNGLQUERYCOUNTERPROC) (GLuint id, GLenum target); + PFNGLQUERYCOUNTERPROC fQueryCounter; typedef void (GLAPIENTRY * PFNGLTEXPARAMETERIPROC) (GLenum target, GLenum pname, GLint param); PFNGLTEXPARAMETERIPROC fTexParameteri; typedef void (GLAPIENTRY * PFNGLTEXPARAMETERIVPROC) (GLenum target, GLenum pname, const GLint* param); @@ -165,6 +171,8 @@ struct GLContextSymbols PFNGLGETUNIFORMFVPROC fGetUniformfv; typedef void (GLAPIENTRY * PFNGLGETUNIFORMIVPROC) (GLuint program, GLint location, GLint* params); PFNGLGETUNIFORMIVPROC fGetUniformiv; + typedef void (GLAPIENTRY * PFNGLGETUNIFORMUIVPROC) (GLuint program, GLint location, GLuint* params); + PFNGLGETUNIFORMUIVPROC fGetUniformuiv; typedef GLint (GLAPIENTRY * PFNGLGETUNIFORMLOCATIONPROC) (GLint programObj, const GLchar* name); PFNGLGETUNIFORMLOCATIONPROC fGetUniformLocation; typedef void (GLAPIENTRY * PFNGLGETVERTEXATTRIBFVPROC) (GLuint, GLenum, GLfloat*); diff --git a/gfx/layers/apz/util/APZCCallbackHelper.cpp b/gfx/layers/apz/util/APZCCallbackHelper.cpp index b71810a2ce..7ad7ec7cf1 100644 --- a/gfx/layers/apz/util/APZCCallbackHelper.cpp +++ b/gfx/layers/apz/util/APZCCallbackHelper.cpp @@ -7,20 +7,20 @@ #include "ContentHelper.h" #include "gfxPlatform.h" // For gfxPlatform::UseTiling +#include "mozilla/dom/Element.h" #include "mozilla/dom/TabParent.h" #include "mozilla/layers/LayerTransactionChild.h" #include "mozilla/layers/ShadowLayers.h" +#include "mozilla/TouchEvents.h" #include "nsIScrollableFrame.h" #include "nsLayoutUtils.h" -#include "nsIDOMElement.h" #include "nsIInterfaceRequestorUtils.h" #include "nsIContent.h" #include "nsIDocument.h" #include "nsIDOMWindow.h" #include "nsRefreshDriver.h" +#include "nsString.h" #include "nsView.h" -#include "mozilla/TouchEvents.h" -#include "mozilla/dom/Element.h" #include "Layers.h" #define APZCCH_LOG(...) diff --git a/gfx/layers/apz/util/APZCCallbackHelper.h b/gfx/layers/apz/util/APZCCallbackHelper.h index f4d30d8d65..26502de328 100644 --- a/gfx/layers/apz/util/APZCCallbackHelper.h +++ b/gfx/layers/apz/util/APZCCallbackHelper.h @@ -6,8 +6,6 @@ #ifndef mozilla_layers_APZCCallbackHelper_h #define mozilla_layers_APZCCallbackHelper_h -#include "nsCOMPtr.h" -#include "nsIPresShell.h" #include "FrameMetrics.h" #include "mozilla/EventForwards.h" #include "mozilla/layers/APZUtils.h" @@ -15,8 +13,11 @@ class nsIContent; class nsIDocument; +class nsIPresShell; class nsIWidget; template struct already_AddRefed; +template class nsCOMPtr; +template class nsRefPtr; namespace mozilla { namespace layers {