int64_t
WebGLRenderbuffer::MemoryUsage() const
{
    int64_t pixels = int64_t(Width()) * int64_t(Height());

    GLenum primaryFormat = InternalFormatForGL();
    // If there is no defined format, we're not taking up any memory
    if (!primaryFormat)
        return 0;

    int64_t secondarySize = 0;
    if (mSecondaryRB) {
        if (NeedsDepthStencilEmu(mContext->gl, primaryFormat)) {
            primaryFormat = DepthStencilDepthFormat(mContext->gl);
            secondarySize = 1*pixels; // STENCIL_INDEX8
        } else {
            secondarySize = 1*1*2; // 1x1xRGBA4
        }
    }

    int64_t primarySize = 0;
    switch (primaryFormat) {
        case LOCAL_GL_STENCIL_INDEX8:
            primarySize = 1*pixels;
            break;
        case LOCAL_GL_RGBA4:
        case LOCAL_GL_RGB5_A1:
        case LOCAL_GL_RGB565:
        case LOCAL_GL_DEPTH_COMPONENT16:
            primarySize = 2*pixels;
            break;
        case LOCAL_GL_RGB8:
        case LOCAL_GL_DEPTH_COMPONENT24:
            primarySize = 3*pixels;
            break;
        case LOCAL_GL_RGBA8:
        case LOCAL_GL_SRGB8_ALPHA8_EXT:
        case LOCAL_GL_DEPTH24_STENCIL8:
        case LOCAL_GL_DEPTH_COMPONENT32:
            primarySize = 4*pixels;
            break;
        case LOCAL_GL_RGB16F:
            primarySize = 2*3*pixels;
            break;
        case LOCAL_GL_RGBA16F:
            primarySize = 2*4*pixels;
            break;
        case LOCAL_GL_RGB32F:
            primarySize = 4*3*pixels;
            break;
        case LOCAL_GL_RGBA32F:
            primarySize = 4*4*pixels;
            break;
        default:
            MOZ_ASSERT(false, "Unknown `primaryFormat`.");
            break;
    }

    return primarySize + secondarySize;
}
void
WebGLRenderbuffer::RenderbufferStorage(GLenum internalFormat, GLsizei width,
                                       GLsizei height) const
{
    gl::GLContext* gl = mContext->gl;

    GLenum primaryFormat = internalFormat;
    GLenum secondaryFormat = 0;

    if (NeedsDepthStencilEmu(mContext->gl, primaryFormat)) {
        primaryFormat = DepthStencilDepthFormat(gl);
        secondaryFormat = LOCAL_GL_STENCIL_INDEX8;
    }

    gl->fRenderbufferStorage(LOCAL_GL_RENDERBUFFER, primaryFormat, width, height);

    if (!mSecondaryRB) {
        MOZ_ASSERT(!secondaryFormat);
        return;
    }
    // We can't leave the secondary RB unspecified either, since we should
    // handle the case where we attach a non-depth-stencil RB to a
    // depth-stencil attachment point, or attach this depth-stencil RB to a
    // non-depth-stencil attachment point.
    gl::ScopedBindRenderbuffer autoRB(gl, mSecondaryRB);
    if (secondaryFormat) {
        gl->fRenderbufferStorage(LOCAL_GL_RENDERBUFFER, secondaryFormat, width, height);
    } else {
        gl->fRenderbufferStorage(LOCAL_GL_RENDERBUFFER, LOCAL_GL_RGBA4, 1, 1);
    }
}
void
WebGLRenderbuffer::RenderbufferStorage(GLsizei samples,
                                       const webgl::FormatUsageInfo* format,
                                       GLsizei width, GLsizei height)
{
    MOZ_ASSERT(mContext->mBoundRenderbuffer == this);


    gl::GLContext* gl = mContext->gl;
    MOZ_ASSERT(samples >= 0 && samples <= 256); // Sanity check.

    GLenum primaryFormat = format->format->sizedFormat;
    GLenum secondaryFormat = 0;

    if (NeedsDepthStencilEmu(mContext->gl, primaryFormat)) {
        primaryFormat = DepthStencilDepthFormat(gl);
        secondaryFormat = LOCAL_GL_STENCIL_INDEX8;
    }

    RenderbufferStorageMaybeMultisample(gl, samples, primaryFormat, width,
                                        height);

    if (mSecondaryRB) {
        // We can't leave the secondary RB unspecified either, since we should
        // handle the case where we attach a non-depth-stencil RB to a
        // depth-stencil attachment point, or attach this depth-stencil RB to a
        // non-depth-stencil attachment point.
        gl::ScopedBindRenderbuffer autoRB(gl, mSecondaryRB);
        if (secondaryFormat) {
            RenderbufferStorageMaybeMultisample(gl, samples, secondaryFormat, width,
                                                height);
        } else {
            RenderbufferStorageMaybeMultisample(gl, samples, LOCAL_GL_RGBA4, 1, 1);
        }
    }

    mSamples = samples;
    mFormat = format;
    mWidth = width;
    mHeight = height;
    mImageDataStatus = WebGLImageDataStatus::UninitializedImageData;
    mIsUsingSecondary = bool(secondaryFormat);

    InvalidateStatusOfAttachedFBs();
}