Closed Bug 1193070 Opened 4 years ago Closed 4 years ago

WebGL 2 - Implement getFramebufferAttachmentParameter

Categories

(Core :: Canvas: WebGL, defect)

All
Unspecified
defect
Not set

Tracking

()

RESOLVED FIXED
mozilla44
Tracking Status
firefox44 --- fixed

People

(Reporter: kamidphish, Assigned: kamidphish)

Details

(Whiteboard: [gfx-noted])

Attachments

(1 file, 3 obsolete files)

No description provided.
Preparation for implementation.
Attachment #8646024 - Flags: review?(jgilbert)
Attached patch Add color sizes to FormatInfo. (obsolete) — Splinter Review
This makes implementing GetFramebufferAttachmentParameter easier.

If needed, hasColor, hasDepth, etc can be implemented as helper
functions that check the responsible field for > 0.
Attachment #8646025 - Flags: review?(jgilbert)
Comment on attachment 8646026 [details] [diff] [review]
Implement getFramebufferAttachmentParamter.

Review of attachment 8646026 [details] [diff] [review]:
-----------------------------------------------------------------

::: dom/canvas/WebGL2ContextFramebuffers.cpp
@@ +28,5 @@
> +    if (fba) {
> +        format = fba->EffectiveInternalFormat().get();
> +    } else {
> +        const GLFormats& formats = gl->GetGLFormats();
> +        switch (component) {

MOZ_CRASH if we don't recognize `component`.

@@ +47,5 @@
> +        }
> +    }
> +
> +    MOZ_ASSERT(format != LOCAL_GL_NONE);
> +    return webgl::GetInfoBySizedFormat(format);

I don't think this will work in the general case here. I don't have confidence in our EffectiveInternalFormats.

@@ +469,5 @@
> +
> +    /* 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. */

/* */ is useful for long comments, but I think we should use `//` anyways. /**/ comments make it excruciating to comment large blocks of code out.

Also, if it's a quote from the spec, put it in double-quotes!

