/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "WebGLTransformFeedback.h" #include "GLContext.h" #include "mozilla/dom/WebGL2RenderingContextBinding.h" #include "WebGL2Context.h" #include "WebGLProgram.h" namespace mozilla { WebGLTransformFeedback::WebGLTransformFeedback(WebGLContext* webgl, GLuint tf) : WebGLRefCountedObject(webgl) , mGLName(tf) , mIndexedBindings(webgl->mGLMaxTransformFeedbackSeparateAttribs) , mIsPaused(false) , mIsActive(false) { mContext->mTransformFeedbacks.insertBack(this); } WebGLTransformFeedback::~WebGLTransformFeedback() { DeleteOnce(); } void WebGLTransformFeedback::Delete() { if (mGLName) { mContext->MakeContextCurrent(); mContext->gl->fDeleteTransformFeedbacks(1, &mGLName); } removeFrom(mContext->mTransformFeedbacks); } //////////////////////////////////////// void WebGLTransformFeedback::BeginTransformFeedback(GLenum primMode) { const char funcName[] = "beginTransformFeedback"; if (mIsActive) return mContext->ErrorInvalidOperation("%s: Already active.", funcName); switch (primMode) { case LOCAL_GL_POINTS: case LOCAL_GL_LINES: case LOCAL_GL_TRIANGLES: break; default: mContext->ErrorInvalidEnum("%s: `primitiveMode` must be one of POINTS, LINES, or" " TRIANGLES.", funcName); return; } const auto& prog = mContext->mCurrentProgram; if (!prog || !prog->IsLinked() || !prog->LinkInfo()->componentsPerTFVert.size()) { mContext->ErrorInvalidOperation("%s: Current program not valid for transform" " feedback.", funcName); return; } const auto& linkInfo = prog->LinkInfo(); const auto& componentsPerTFVert = linkInfo->componentsPerTFVert; size_t minVertCapacity = SIZE_MAX; for (size_t i = 0; i < componentsPerTFVert.size(); i++) { const auto& indexedBinding = mIndexedBindings[i]; const auto& componentsPerVert = componentsPerTFVert[i]; const auto& buffer = indexedBinding.mBufferBinding; if (!buffer) { mContext->ErrorInvalidOperation("%s: No buffer attached to required transform" " feedback index %u.", funcName, (uint32_t)i); return; } const size_t vertCapacity = buffer->ByteLength() / 4 / componentsPerVert; minVertCapacity = std::min(minVertCapacity, vertCapacity); } //// const auto& gl = mContext->gl; gl->MakeCurrent(); gl->fBeginTransformFeedback(primMode); //// mIsActive = true; MOZ_ASSERT(!mIsPaused); mActive_Program = prog; mActive_PrimMode = primMode; mActive_VertPosition = 0; mActive_VertCapacity = minVertCapacity; //// mActive_Program->mNumActiveTFOs++; } void WebGLTransformFeedback::EndTransformFeedback() { const char funcName[] = "endTransformFeedback"; if (!mIsActive) return mContext->ErrorInvalidOperation("%s: Not active.", funcName); //// const auto& gl = mContext->gl; gl->MakeCurrent(); gl->fEndTransformFeedback(); //// mIsActive = false; mIsPaused = false; //// mActive_Program->mNumActiveTFOs--; } void WebGLTransformFeedback::PauseTransformFeedback() { const char funcName[] = "pauseTransformFeedback"; if (!mIsActive || mIsPaused) { mContext->ErrorInvalidOperation("%s: Not active or is paused.", funcName); return; } //// const auto& gl = mContext->gl; gl->MakeCurrent(); gl->fPauseTransformFeedback(); //// mIsPaused = true; } void WebGLTransformFeedback::ResumeTransformFeedback() { const char funcName[] = "resumeTransformFeedback"; if (!mIsPaused) return mContext->ErrorInvalidOperation("%s: Not paused.", funcName); if (mContext->mCurrentProgram != mActive_Program) { mContext->ErrorInvalidOperation("%s: Active program differs from original.", funcName); return; } //// const auto& gl = mContext->gl; gl->MakeCurrent(); gl->fResumeTransformFeedback(); //// MOZ_ASSERT(mIsActive); mIsPaused = false; } //////////////////////////////////////// void WebGLTransformFeedback::AddBufferBindCounts(int8_t addVal) const { const GLenum target = LOCAL_GL_TRANSFORM_FEEDBACK_BUFFER; WebGLBuffer::AddBindCount(target, mGenericBufferBinding.get(), addVal); for (const auto& binding : mIndexedBindings) { WebGLBuffer::AddBindCount(target, binding.mBufferBinding.get(), addVal); } } //////////////////////////////////////// JSObject* WebGLTransformFeedback::WrapObject(JSContext* cx, JS::Handle givenProto) { return dom::WebGLTransformFeedbackBinding::Wrap(cx, this, givenProto); } NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(WebGLTransformFeedback, AddRef) NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(WebGLTransformFeedback, Release) NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(WebGLTransformFeedback, mGenericBufferBinding, mIndexedBindings, mActive_Program) } // namespace mozilla