bool WebGLFramebuffer::isAttachmentComplete(WebGLAttachment* attachedObject, GLenum attachment, const char** reason) const
{
    ASSERT(attachedObject && attachedObject->valid());
    ASSERT(reason);

    GLenum internalformat = attachedObject->format();

    switch (attachment) {
    case GL_DEPTH_ATTACHMENT:
        if (!isDepthRenderable(internalformat, context()->isWebGL2OrHigher())) {
            *reason = "the internalformat of the attached image is not depth-renderable";
            return false;
        }
        break;
    case GL_STENCIL_ATTACHMENT:
        if (!isStencilRenderable(internalformat, context()->isWebGL2OrHigher())) {
            *reason = "the internalformat of the attached image is not stencil-renderable";
            return false;
        }
        break;
    case GL_DEPTH_STENCIL_ATTACHMENT:
        ASSERT(!context()->isWebGL2OrHigher());
        if (internalformat != GL_DEPTH_STENCIL_OES) {
            *reason = "the internalformat of the attached image is not DEPTH_STENCIL";
            return false;
        }
        break;
    default:
        ASSERT(attachment == GL_COLOR_ATTACHMENT0 || (attachment > GL_COLOR_ATTACHMENT0 && attachment < static_cast<GLenum>(GL_COLOR_ATTACHMENT0 + context()->maxColorAttachments())));
        if (!isColorRenderable(internalformat, context()->extensionEnabled(EXTColorBufferFloatName))) {
            *reason = "the internalformat of the attached image is not color-renderable";
            return false;
        }
        break;
    }

    if (!attachedObject->width() || !attachedObject->height()) {
        *reason = "attachment has a 0 dimension";
        return false;
    }

    if (attachedObject->object()->isTexture() && !attachedObject->isCubeComplete()) {
        *reason = "attachment is not cube complete";
        return false;
    }

    return true;
}
Example #2
0
bool WebGLFramebuffer::isAttachmentComplete(WebGLAttachment* attachedObject, GLenum attachment, const char** reason) const
{
    ASSERT(attachedObject && attachedObject->valid());
    ASSERT(reason);

    GLenum internalformat = attachedObject->format();
    WebGLSharedObject* object = attachedObject->object();
    ASSERT(object && (object->isTexture() || object->isRenderbuffer()));

    if (attachment == GL_DEPTH_ATTACHMENT) {
        if (object->isRenderbuffer()) {
            if (internalformat != GL_DEPTH_COMPONENT16) {
                *reason = "the internalformat of the attached renderbuffer is not DEPTH_COMPONENT16";
                return false;
            }
        } else if (object->isTexture()) {
            GLenum type = attachedObject->type();
            if (!(context()->extensionEnabled(WebGLDepthTextureName) && internalformat == GL_DEPTH_COMPONENT
                && (type == GL_UNSIGNED_SHORT || type == GL_UNSIGNED_INT))) {
                *reason = "the attached texture is not a depth texture";
                return false;
            }
        }
    } else if (attachment == GL_STENCIL_ATTACHMENT) {
        // Depend on the underlying GL drivers to check stencil textures
        // and check renderbuffer type here only.
        if (object->isRenderbuffer()) {
            if (internalformat != GL_STENCIL_INDEX8) {
                *reason = "the internalformat of the attached renderbuffer is not STENCIL_INDEX8";
                return false;
            }
        }
    } else if (attachment == GC3D_DEPTH_STENCIL_ATTACHMENT_WEBGL) {
        if (object->isRenderbuffer()) {
            if (internalformat != GL_DEPTH_STENCIL_OES) {
                *reason = "the internalformat of the attached renderbuffer is not DEPTH_STENCIL";
                return false;
            }
        } else if (object->isTexture()) {
            GLenum type = attachedObject->type();
            if (!(context()->extensionEnabled(WebGLDepthTextureName) && internalformat == GL_DEPTH_STENCIL_OES
                && type == GL_UNSIGNED_INT_24_8_OES)) {
                *reason = "the attached texture is not a DEPTH_STENCIL texture";
                return false;
            }
        }
    } else if (attachment == GL_COLOR_ATTACHMENT0
        || (context()->extensionEnabled(WebGLDrawBuffersName) && attachment > GL_COLOR_ATTACHMENT0
            && attachment < static_cast<GLenum>(GL_COLOR_ATTACHMENT0 + context()->maxColorAttachments()))) {
        if (object->isRenderbuffer()) {
            if (!isColorRenderable(internalformat)) {
                *reason = "the internalformat of the attached renderbuffer is not color-renderable";
                return false;
            }
        } else if (object->isTexture()) {
            GLenum type = attachedObject->type();
            if (internalformat != GL_RGBA && internalformat != GL_RGB
                && !(internalformat == GL_SRGB_ALPHA_EXT && context()->extensionEnabled(EXTsRGBName))) {
                *reason = "the internalformat of the attached texture is not color-renderable";
                return false;
            }
            // TODO: WEBGL_color_buffer_float and EXT_color_buffer_half_float extensions have not been implemented in
            // WebGL yet. It would be better to depend on the underlying GL drivers to check on rendering to floating point textures
            // and add the check back to WebGL when above two extensions are implemented.
            // Assume UNSIGNED_BYTE is renderable here without the need to explicitly check if GL_OES_rgb8_rgba8 extension is supported.
            if (type != GL_UNSIGNED_BYTE
                && type != GL_UNSIGNED_SHORT_5_6_5
                && type != GL_UNSIGNED_SHORT_4_4_4_4
                && type != GL_UNSIGNED_SHORT_5_5_5_1
                && !(type == GL_FLOAT && context()->extensionEnabled(OESTextureFloatName))
                && !(type == GL_HALF_FLOAT_OES && context()->extensionEnabled(OESTextureHalfFloatName))) {
                *reason = "unsupported type: The attached texture is not supported to be rendered to";
                return false;
            }
        }
    } else {
        *reason = "unknown framebuffer attachment point";
        return false;
    }

    if (!attachedObject->width() || !attachedObject->height()) {
        *reason = "attachment has a 0 dimension";
        return false;
    }
    return true;
}