diff --git a/dom/canvas/WebGL2Context.h b/dom/canvas/WebGL2Context.h index e3556ed6fd93..f3d11cac1459 100644 --- a/dom/canvas/WebGL2Context.h +++ b/dom/canvas/WebGL2Context.h @@ -71,6 +71,11 @@ public: GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter); void FramebufferTextureLayer(GLenum target, GLenum attachment, WebGLTexture* texture, GLint level, GLint layer); + + virtual JS::Value GetFramebufferAttachmentParameter(JSContext* cx, GLenum target, + GLenum attachment, GLenum pname, + ErrorResult& rv) override; + void InvalidateFramebuffer(GLenum target, const dom::Sequence& attachments, ErrorResult& rv); void InvalidateSubFramebuffer (GLenum target, const dom::Sequence& attachments, GLint x, GLint y, diff --git a/dom/canvas/WebGL2ContextFramebuffers.cpp b/dom/canvas/WebGL2ContextFramebuffers.cpp index 62d330f2a254..abf5c3eb2d87 100644 --- a/dom/canvas/WebGL2ContextFramebuffers.cpp +++ b/dom/canvas/WebGL2ContextFramebuffers.cpp @@ -8,10 +8,17 @@ #include "GLContext.h" #include "GLScreenBuffer.h" #include "WebGLContextUtils.h" +#include "WebGLFormats.h" #include "WebGLFramebuffer.h" namespace mozilla { +using gl::GLContext; +using gl::GLFormats; +using webgl::EffectiveFormat; +using webgl::FormatInfo; +using webgl::ComponentType; + // Returns one of FLOAT, INT, UNSIGNED_INT. // Fixed-points (normalized ints) are considered FLOAT. static GLenum @@ -418,6 +425,103 @@ WebGL2Context::FramebufferTextureLayer(GLenum target, GLenum attachment, fb->FramebufferTextureLayer(attachment, texture, level, layer); } +JS::Value +WebGL2Context::GetFramebufferAttachmentParameter(JSContext* cx, + GLenum target, + GLenum attachment, + GLenum pname, + ErrorResult& rv) +{ + if (IsContextLost()) + return JS::NullValue(); + + // OpenGL ES 3.0.4 (August 27, 2014) 6.1. QUERYING GL STATE 240 + // "getFramebufferAttachmentParamter returns information about attachments of a bound + // framebuffer object. target must be DRAW_FRAMEBUFFER, READ_FRAMEBUFFER, or + // FRAMEBUFFER." + + if (!ValidateFramebufferTarget(target, "getFramebufferAttachmentParameter")) + return JS::NullValue(); + + // FRAMEBUFFER is equivalent to DRAW_FRAMEBUFFER. + if (target == LOCAL_GL_FRAMEBUFFER) + target = LOCAL_GL_DRAW_FRAMEBUFFER; + + WebGLFramebuffer* boundFB = nullptr; + switch (target) { + case LOCAL_GL_DRAW_FRAMEBUFFER: boundFB = mBoundDrawFramebuffer; break; + case LOCAL_GL_READ_FRAMEBUFFER: boundFB = mBoundReadFramebuffer; break; + } + + if (boundFB) { + return boundFB->GetAttachmentParameter(cx, attachment, pname, rv); + } + + // Handle default FB + const gl::GLFormats& formats = gl->GetGLFormats(); + GLenum internalFormat = LOCAL_GL_NONE; + + /* If the default framebuffer is bound to target, then attachment must be BACK, + identifying the color buffer; DEPTH, identifying the depth buffer; or STENCIL, + identifying the stencil buffer. */ + switch (attachment) { + case LOCAL_GL_BACK: + internalFormat = formats.color_texInternalFormat; + break; + + case LOCAL_GL_DEPTH: + internalFormat = formats.depth; + break; + + case LOCAL_GL_STENCIL: + internalFormat = formats.stencil; + break; + + default: + ErrorInvalidEnum("getFramebufferAttachmentParameter: Can only query " + "attachment BACK, DEPTH, or STENCIL from default " + "framebuffer"); + return JS::NullValue(); + } + + const FormatInfo* info = webgl::GetInfoBySizedFormat(internalFormat); + MOZ_RELEASE_ASSERT(info); + EffectiveFormat effectiveFormat = info->effectiveFormat; + + switch (pname) { + case LOCAL_GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE: + return JS::Int32Value(LOCAL_GL_FRAMEBUFFER_DEFAULT); + + case LOCAL_GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE: + case LOCAL_GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE: + case LOCAL_GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE: + case LOCAL_GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE: + case LOCAL_GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE: + case LOCAL_GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE: + return JS::Int32Value(webgl::GetComponentSize(effectiveFormat, pname)); + + case LOCAL_GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE: + if (attachment == LOCAL_GL_DEPTH_STENCIL_ATTACHMENT && + pname == LOCAL_GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE) + { + ErrorInvalidOperation("getFramebufferAttachmentParameter: Querying " + "FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE against " + "DEPTH_STENCIL_ATTACHMENT is an error."); + return JS::NullValue(); + } + + return JS::Int32Value(webgl::GetComponentType(effectiveFormat)); + + case LOCAL_GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING: + return JS::Int32Value(webgl::GetColorEncoding(effectiveFormat)); + } + + /* Any combinations of framebuffer type and pname not described above will generate an + INVALID_ENUM error. */ + ErrorInvalidEnum("getFramebufferAttachmentParameter: Invalid combination of "); + return JS::NullValue(); +} + // Map attachments intended for the default buffer, to attachments for a non- // default buffer. static bool diff --git a/dom/canvas/WebGLContext.h b/dom/canvas/WebGLContext.h index c6ae9bb8a2ab..171d89208c83 100644 --- a/dom/canvas/WebGLContext.h +++ b/dom/canvas/WebGLContext.h @@ -458,9 +458,9 @@ public: } GLenum GetError(); - JS::Value GetFramebufferAttachmentParameter(JSContext* cx, GLenum target, - GLenum attachment, GLenum pname, - ErrorResult& rv); + virtual JS::Value GetFramebufferAttachmentParameter(JSContext* cx, GLenum target, + GLenum attachment, GLenum pname, + ErrorResult& rv); void GetFramebufferAttachmentParameter(JSContext* cx, GLenum target, GLenum attachment, GLenum pname, diff --git a/dom/canvas/WebGLFormats.cpp b/dom/canvas/WebGLFormats.cpp index 0028dde7af6f..5966e80e4cec 100644 --- a/dom/canvas/WebGLFormats.cpp +++ b/dom/canvas/WebGLFormats.cpp @@ -809,5 +809,319 @@ FormatUsageAuthority::AddUnpackOption(GLenum unpackFormat, GLenum unpackType, MOZ_ALWAYS_TRUE(didInsert); } +//////////////////////////////////////////////////////////////////////////////// + +struct ComponentSizes +{ + GLubyte redSize; + GLubyte greenSize; + GLubyte blueSize; + GLubyte alphaSize; + GLubyte depthSize; + GLubyte stencilSize; +}; + +static ComponentSizes kComponentSizes[] = { + // GLES 3.0.4, p128-129, "Required Texture Formats" + // "Texture and renderbuffer color formats" + { 32, 32, 32, 32, 0, 0 }, // RGBA32I, + { 32, 32, 32, 32, 0, 0 }, // RGBA32UI, + { 16, 16, 16, 16, 0, 0 }, // RGBA16I, + { 16, 16, 16, 16, 0, 0 }, // RGBA16UI, + { 8, 8, 8, 8, 0, 0 }, // RGBA8, + { 8, 8, 8, 8, 0, 0 }, // RGBA8I, + { 8, 8, 8, 8, 0, 0 }, // RGBA8UI, + { 8, 8, 8, 8, 0, 0 }, // SRGB8_ALPHA8, + { 10, 10, 10, 2, 0, 0 }, // RGB10_A2, + { 10, 10, 10, 2, 0, 0 }, // RGB10_A2UI, + { 4, 4, 4, 4, 0, 0 }, // RGBA4, + { 5, 5, 5, 1, 0, 0 }, // RGB5_A1, + + { 8, 8, 8, 0, 0, 0 }, // RGB8, + { 8, 8, 8, 0, 0, 0 }, // RGB565, + + { 32, 32, 0, 0, 0, 0 }, // RG32I, + { 32, 32, 0, 0, 0, 0 }, // RG32UI, + { 16, 16, 0, 0, 0, 0 }, // RG16I, + { 16, 16, 0, 0, 0, 0 }, // RG16UI, + { 8, 8, 0, 0, 0, 0 }, // RG8, + { 8, 8, 0, 0, 0, 0 }, // RG8I, + { 8, 8, 0, 0, 0, 0 }, // RG8UI, + + { 32, 0, 0, 0, 0, 0 }, // R32I, + { 32, 0, 0, 0, 0, 0 }, // R32UI, + { 16, 0, 0, 0, 0, 0 }, // R16I, + { 16, 0, 0, 0, 0, 0 }, // R16UI, + { 8, 0, 0, 0, 0, 0 }, // R8, + { 8, 0, 0, 0, 0, 0 }, // R8I, + { 8, 0, 0, 0, 0, 0 }, // R8UI, + + // "Texture-only color formats" + { 32, 32, 32, 32, 0, 0 }, // RGBA32F, + { 16, 16, 16, 16, 0, 0 }, // RGBA16F, + { 8, 8, 8, 8, 0, 0 }, // RGBA8_SNORM, + + { 32, 32, 32, 0, 0, 0 }, // RGB32F, + { 32, 32, 32, 0, 0, 0 }, // RGB32I, + { 32, 32, 32, 0, 0, 0 }, // RGB32UI, + + { 16, 16, 16, 0, 0, 0 }, // RGB16F, + { 16, 16, 16, 0, 0, 0 }, // RGB16I, + { 16, 16, 16, 0, 0, 0 }, // RGB16UI, + + { 8, 8, 8, 0, 0, 0 }, // RGB8_SNORM, + { 8, 8, 8, 0, 0, 0 }, // RGB8I, + { 8, 8, 8, 0, 0, 0 }, // RGB8UI, + { 8, 8, 8, 0, 0, 0 }, // SRGB8, + + { 11, 11, 11, 0, 0, 0 }, // R11F_G11F_B10F, + { 9, 9, 9, 0, 0, 0 }, // RGB9_E5, + + { 32, 32, 0, 0, 0, 0 }, // RG32F, + { 16, 16, 0, 0, 0, 0 }, // RG16F, + { 8, 8, 0, 0, 0, 0 }, // RG8_SNORM, + + { 32, 0, 0, 0, 0, 0 }, // R32F, + { 16, 0, 0, 0, 0, 0 }, // R16F, + { 8, 0, 0, 0, 0, 0 }, // R8_SNORM, + + // "Depth formats" + { 0, 0, 0, 0, 32, 0 }, // DEPTH_COMPONENT32F, + { 0, 0, 0, 0, 24, 0 }, // DEPTH_COMPONENT24, + { 0, 0, 0, 0, 16, 0 }, // DEPTH_COMPONENT16, + + // "Combined depth+stencil formats" + { 0, 0, 0, 0, 32, 8 }, // DEPTH32F_STENCIL0, + { 0, 0, 0, 0, 24, 8 }, // DEPTH24_STENCIL8, + + // GLES 3.0.4, p205-206, "Required Renderbuffer Formats" + { 0, 0, 0, 0, 0, 8 }, // STENCIL_INDEX8, + + // GLES 3.0.4, p128, table 3.12. + { 8, 8, 8, 8, 0, 0 }, // Luminance8Alpha8, + { 8, 8, 8, 0, 0, 0 }, // Luminance8, + { 0, 0, 0, 8, 0, 0 }, // Alpha8, + + // GLES 3.0.4, p147, table 3.19 + // GLES 3.0.4, p286+, $C.1 "ETC Compressed Texture Image Formats" + { 8, 8, 8, 8, 0, 0 }, // COMPRESSED_R11_EAC, + { 8, 8, 8, 8, 0, 0 }, // COMPRESSED_SIGNED_R11_EAC, + { 8, 8, 8, 8, 0, 0 }, // COMPRESSED_RG11_EAC, + { 8, 8, 8, 8, 0, 0 }, // COMPRESSED_SIGNED_RG11_EAC, + { 8, 8, 8, 8, 0, 0 }, // COMPRESSED_RGB8_ETC2, + { 8, 8, 8, 8, 0, 0 }, // COMPRESSED_SRGB8_ETC2, + { 8, 8, 8, 8, 0, 0 }, // COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2, + { 8, 8, 8, 8, 0, 0 }, // COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2, + { 8, 8, 8, 8, 0, 0 }, // COMPRESSED_RGBA8_ETC2_EAC, + { 8, 8, 8, 8, 0, 0 }, // COMPRESSED_SRGB8_ALPHA8_ETC2_EAC, + + // AMD_compressed_ATC_texture + { 8, 8, 8, 0, 0, 0 }, // ATC_RGB_AMD, + { 8, 8, 8, 8, 0, 0 }, // ATC_RGBA_EXPLICIT_ALPHA_AMD, + { 8, 8, 8, 8, 0, 0 }, // ATC_RGBA_INTERPOLATED_ALPHA_AMD, + + // EXT_texture_compression_s3tc + { 8, 8, 8, 0, 0, 0 }, // COMPRESSED_RGB_S3TC_DXT1, + { 8, 8, 8, 8, 0, 0 }, // COMPRESSED_RGBA_S3TC_DXT1, + { 8, 8, 8, 8, 0, 0 }, // COMPRESSED_RGBA_S3TC_DXT3, + { 8, 8, 8, 8, 0, 0 }, // COMPRESSED_RGBA_S3TC_DXT5, + + // IMG_texture_compression_pvrtc + { 8, 8, 8, 0, 0, 0 }, // COMPRESSED_RGB_PVRTC_4BPPV1, + { 8, 8, 8, 8, 0, 0 }, // COMPRESSED_RGBA_PVRTC_4BPPV1, + { 8, 8, 8, 0, 0, 0 }, // COMPRESSED_RGB_PVRTC_2BPPV1, + { 8, 8, 8, 8, 0, 0 }, // COMPRESSED_RGBA_PVRTC_2BPPV1, + + // OES_compressed_ETC1_RGB8_texture + { 8, 8, 8, 0, 0, 0 }, // ETC1_RGB8, + + // OES_texture_float + { 32, 32, 32, 32, 0, 0 }, // Luminance32FAlpha32F, + { 32, 32, 32, 0, 0, 0 }, // Luminance32F, + { 0, 0, 0, 32, 0, 0 }, // Alpha32F, + + // OES_texture_half_float + { 16, 16, 16, 16, 0, 0 }, // Luminance16FAlpha16F, + { 16, 16, 16, 0, 0, 0 }, // Luminance16F, + { 0, 0, 0, 16, 0, 0 }, // Alpha16F, + + { 0, } // MAX +}; + +GLint +GetComponentSize(EffectiveFormat format, GLenum component) +{ + ComponentSizes compSize = kComponentSizes[(int) format]; + switch (component) { + case LOCAL_GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE: + case LOCAL_GL_RENDERBUFFER_RED_SIZE: + case LOCAL_GL_RED_BITS: + return compSize.redSize; + case LOCAL_GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE: + case LOCAL_GL_RENDERBUFFER_GREEN_SIZE: + case LOCAL_GL_GREEN_BITS: + return compSize.greenSize; + case LOCAL_GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE: + case LOCAL_GL_RENDERBUFFER_BLUE_SIZE: + case LOCAL_GL_BLUE_BITS: + return compSize.blueSize; + case LOCAL_GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE: + case LOCAL_GL_RENDERBUFFER_ALPHA_SIZE: + case LOCAL_GL_ALPHA_BITS: + return compSize.alphaSize; + case LOCAL_GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE: + case LOCAL_GL_RENDERBUFFER_DEPTH_SIZE: + case LOCAL_GL_DEPTH_BITS: + return compSize.depthSize; + case LOCAL_GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE: + case LOCAL_GL_RENDERBUFFER_STENCIL_SIZE: + case LOCAL_GL_STENCIL_BITS: + return compSize.stencilSize; + } + + return 0; +} + +static GLenum kComponentTypes[] = { + // GLES 3.0.4, p128-129, "Required Texture Formats" + // "Texture and renderbuffer color formats" + LOCAL_GL_INT, // RGBA32I, + LOCAL_GL_UNSIGNED_INT, // RGBA32UI, + LOCAL_GL_INT, // RGBA16I, + LOCAL_GL_UNSIGNED_INT, // RGBA16UI, + LOCAL_GL_UNSIGNED_NORMALIZED, // RGBA8, + LOCAL_GL_INT, // RGBA8I, + LOCAL_GL_UNSIGNED_INT, // RGBA8UI, + LOCAL_GL_UNSIGNED_NORMALIZED, // SRGB8_ALPHA8, + LOCAL_GL_UNSIGNED_NORMALIZED, // RGB10_A2, + LOCAL_GL_UNSIGNED_INT, // RGB10_A2UI, + LOCAL_GL_UNSIGNED_NORMALIZED, // RGBA4, + LOCAL_GL_UNSIGNED_NORMALIZED, // RGB5_A1, + + LOCAL_GL_UNSIGNED_NORMALIZED, // RGB8, + LOCAL_GL_UNSIGNED_NORMALIZED, // RGB565, + + LOCAL_GL_INT, // RG32I, + LOCAL_GL_UNSIGNED_INT, // RG32UI, + LOCAL_GL_INT, // RG16I, + LOCAL_GL_UNSIGNED_INT, // RG16UI, + LOCAL_GL_UNSIGNED_NORMALIZED, // RG8, + LOCAL_GL_INT, // RG8I, + LOCAL_GL_UNSIGNED_INT, // RG8UI, + + LOCAL_GL_INT, // R32I, + LOCAL_GL_UNSIGNED_INT, // R32UI, + LOCAL_GL_INT, // R16I, + LOCAL_GL_UNSIGNED_INT, // R16UI, + LOCAL_GL_UNSIGNED_NORMALIZED, // R8, + LOCAL_GL_INT, // R8I, + LOCAL_GL_UNSIGNED_INT, // R8UI, + + // "Texture-only color formats" + LOCAL_GL_FLOAT, // RGBA32F, + LOCAL_GL_FLOAT, // RGBA16F, + LOCAL_GL_SIGNED_NORMALIZED, // RGBA8_SNORM, + + LOCAL_GL_FLOAT, // RGB32F, + LOCAL_GL_INT, // RGB32I, + LOCAL_GL_UNSIGNED_INT, // RGB32UI, + + LOCAL_GL_FLOAT, // RGB16F, + LOCAL_GL_INT, // RGB16I, + LOCAL_GL_UNSIGNED_INT, // RGB16UI, + + LOCAL_GL_SIGNED_NORMALIZED, // RGB8_SNORM, + LOCAL_GL_INT, // RGB8I, + LOCAL_GL_UNSIGNED_INT, // RGB8UI, + LOCAL_GL_UNSIGNED_NORMALIZED, // SRGB8, + + LOCAL_GL_FLOAT, // R11F_G11F_B10F, + LOCAL_GL_FLOAT, // RGB9_E5, + + LOCAL_GL_FLOAT, // RG32F, + LOCAL_GL_FLOAT, // RG16F, + LOCAL_GL_SIGNED_NORMALIZED, // RG8_SNORM, + + LOCAL_GL_FLOAT, // R32F, + LOCAL_GL_FLOAT, // R16F, + LOCAL_GL_SIGNED_NORMALIZED, // R8_SNORM, + + // "Depth formats" + LOCAL_GL_FLOAT, // DEPTH_COMPONENT32F, + LOCAL_GL_UNSIGNED_NORMALIZED, // DEPTH_COMPONENT24, + LOCAL_GL_UNSIGNED_NORMALIZED, // DEPTH_COMPONENT16, + + // "Combined depth+stencil formats" + LOCAL_GL_FLOAT, // DEPTH32F_STENCIL8, + LOCAL_GL_UNSIGNED_NORMALIZED, // DEPTH24_STENCIL8, + + // GLES 3.0.4, p205-206, "Required Renderbuffer Formats" + LOCAL_GL_UNSIGNED_NORMALIZED, // STENCIL_INDEX8, + + // GLES 3.0.4, p128, table 3.12. + LOCAL_GL_UNSIGNED_NORMALIZED, // Luminance8Alpha8, + LOCAL_GL_UNSIGNED_NORMALIZED, // Luminance8, + LOCAL_GL_UNSIGNED_NORMALIZED, // Alpha8, + + // GLES 3.0.4, p147, table 3.19 + // GLES 3.0.4, p286+, $C.1 "ETC Compressed Texture Image Formats" + LOCAL_GL_UNSIGNED_NORMALIZED, // COMPRESSED_R11_EAC, + LOCAL_GL_UNSIGNED_NORMALIZED, // COMPRESSED_SIGNED_R11_EAC, + LOCAL_GL_UNSIGNED_NORMALIZED, // COMPRESSED_RG11_EAC, + LOCAL_GL_UNSIGNED_NORMALIZED, // COMPRESSED_SIGNED_RG11_EAC, + LOCAL_GL_UNSIGNED_NORMALIZED, // COMPRESSED_RGB8_ETC2, + LOCAL_GL_UNSIGNED_NORMALIZED, // COMPRESSED_SRGB8_ETC2, + LOCAL_GL_UNSIGNED_NORMALIZED, // COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2, + LOCAL_GL_UNSIGNED_NORMALIZED, // COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2, + LOCAL_GL_UNSIGNED_NORMALIZED, // COMPRESSED_RGBA8_ETC2_EAC, + LOCAL_GL_UNSIGNED_NORMALIZED, // COMPRESSED_SRGB8_ALPHA8_ETC2_EAC, + + // AMD_compressed_ATC_texture + LOCAL_GL_UNSIGNED_NORMALIZED, // ATC_RGB_AMD, + LOCAL_GL_UNSIGNED_NORMALIZED, // ATC_RGBA_EXPLICIT_ALPHA_AMD, + LOCAL_GL_UNSIGNED_NORMALIZED, // ATC_RGBA_INTERPOLATED_ALPHA_AMD, + + // EXT_texture_compression_s3tc + LOCAL_GL_UNSIGNED_NORMALIZED, // COMPRESSED_RGB_S3TC_DXT1, + LOCAL_GL_UNSIGNED_NORMALIZED, // COMPRESSED_RGBA_S3TC_DXT1, + LOCAL_GL_UNSIGNED_NORMALIZED, // COMPRESSED_RGBA_S3TC_DXT3, + LOCAL_GL_UNSIGNED_NORMALIZED, // COMPRESSED_RGBA_S3TC_DXT5, + + // IMG_texture_compression_pvrtc + LOCAL_GL_UNSIGNED_NORMALIZED, // COMPRESSED_RGB_PVRTC_4BPPV1, + LOCAL_GL_UNSIGNED_NORMALIZED, // COMPRESSED_RGBA_PVRTC_4BPPV1, + LOCAL_GL_UNSIGNED_NORMALIZED, // COMPRESSED_RGB_PVRTC_2BPPV1, + LOCAL_GL_UNSIGNED_NORMALIZED, // COMPRESSED_RGBA_PVRTC_2BPPV1, + + // OES_compressed_ETC1_RGB8_texture + LOCAL_GL_UNSIGNED_NORMALIZED, // ETC1_RGB8, + + // OES_texture_float + LOCAL_GL_FLOAT, // Luminance32FAlpha32F, + LOCAL_GL_FLOAT, // Luminance32F, + LOCAL_GL_FLOAT, // Alpha32F, + + // OES_texture_half_float + LOCAL_GL_FLOAT, // Luminance16FAlpha16F, + LOCAL_GL_FLOAT, // Luminance16F, + LOCAL_GL_FLOAT, // Alpha16F, + + LOCAL_GL_NONE // MAX +}; + +GLenum +GetComponentType(EffectiveFormat format) +{ + return kComponentTypes[(int) format]; +} + +GLenum +GetColorEncoding(EffectiveFormat format) +{ + const bool isSRGB = (GetFormatInfo(format)->colorComponentType == + ComponentType::NormUIntSRGB); + return (isSRGB) ? LOCAL_GL_SRGB : LOCAL_GL_LINEAR; +} + } // namespace webgl } // namespace mozilla diff --git a/dom/canvas/WebGLFormats.h b/dom/canvas/WebGLFormats.h index 33735bab473f..e780e77b8040 100644 --- a/dom/canvas/WebGLFormats.h +++ b/dom/canvas/WebGLFormats.h @@ -252,13 +252,21 @@ public: EffectiveFormat effectiveFormat); FormatUsageInfo* GetUsage(EffectiveFormat format); - FormatUsageInfo* GetUsage(const FormatInfo* format) { + if (!format) + return nullptr; + return GetUsage(format->effectiveFormat); } }; +//////////////////////////////////////////////////////////////////////////////// + +GLint GetComponentSize(EffectiveFormat format, GLenum component); +GLenum GetComponentType(EffectiveFormat format); +GLenum GetColorEncoding(EffectiveFormat format); + } // namespace webgl } // namespace mozilla diff --git a/dom/canvas/WebGLFramebuffer.cpp b/dom/canvas/WebGLFramebuffer.cpp index 34363d1b0aa9..93a8e293016d 100644 --- a/dom/canvas/WebGLFramebuffer.cpp +++ b/dom/canvas/WebGLFramebuffer.cpp @@ -433,6 +433,66 @@ WebGLFBAttachPoint::FinalizeAttachment(gl::GLContext* gl, MOZ_CRASH(); } +JS::Value +WebGLFBAttachPoint::GetParameter(WebGLContext* context, GLenum pname) +{ + // TODO: WebGLTexture and WebGLRenderbuffer should store FormatInfo instead of doing + // this dance every time. + const GLenum internalFormat = EffectiveInternalFormat().get(); + const webgl::FormatInfo* info = webgl::GetInfoBySizedFormat(internalFormat); + MOZ_ASSERT(info); + + WebGLTexture* tex = Texture(); + + switch (pname) { + case LOCAL_GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE: + case LOCAL_GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE: + case LOCAL_GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE: + case LOCAL_GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE: + case LOCAL_GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE: + case LOCAL_GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE: + return JS::Int32Value(webgl::GetComponentSize(info->effectiveFormat, pname)); + + case LOCAL_GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE: + return JS::Int32Value(webgl::GetComponentType(info->effectiveFormat)); + + case LOCAL_GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING: + return JS::Int32Value(webgl::GetColorEncoding(info->effectiveFormat)); + + case LOCAL_GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL: + if (tex) { + return JS::Int32Value(MipLevel()); + } + break; + + case LOCAL_GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE: + if (tex) { + int32_t face = 0; + if (tex->Target() == LOCAL_GL_TEXTURE_CUBE_MAP) { + face = ImageTarget().get(); + } + return JS::Int32Value(face); + } + break; + + case LOCAL_GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER: + if (tex) { + int32_t layer = 0; + if (tex->Target() == LOCAL_GL_TEXTURE_2D_ARRAY || + tex->Target() == LOCAL_GL_TEXTURE_3D) + { + layer = Layer(); + } + return JS::Int32Value(layer); + } + break; + } + + context->ErrorInvalidEnum("getFramebufferParameter: Invalid combination of " + "attachment and pname."); + return JS::NullValue(); +} + //////////////////////////////////////////////////////////////////////////////// // WebGLFramebuffer @@ -987,6 +1047,110 @@ WebGLFramebuffer::ValidateForRead(const char* info, TexInternalFormat* const out return true; } +static bool +AttachmentsDontMatch(const WebGLFBAttachPoint& a, const WebGLFBAttachPoint& b) +{ + if (a.Texture()) { + return (a.Texture() != b.Texture()); + } + + if (a.Renderbuffer()) { + return (a.Renderbuffer() != b.Renderbuffer()); + } + + return false; +} + +JS::Value +WebGLFramebuffer::GetAttachmentParameter(JSContext* cx, + GLenum attachment, + GLenum pname, + ErrorResult& rv) +{ + // "If a framebuffer object is bound to target, then attachment must be one of the + // attachment points of the framebuffer listed in table 4.6." + switch (attachment) { + case LOCAL_GL_DEPTH_ATTACHMENT: + case LOCAL_GL_DEPTH_STENCIL_ATTACHMENT: + break; + + case LOCAL_GL_STENCIL_ATTACHMENT: + // "If attachment is DEPTH_STENCIL_ATTACHMENT, and different objects are bound to + // the depth and stencil attachment points of target, the query will fail and + // generate an INVALID_OPERATION error. If the same object is bound to both + // attachment points, information about that object will be returned." + + // Does this mean it has to be the same level or layer? Because the queries are + // independent of level or layer. + if (AttachmentsDontMatch(DepthAttachment(), StencilAttachment())) { + mContext->ErrorInvalidOperation("getFramebufferAttachmentParameter: " + "DEPTH_ATTACHMENT and STENCIL_ATTACHMENT " + "have different objects bound."); + return JS::NullValue(); + } + break; + + default: + if (attachment < LOCAL_GL_COLOR_ATTACHMENT0 || + attachment > mContext->LastColorAttachment()) + { + mContext->ErrorInvalidEnum("getFramebufferAttachmentParameter: Can only " + "query COLOR_ATTACHMENTi, DEPTH_ATTACHMENT, " + "DEPTH_STENCIL_ATTACHMENT, or STENCIL_ATTACHMENT " + "on framebuffer."); + return JS::NullValue(); + } + } + + if (attachment == LOCAL_GL_DEPTH_STENCIL_ATTACHMENT && + pname == LOCAL_GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE) + { + mContext->ErrorInvalidOperation("getFramebufferAttachmentParameter: Querying " + "FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE against " + "DEPTH_STENCIL_ATTACHMENT is an error."); + return JS::NullValue(); + } + + GLenum objectType = LOCAL_GL_NONE; + auto& fba = GetAttachPoint(attachment); + if (fba.Texture()) { + objectType = LOCAL_GL_TEXTURE; + } else if (fba.Renderbuffer()) { + objectType = LOCAL_GL_RENDERBUFFER; + } + + switch (pname) { + case LOCAL_GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE: + return JS::Int32Value(objectType); + + case LOCAL_GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME: + if (objectType == LOCAL_GL_NONE) { + return JS::NullValue(); + } + + if (objectType == LOCAL_GL_RENDERBUFFER) { + const WebGLRenderbuffer* rb = fba.Renderbuffer(); + return mContext->WebGLObjectAsJSValue(cx, rb, rv); + } + + /* If the value of FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE is TEXTURE, then */ + if (objectType == LOCAL_GL_TEXTURE) { + const WebGLTexture* tex = fba.Texture(); + return mContext->WebGLObjectAsJSValue(cx, tex, rv); + } + break; + } + + if (objectType == LOCAL_GL_NONE) { + mContext->ErrorInvalidOperation("getFramebufferAttachmentParameter: No " + "attachment at %s", + mContext->EnumName(attachment)); + return JS::NullValue(); + } + + return fba.GetParameter(mContext, pname); +} + //////////////////////////////////////////////////////////////////////////////// // Goop. diff --git a/dom/canvas/WebGLFramebuffer.h b/dom/canvas/WebGLFramebuffer.h index 7e12b8f47104..a832c1ad2cd9 100644 --- a/dom/canvas/WebGLFramebuffer.h +++ b/dom/canvas/WebGLFramebuffer.h @@ -62,7 +62,7 @@ public: void SetTexImageLayer(WebGLTexture* tex, TexImageTarget target, GLint level, GLint layer); void SetRenderbuffer(WebGLRenderbuffer* rb); - + const WebGLTexture* Texture() const { return mTexturePtr; } @@ -95,6 +95,8 @@ public: void FinalizeAttachment(gl::GLContext* gl, FBAttachment attachmentLoc) const; + + JS::Value GetParameter(WebGLContext* context, GLenum pname); }; class WebGLFramebuffer final @@ -225,6 +227,9 @@ public: } bool ValidateForRead(const char* info, TexInternalFormat* const out_format); + + JS::Value GetAttachmentParameter(JSContext* cx, GLenum attachment, GLenum pname, + ErrorResult& rv); }; } // namespace mozilla