void
WebGLContext::DeleteBuffer(WebGLBuffer* buffer)
{
    if (IsContextLost())
        return;

    if (!ValidateObjectAllowDeletedOrNull("deleteBuffer", buffer))
        return;

    if (!buffer || buffer->IsDeleted())
        return;

    ////

    const auto fnClearIfBuffer = [&](WebGLRefPtr<WebGLBuffer>& bindPoint) {
        if (bindPoint == buffer) {
            bindPoint = nullptr;
        }
    };

    fnClearIfBuffer(mBoundArrayBuffer);
    fnClearIfBuffer(mBoundVertexArray->mElementArrayBuffer);

    // WebGL binding points
    if (IsWebGL2()) {
        fnClearIfBuffer(mBoundCopyReadBuffer);
        fnClearIfBuffer(mBoundCopyWriteBuffer);
        fnClearIfBuffer(mBoundPixelPackBuffer);
        fnClearIfBuffer(mBoundPixelUnpackBuffer);
        fnClearIfBuffer(mBoundUniformBuffer);
        fnClearIfBuffer(mBoundTransformFeedback->mGenericBufferBinding);

        if (!mBoundTransformFeedback->mIsActive) {
            for (auto& binding : mBoundTransformFeedback->mIndexedBindings) {
                fnClearIfBuffer(binding.mBufferBinding);
            }
        }

        for (auto& binding : mIndexedUniformBufferBindings) {
            fnClearIfBuffer(binding.mBufferBinding);
        }
    }

    for (int32_t i = 0; i < mGLMaxVertexAttribs; i++) {
        if (mBoundVertexArray->HasAttrib(i)) {
            fnClearIfBuffer(mBoundVertexArray->mAttribs[i].mBuf);
        }
    }

    ////

    buffer->RequestDelete();
}
void
WebGLContext::BindBufferBase(GLenum target, GLuint index, WebGLBuffer* buffer)
{
    const char funcName[] = "bindBufferBase";
    if (IsContextLost())
        return;

    if (!ValidateObjectAllowDeletedOrNull(funcName, buffer))
        return;

    if (buffer && buffer->IsDeleted())
        return ErrorInvalidOperation("%s: Cannot bind a deleted object.", funcName);

    WebGLRefPtr<WebGLBuffer>* genericBinding;
    IndexedBufferBinding* indexedBinding;
    if (!ValidateIndexedBufferBinding(funcName, target, index, &genericBinding,
                                      &indexedBinding))
    {
        return;
    }

    if (buffer && !buffer->ValidateCanBindToTarget(funcName, target))
        return;

    ////

    gl->MakeCurrent();
    gl->fBindBufferBase(target, index, buffer ? buffer->mGLName : 0);

    ////

    *genericBinding = buffer;
    indexedBinding->mBufferBinding = buffer;
    indexedBinding->mRangeStart = 0;
    indexedBinding->mRangeSize = 0;

    if (buffer) {
        buffer->SetContentAfterBind(target);
    }

    switch (target) {
    case LOCAL_GL_TRANSFORM_FEEDBACK_BUFFER:
        mBoundTransformFeedback->OnIndexedBindingsChanged();
        break;
    case LOCAL_GL_UNIFORM:
        OnUBIndexedBindingsChanged();
        break;
    }
}
bool
WebGL2Context::IsTransformFeedback(WebGLTransformFeedback* tf)
{
    if (IsContextLost())
        return false;

    if (!ValidateObjectAllowDeletedOrNull("isTransformFeedback", tf))
        return false;

    if (!tf || tf->IsDeleted())
        return false;

    MakeContextCurrent();
    return gl->fIsTransformFeedback(tf->mGLName);
}
void
WebGL2Context::DeleteTransformFeedback(WebGLTransformFeedback* tf)
{
    if (IsContextLost())
        return;

    if (!ValidateObjectAllowDeletedOrNull("deleteTransformFeedback", tf))
        return;

    if (!tf || tf->IsDeleted())
        return;

    if (mBoundTransformFeedback == tf)
        BindTransformFeedback(LOCAL_GL_TRANSFORM_FEEDBACK, nullptr);

    tf->RequestDelete();
}
示例#5
0
void
WebGLContext::BindTexture(GLenum rawTarget, WebGLTexture* newTex)
{
    if (IsContextLost())
        return;

     if (!ValidateObjectAllowDeletedOrNull("bindTexture", newTex))
        return;

    // Need to check rawTarget first before comparing against newTex->Target() as
    // newTex->Target() returns a TexTarget, which will assert on invalid value.
    WebGLRefPtr<WebGLTexture>* currentTexPtr = nullptr;
    switch (rawTarget) {
        case LOCAL_GL_TEXTURE_2D:
            currentTexPtr = &mBound2DTextures[mActiveTexture];
            break;

       case LOCAL_GL_TEXTURE_CUBE_MAP:
            currentTexPtr = &mBoundCubeMapTextures[mActiveTexture];
            break;

       case LOCAL_GL_TEXTURE_3D:
            if (!IsWebGL2())
                return ErrorInvalidEnum("bindTexture: target TEXTURE_3D is only available in WebGL version 2.0 or newer");

            currentTexPtr = &mBound3DTextures[mActiveTexture];
            break;

       default:
            return ErrorInvalidEnumInfo("bindTexture: target", rawTarget);
    }
    const TexTarget texTarget(rawTarget);

    MakeContextCurrent();

    if (newTex && !newTex->BindTexture(texTarget))
        return;

    if (!newTex) {
        gl->fBindTexture(texTarget.get(), 0);
    }

    *currentTexPtr = newTex;
}
void
WebGL2Context::BindSampler(GLuint unit, WebGLSampler* sampler)
{
    if (IsContextLost())
        return;

    if (!ValidateObjectAllowDeletedOrNull("bindSampler", sampler))
        return;

    if (GLint(unit) >= mGLMaxTextureUnits)
        return ErrorInvalidValue("bindSampler: unit must be < %d", mGLMaxTextureUnits);

    if (sampler && sampler->IsDeleted())
        return ErrorInvalidOperation("bindSampler: binding deleted sampler");

    WebGLContextUnchecked::BindSampler(unit, sampler);

    mBoundSamplers[unit] = sampler;
}
void
WebGL2Context::DeleteSampler(WebGLSampler* sampler)
{
    if (IsContextLost())
        return;

    if (!ValidateObjectAllowDeletedOrNull("deleteSampler", sampler))
        return;

    if (!sampler || sampler->IsDeleted())
        return;

    for (int n = 0; n < mGLMaxTextureUnits; n++) {
        if (mBoundSamplers[n] == sampler) {
            mBoundSamplers[n] = nullptr;
        }
    }

    sampler->RequestDelete();
}
void
WebGLContext::BindBufferRange(GLenum target, GLuint index, WebGLBuffer* buffer,
                              WebGLintptr offset, WebGLsizeiptr size)
{
    if (IsContextLost())
        return;

    if (!ValidateObjectAllowDeletedOrNull("bindBufferRange", buffer))
        return;

    // silently ignore a deleted buffer
    if (buffer && buffer->IsDeleted())
        return;

    // ValidateBufferTarget
    switch (target) {
    case LOCAL_GL_TRANSFORM_FEEDBACK_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);
    }

    if (!ValidateBufferForTarget(target, buffer, "bindBufferRange"))
        return;

    WebGLContextUnchecked::BindBufferRange(target, index, buffer, offset, size);

    UpdateBoundBufferIndexed(target, index, buffer);
}
void
WebGLContext::BindBuffer(GLenum target, WebGLBuffer* buffer)
{
    if (IsContextLost())
        return;

    if (!ValidateObjectAllowDeletedOrNull("bindBuffer", buffer))
        return;

    // silently ignore a deleted buffer
    if (buffer && buffer->IsDeleted())
        return;

    if (!ValidateBufferTarget(target, "bindBuffer"))
        return;

    if (!ValidateBufferForTarget(target, buffer, "bindBuffer"))
        return;

    WebGLContextUnchecked::BindBuffer(target, buffer);

    UpdateBoundBuffer(target, buffer);
}
示例#10
0
void
WebGLContext::BindBufferRange(GLenum target, GLuint index, WebGLBuffer* buffer,
                              WebGLintptr offset, WebGLsizeiptr size)
{
    const char funcName[] = "bindBufferRange";
    if (IsContextLost())
        return;

    if (!ValidateObjectAllowDeletedOrNull(funcName, buffer))
        return;

    if (buffer && buffer->IsDeleted())
        return ErrorInvalidOperation("%s: Cannot bind a deleted object.", funcName);

    if (!ValidateNonNegative(funcName, "offset", offset) ||
        !ValidateNonNegative(funcName, "size", size))
    {
        return;
    }

    WebGLRefPtr<WebGLBuffer>* genericBinding;
    IndexedBufferBinding* indexedBinding;
    if (!ValidateIndexedBufferBinding(funcName, target, index, &genericBinding,
                                      &indexedBinding))
    {
        return;
    }

    if (buffer && !buffer->ValidateCanBindToTarget(funcName, target))
        return;

    ////

    gl->MakeCurrent();

    switch (target) {
    case LOCAL_GL_TRANSFORM_FEEDBACK_BUFFER:
        if (offset % 4 != 0 || size % 4 != 0) {
            ErrorInvalidValue("%s: For %s, `offset` and `size` must be multiples of 4.",
                              funcName, "TRANSFORM_FEEDBACK_BUFFER");
            return;
        }
        break;

    case LOCAL_GL_UNIFORM_BUFFER:
        {
            GLuint offsetAlignment = 0;
            gl->GetUIntegerv(LOCAL_GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT, &offsetAlignment);
            if (offset % offsetAlignment != 0) {
                ErrorInvalidValue("%s: For %s, `offset` must be a multiple of %s.",
                                  funcName, "UNIFORM_BUFFER",
                                  "UNIFORM_BUFFER_OFFSET_ALIGNMENT");
                return;
            }
        }
        break;
    }

    ////

#ifdef XP_MACOSX
    if (buffer && buffer->Content() == WebGLBuffer::Kind::Undefined &&
        gl->WorkAroundDriverBugs())
    {
        // BindBufferRange will fail if the buffer's contents is undefined.
        // Bind so driver initializes the buffer.
        gl->fBindBuffer(target, buffer->mGLName);
    }
#endif

    gl->fBindBufferRange(target, index, buffer ? buffer->mGLName : 0, offset, size);

    ////

    *genericBinding = buffer;
    indexedBinding->mBufferBinding = buffer;
    indexedBinding->mRangeStart = offset;
    indexedBinding->mRangeSize = size;

    if (buffer) {
        buffer->SetContentAfterBind(target);
    }

    switch (target) {
    case LOCAL_GL_TRANSFORM_FEEDBACK_BUFFER:
        mBoundTransformFeedback->OnIndexedBindingsChanged();
        break;
    case LOCAL_GL_UNIFORM:
        OnUBIndexedBindingsChanged();
        break;
    }
}
void
WebGLContext::DeleteBuffer(WebGLBuffer* buffer)
{
    if (IsContextLost())
        return;

    if (!ValidateObjectAllowDeletedOrNull("deleteBuffer", buffer))
        return;

    if (!buffer || buffer->IsDeleted())
        return;

    // TODO: Extract this into a helper function?
    if (mBoundArrayBuffer == buffer) {
        WebGLContextUnchecked::BindBuffer(LOCAL_GL_ARRAY_BUFFER, nullptr);
        mBoundArrayBuffer = nullptr;
    }

    if (mBoundVertexArray->mElementArrayBuffer == buffer) {
        WebGLContextUnchecked::BindBuffer(LOCAL_GL_ELEMENT_ARRAY_BUFFER, nullptr);
        mBoundVertexArray->mElementArrayBuffer = nullptr;
    }

    // WebGL binding points
    if (IsWebGL2()) {
        if (mBoundCopyReadBuffer == buffer)
            mBoundCopyReadBuffer = nullptr;

        if (mBoundCopyWriteBuffer == buffer)
            mBoundCopyWriteBuffer = nullptr;

        if (mBoundPixelPackBuffer == buffer)
            mBoundPixelPackBuffer = nullptr;

        if (mBoundPixelUnpackBuffer == buffer)
            mBoundPixelUnpackBuffer = nullptr;

        if (mBoundTransformFeedbackBuffer == buffer)
            mBoundTransformFeedbackBuffer = nullptr;

        if (mBoundUniformBuffer == buffer)
            mBoundUniformBuffer = nullptr;

        const size_t xfBufferCount = mBoundTransformFeedbackBuffers.Length();
        for (size_t n = 0; n < xfBufferCount; n++) {
            if (mBoundTransformFeedbackBuffers[n] == buffer) {
                mBoundTransformFeedbackBuffers[n] = nullptr;
            }
        }

        const size_t uniformBufferCount = mBoundUniformBuffers.Length();
        for (size_t n = 0; n < uniformBufferCount; n++) {
            if (mBoundUniformBuffers[n] == buffer) {
                mBoundUniformBuffers[n] = nullptr;
            }
        }
    }

    for (int32_t i = 0; i < mGLMaxVertexAttribs; i++) {
        if (mBoundVertexArray->HasAttrib(i) &&
            mBoundVertexArray->mAttribs[i].buf == buffer)
        {
            mBoundVertexArray->mAttribs[i].buf = nullptr;
        }
    }

    buffer->RequestDelete();
}