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(); }
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); }
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(); }