diff --git a/file/gl_obj.cc b/file/gl_obj.cc index cec445c..a26420d 100644 --- a/file/gl_obj.cc +++ b/file/gl_obj.cc @@ -744,57 +744,72 @@ struct Program { const nf7::Mutex::Resource<std::shared_ptr<Product>>& prog, const nf7::Node::Lambda::Msg& msg) { const auto& base = la->env().GetFileOrThrow(la->initiator()); + const auto& v = msg.value; if (msg.name == "draw") { const auto mode = ToDrawMode(msg.value.tuple("mode").string()); - const auto count = msg.value.tuple("count").integer<GLsizei>(); - const auto inst = msg.value.tuple("instance").integer<GLsizei>(); - const auto& fbo_path = msg.value.tuple("fbo").string(); - const auto& vao_path = msg.value.tuple("vao").string(); + const auto count = v.tuple("count").integer<GLsizei>(); + const auto inst = v.tupleOr("instance", nf7::Value::Integer{1}).integer<GLsizei>(); + const auto& fbo_path = v.tuple("fbo").string(); + const auto& vao_path = v.tuple("vao").string(); const auto& vp = msg.value.tuple("viewport"); - const auto vp_x = vp.tuple(0).integer<GLint>(); - const auto vp_y = vp.tuple(1).integer<GLint>(); - const auto vp_w = vp.tuple(2).integer<GLsizei>(); - const auto vp_h = vp.tuple(3).integer<GLsizei>(); + const auto vp_x = vp.tuple(0).integerOrScalar<GLint>(); + const auto vp_y = vp.tuple(1).integerOrScalar<GLint>(); + const auto vp_w = vp.tuple(2).integerOrScalar<GLsizei>(); + const auto vp_h = vp.tuple(3).integerOrScalar<GLsizei>(); if (vp_w < 0 || vp_h < 0) { throw nf7::Exception {"negative size viewport"}; } - // find object - auto fbo_fu = base. - ResolveOrThrow(fbo_path). - interfaceOrThrow<nf7::gl::FramebufferFactory>().Create(); - auto vao_fu = base. - ResolveOrThrow(vao_path). - interfaceOrThrow<nf7::gl::VertexArrayFactory>().Create(); - - // lock child objects - nf7::gl::Framebuffer::Meta::LockedAttachmentsFuture::Promise fbo_lock_pro; - nf7::gl::VertexArray::Meta::LockedBuffersFuture::Promise vao_lock_pro; - fbo_fu.ThenIf([la, fbo_lock_pro](auto& fbo) mutable { - (**fbo).meta().LockAttachments(la).Chain(fbo_lock_pro); - }); - vao_fu.ThenIf([la, vao_lock_pro](auto& vao) mutable { - (**vao).meta().LockBuffers(la).Chain(vao_lock_pro); - }); - - // wait for locking + // this will be triggered when all preparation done nf7::AggregatePromise apro {la}; - auto fbo_lock_fu = fbo_lock_pro.future(); - auto vao_lock_fu = vao_lock_pro.future(); - apro.Add(fbo_lock_fu); - apro.Add(vao_lock_fu); - // FIXME: deadlock when vao_fu or fbo_fu failed + // find, fetch and lock FBO + std::optional<nf7::gl::FramebufferFactory::Product> fbo_fu; + std::optional<nf7::gl::Framebuffer::Meta::LockedAttachmentsFuture> fbo_lock_fu; + { + fbo_fu = base. + ResolveOrThrow(fbo_path). + interfaceOrThrow<nf7::gl::FramebufferFactory>().Create(); + + nf7::gl::Framebuffer::Meta::LockedAttachmentsFuture::Promise fbo_lock_pro; + fbo_fu->ThenIf([la, fbo_lock_pro](auto& fbo) mutable { + (**fbo).meta().LockAttachments(la).Chain(fbo_lock_pro); + }); + + fbo_lock_fu = fbo_lock_pro.future(); + apro.Add(*fbo_lock_fu); + } + + // find, fetch and lock VAO + std::optional<nf7::gl::VertexArrayFactory::Product> vao_fu; + std::optional<nf7::gl::VertexArray::Meta::LockedBuffersFuture> vao_lock_fu; + { + vao_fu = base. + ResolveOrThrow(vao_path). + interfaceOrThrow<nf7::gl::VertexArrayFactory>().Create(); + + nf7::gl::VertexArray::Meta::LockedBuffersFuture::Promise vao_lock_pro; + vao_fu->ThenIf([la, vao_lock_pro](auto& vao) mutable { + (**vao).meta().LockBuffers(la).Chain(vao_lock_pro); + }); + + vao_lock_fu = vao_lock_pro.future(); + apro.Add(*vao_lock_fu); + } + + // execute drawing after successful locking apro.future().Then(nf7::Env::kGL, la, [=](auto&) { - if (!fbo_lock_fu.done() || !vao_lock_fu.done()) { + assert(fbo_lock_fu); + assert(vao_lock_fu); + if (!fbo_lock_fu->done() || !vao_lock_fu->done()) { // TODO std::cout << "err" << std::endl; return; } - const auto& fbo = *fbo_fu.value(); - const auto& vao = *vao_fu.value(); + const auto& fbo = *fbo_fu->value(); + const auto& vao = *vao_fu->value(); glUseProgram((*prog)->id()); glBindFramebuffer(GL_FRAMEBUFFER, fbo->id());