// // Copyright 2016 Pixar // // Licensed under the Apache License, Version 2.0 (the "Apache License") // with the following modification; you may not use this file except in // compliance with the Apache License and the following modification to it: // Section 6. Trademarks. is deleted and replaced with: // // 6. Trademarks. This License does not grant permission to use the trade // names, trademarks, service marks, or product names of the Licensor // and its affiliates, except as required to comply with Section 4(c) of // the License and to reproduce the content of the NOTICE file. // // You may obtain a copy of the Apache License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the Apache License with the above modification is // distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the Apache License for the specific // language governing permissions and limitations under the Apache License. // #include "pxr/imaging/glf/glew.h" #include "pxr/imaging/glf/glContext.h" #include "pxr/imaging/hdx/drawTargetRenderPass.h" #include "pxr/imaging/hdx/tokens.h" #include "pxr/imaging/hdSt/drawTargetRenderPassState.h" #include "pxr/imaging/hd/renderPassState.h" PXR_NAMESPACE_OPEN_SCOPE static void _ClearBuffer(GLenum buffer, GLint drawBuffer, const VtValue &value) { // XXX: There has to be a better way to handle the different formats. if (value.IsHolding()) { glClearBufferiv(buffer, drawBuffer, &value.UncheckedGet()); } else if (value.IsHolding()) { glClearBufferiv(buffer, drawBuffer, value.UncheckedGet().GetArray()); } else if (value.IsHolding()) { glClearBufferiv(buffer, drawBuffer, value.UncheckedGet().GetArray()); } else if (value.IsHolding()) { glClearBufferiv(buffer, drawBuffer, value.UncheckedGet().GetArray()); } else if (value.IsHolding()) { glClearBufferfv(buffer, drawBuffer, &value.UncheckedGet()); } else if (value.IsHolding()) { glClearBufferfv(buffer, drawBuffer, value.UncheckedGet().GetArray()); } else if (value.IsHolding()) { glClearBufferfv(buffer, drawBuffer, value.UncheckedGet().GetArray()); } else if (value.IsHolding()) { glClearBufferfv(buffer, drawBuffer, value.UncheckedGet().GetArray()); } else { TF_CODING_ERROR("Unsupported clear value type: %s", value.GetTypeName().c_str()); } } // _renderPass's collection is populated after build time, during Sync(). HdxDrawTargetRenderPass::HdxDrawTargetRenderPass(HdRenderIndex *index) : _renderPass(index, HdRprimCollection()) , _drawTargetRenderPassState(nullptr) , _drawTarget() , _drawTargetContext() , _collectionObjectVersion(0) , _hasDependentDrawTargets(false) { } HdxDrawTargetRenderPass::~HdxDrawTargetRenderPass() = default; void HdxDrawTargetRenderPass::SetDrawTarget(const GlfDrawTargetRefPtr &drawTarget) { if (drawTarget) { // XXX: The Draw Target may have been created on a different GL // context, so create a local copy here to use on this context. _drawTarget = GlfDrawTarget::New(drawTarget); _drawTargetContext = GlfGLContext::GetCurrentGLContext(); } else { _drawTarget = TfNullPtr; _drawTargetContext = nullptr; } } void HdxDrawTargetRenderPass::SetRenderPassState( const HdStDrawTargetRenderPassState *drawTargetRenderPassState) { _drawTargetRenderPassState = drawTargetRenderPassState; } void HdxDrawTargetRenderPass::SetRprimCollection(HdRprimCollection const& col) { _renderPass.SetRprimCollection(col); } bool HdxDrawTargetRenderPass::HasDependentDrawTargets() const { return _hasDependentDrawTargets; } void HdxDrawTargetRenderPass::SetHasDependentDrawTargets(bool value) { _hasDependentDrawTargets = value; } void HdxDrawTargetRenderPass::Sync() { // Update the collection object if necessary. unsigned int newCollectionVersion = _drawTargetRenderPassState->GetRprimCollectionVersion(); if (_collectionObjectVersion != newCollectionVersion) { SetRprimCollection(_drawTargetRenderPassState->GetRprimCollection()); _collectionObjectVersion = newCollectionVersion; } _renderPass.Sync(); } void HdxDrawTargetRenderPass::Prepare() { if (!_drawTarget) { return; } // Check that draw target was created on current context. if (_drawTargetContext != GlfGLContext::GetCurrentGLContext()) { // If not, create yet another draw target so that it is valid // on the current context. TF_CODING_ERROR("Given draw target was for different GL context"); SetDrawTarget(_drawTarget); } } void HdxDrawTargetRenderPass::Execute( HdRenderPassStateSharedPtr const &renderPassState, TfTokenVector const &renderTags) { if (_drawTarget) { _drawTarget->Bind(); // The draw target task is already settings flags on // HgiGraphicsCmdsDesc to clear the render buffers if the Storm texture // system is used, so clear buffers is only necessary if using // GlfDrawTarget's. _ClearBuffers(); } // XXX: Should the Raster State or Renderpass set and restore this? // save the current viewport GLint originalViewport[4]; glGetIntegerv(GL_VIEWPORT, originalViewport); const GfVec4f viewport = renderPassState->GetViewport(); glViewport(GLint(viewport[0]), GLint(viewport[1]), GLint(viewport[2]), GLint(viewport[3])); // Perform actual draw _renderPass.Execute(renderPassState, renderTags); // restore viewport glViewport(originalViewport[0], originalViewport[1], originalViewport[2], originalViewport[3]); if (_drawTarget) { _drawTarget->Unbind(); } } void HdxDrawTargetRenderPass::_ClearBuffers() { float depthValue = _drawTargetRenderPassState->GetDepthClearValue(); glClearBufferfv(GL_DEPTH, 0, &depthValue); size_t numAttachments = _drawTargetRenderPassState->GetNumColorAttachments(); for (size_t attachmentNum = 0; attachmentNum < numAttachments; ++attachmentNum) { const VtValue &clearColor = _drawTargetRenderPassState->GetColorClearValue(attachmentNum); _ClearBuffer(GL_COLOR, attachmentNum, clearColor); } } GlfDrawTargetRefPtr HdxDrawTargetRenderPass::GetDrawTarget() { return _drawTarget; } PXR_NAMESPACE_CLOSE_SCOPE