@@ +480,5 @@
> +
> +    WebGLFramebuffer* boundFB = nullptr;
> +    switch (target) {
> +    case LOCAL_GL_DRAW_FRAMEBUFFER: boundFB = mBoundDrawFramebuffer; break;
> +    case LOCAL_GL_READ_FRAMEBUFFER: boundFB = mBoundReadFramebuffer; break;

About here IMO you should forward the call to WebGLFramebuffer::GetFramebufferAttachmentParameter, if we're not referencing the default FB.

The default FB can be handled in this function fairly simply.

@@ +518,5 @@
> +        case LOCAL_GL_DEPTH_ATTACHMENT:
> +        case LOCAL_GL_DEPTH_STENCIL_ATTACHMENT:
> +            break;
> +
> +        case LOCAL_GL_STENCIL_ATTACHMENT:

This should switch places with LOCAL_GL_DEPTH_STENCIL_ATTACHMENT above.

@@ +523,5 @@
> +                /* 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. */
> +                if (boundFB->DepthAttachment() != boundFB->StencilAttachment()) {

If this is the only user of operator!=, I would just dump the logic in here.

@@ +561,5 @@
> +    /* If the value of FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE is NONE, no framebuffer is bound
> +       to target. In this case querying pname FRAMEBUFFER_ATTACHMENT_OBJECT_NAME will
> +       return zero, and all other queries will generate an INVALID_OPERATION error. */
> +    if (objectType == LOCAL_GL_NONE) {
> +        // Here I convert name zero to mean JS null.

s/I convert/WebGL converts/

@@ +577,5 @@
> +    /* If the value of FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE is not NONE, these queries apply
> +       to all other framebuffer types: */
> +    if (objectType != LOCAL_GL_NONE) {
> +        switch (pname) {
> +        /* • If pname is FRAMEBUFFER_ATTACHMENT_RED_SIZE,

Please stick to * instead of non-trivially-typeable chars.

@@ +583,5 @@
> +             FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE, FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE, or
> +             FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE, then params will contain the number of
> +             bits in the corresponding red, green, blue, alpha, depth, or stencil
> +             component of the specified attachment. Zero is returned if the requested
> +             component is not present in attachment. */

Pretty sure we don't need this obvious bit of spec.

@@ +615,5 @@
> +                    ErrorInvalidOperation("getFramebufferAttachmentParameter:");
> +                    return JS::NullValue();
> +                }
> +
> +                int result = 0;

Move result's decl closer to where it's set.

@@ +616,5 @@
> +                    return JS::NullValue();
> +                }
> +
> +                int result = 0;
> +                const FormatInfo* info = FormatInfoForAttachment(gl, fba, pname);

FormatInfoForAttachment is not equiped to handle a pname of LOCAL_GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE.

@@ +638,5 @@
> +             the attachment, params will contain the value LINEAR. */
> +        case LOCAL_GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING:
> +            {
> +                // TODO: This implementation reports default framebuffer linear. Is that
> +                // true?

Yes it is.

@@ +645,5 @@
> +                    const WebGLFBAttachPoint& fba = boundFB->GetAttachPoint(attachment);
> +                    const FormatInfo* info = webgl::GetInfoBySizedFormat(
> +                        fba.EffectiveInternalFormat().get());
> +
> +                    if (fba.IsDefined() && info) {

If !fba.IsDefined(), fba.EffectiveInternalFormat() isn't safe to call.

@@ +671,5 @@
> +            const WebGLFBAttachPoint& fba = boundFB->GetAttachPoint(attachment);
> +            const WebGLTexture* tex = fba.Texture();
> +
> +            /* • If pname is FRAMEBUFFER_ATTACHMENT_OBJECT_NAME, then params will contain
> +                 the name of the texture object which contains the attached image. */

This level of spec-quoting seems unnecessary. Just use a switch, and leave a reference to where in the spec the exact text is.

It's hard to read the code through all the comments.

::: dom/canvas/WebGLFramebuffer.cpp
@@ +31,5 @@
>  bool
> +WebGLFBAttachPoint::operator==(const WebGLFBAttachPoint& rhs) const
> +{
> +    if (Texture())
> +        return Texture() == rhs.Texture();

This isn't true. It has to match levels too.
Attachment #8646026 - Flags: review?(jgilbert) → review-
Comment on attachment 8646025 [details] [diff] [review]
Add color sizes to FormatInfo.

Review of attachment 8646025 [details] [diff] [review]:
-----------------------------------------------------------------

::: dom/canvas/WebGLFormats.cpp
@@ +14,5 @@
>  //////////////////////////////////////////////////////////////////////////////////////////
>  
> +
> +GLint
> +ComponentSize(const FormatInfo* info, GLenum comp)

I wouldn't bother with a function for this, and would just put it in the calling code.

@@ +16,5 @@
> +
> +GLint
> +ComponentSize(const FormatInfo* info, GLenum comp)
> +{
> +    MOZ_ASSERT(info);

MOZ_RELEASE_ASSERT

@@ +19,5 @@
> +{
> +    MOZ_ASSERT(info);
> +    GLint size = 0;
> +
> +    if (info) {

Don't bother with this.

@@ +60,5 @@
> +ColorEncoding(const FormatInfo* info)
> +{
> +    MOZ_ASSERT(info);
> +    GLenum encoding = LOCAL_GL_LINEAR;
> +    if (info) {

Don't tolerate null infos.

@@ +66,5 @@
> +        case EffectiveFormat::SRGB8:
> +        case EffectiveFormat::SRGB8_ALPHA8:
> +        case EffectiveFormat::COMPRESSED_SRGB8_ETC2:
> +        case EffectiveFormat::COMPRESSED_SRGB8_ALPHA8_ETC2_EAC:
> +        case EffectiveFormat::COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2:

The main thing I don't like about this is that it breaks the "It's all in the tables" idea. I like this idea, and think we should keep it.

Even embedding this logic in AddFormatInfo() would be better, I think.

@@ -114,5 @@
> -    bool hasAlpha = false;
> -    bool hasDepth = false;
> -    bool hasStencil = false;
> -
> -    switch (unsizedFormat) {

Keep this switch, and assert that it matches the presence of bits for the components.
Such as:
case UnsizedFormat::D:
  MOZ_ASSERT(!isColorFormat&& !stencilSize);
  MOZ_ASSERT(depthSize);

And have above:
const bool isColorFormat = (redSize || greenSize || blueSize || alphaSize || luminanceSize);

@@ +180,5 @@
>      MOZ_ASSERT(!bytesPerPixel == bool(compressedFormatInfo));
>  
> +    const FormatInfo info = { format, name, baseFormat, dataType, bytesPerPixel,
> +                              redSize, greenSize, blueSize, alphaSize,
> +                              luminanceSize, depthSize, stencilSize,

We want to keep an `isColorFormat` which = (redSize || greenSize || blueSize || alphaSize || luminanceSize).

@@ +212,3 @@
>  
>      // GLES 3.0.4, p130-132, table 3.13
> +    AddFormatInfo(FOO(R8            ), _(RED ), _(UNSIGNED_NORMALIZED),  1, _R    (8));

It's tidier to keep `bytesPerTexel` before RED and UNSIGNED_NORMALIZED.
Otherwise, it may also be tempting to assume that bytesPerTexel was related to the unsized format and componentType, which it's looser than that.

@@ +239,3 @@
>  
> +    AddFormatInfo(FOO(R11F_G11F_B10F), _(RGB ), _(FLOAT),  4, _R_G_B(11,11,10));
> +    AddFormatInfo(FOO(RGB9_E5       ), _(RGB ), _(FLOAT),  4, _RGB(9));

RGB9E5 is closest to _RGB(14), though the exact bit depths can't be queried via the WebGL API.

@@ +272,5 @@
> +    AddFormatInfo(FOO(DEPTH_COMPONENT16 ), _(DEPTH_COMPONENT), _(UNSIGNED_NORMALIZED), 2, _D (16));
> +    AddFormatInfo(FOO(DEPTH_COMPONENT24 ), _(DEPTH_COMPONENT), _(UNSIGNED_NORMALIZED), 3, _D (24));
> +    AddFormatInfo(FOO(DEPTH_COMPONENT32F), _(DEPTH_COMPONENT), _(FLOAT),               4, _D (32));
> +    AddFormatInfo(FOO(DEPTH24_STENCIL8  ), _(DEPTH_STENCIL  ), _(UNSIGNED_NORMALIZED), 4, _DS(24,8));
> +    AddFormatInfo(FOO(DEPTH32F_STENCIL8 ), _(DEPTH_STENCIL  ), _(FLOAT),               8, _DS(32,8));

DEPTH_STENCIL formats have a component-type of NONE.

::: dom/canvas/WebGLFormats.h
@@ +170,5 @@
> +    /**
> +     * Base format is one of GL_RED, GL_RG, GL_RGB, GL_RGBA, GL_ALPHA, GL_LUMINANCE,
> +     * GL_LUMINANCE_ALPHA, GL_DEPTH_COMPONENT, GL_STENCIL_INDEX, GL_DEPTH_STENCIL.
> +     */
> +    GLenum baseFormat;

Don't use a GLenum for this, since this never needs to be converted back to an enum.

@@ +176,5 @@
> +    /**
> +     * Logical data type: one of GL_UNSIGNED_NORMALIZED, GL_SIGNED_NORMALIZED,
> +     * GL_UNSIGNED_INT, GL_INT, GL_FLOAT.
> +     */
> +    GLenum dataType;

`componentType`

@@ +185,5 @@
>      const uint8_t bytesPerPixel; // 0 iff `!!compression`.
> +
> +    /**
> +     * Size of components, in bits.
> +     */

Don't use three lines for a one-line comment.

@@ +262,5 @@
> +
> +/**
> + * Return the size in bits for comp.
> + */
> +GLint ComponentSize(const FormatInfo* info, GLenum comp);

What is `comp`? There's not enough info here to have an idea without reading the implementation.
Attachment #8646025 - Flags: review?(jgilbert) → review-
Attachment #8646024 - Flags: review?(jgilbert) → review+
I cut'n'paste the spec from preview to aid in checking the logic is correct.  I'll clean up the function and split default from non-default framebuffers.
Attachment #8646024 - Attachment is obsolete: true
Attachment #8646025 - Attachment is obsolete: true
Attachment #8646026 - Attachment is obsolete: true
Attachment #8647917 - Flags: review?(jgilbert)
Attachment #8647917 - Flags: review?(jgilbert) → review+
https://hg.mozilla.org/mozilla-central/rev/81c18a4b672f
Status: ASSIGNED → RESOLVED
Closed: 4 years ago
Resolution: --- → FIXED
Target Milestone: --- → mozilla44
You need to log in before you can comment on or make changes to this bug.