diff --git a/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp b/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp index 00771927fb..442017c8b0 100644 --- a/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp +++ b/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp @@ -360,7 +360,7 @@ void OpenGLDisplayPlugin::customizeContext() { auto presentThread = DependencyManager::get(); Q_ASSERT(thread() == presentThread->thread()); - getGLBackend()->setCameraCorrection(mat4(), mat4(), true, true); + getBackend()->setCameraCorrection(mat4(), mat4(), true, true); for (auto& cursorValue : _cursorsData) { auto& cursorData = cursorValue.second; @@ -704,7 +704,7 @@ void OpenGLDisplayPlugin::present(const std::shared_ptr& if (_currentFrame) { auto correction = getViewCorrection(); - getGLBackend()->setCameraCorrection(correction, _prevRenderView, true); + getBackend()->setCameraCorrection(correction, _prevRenderView, true); _prevRenderView = correction * _currentFrame->view; { withPresentThreadLock([&] { @@ -829,7 +829,9 @@ QImage OpenGLDisplayPlugin::getScreenshot(float aspectRatio) { corner.y = round((size.y - bestSize.y) / 2.0f); } QImage screenshot(bestSize.x, bestSize.y, QImage::Format_ARGB32); - getGLBackend()->downloadFramebuffer(_compositeFramebuffer, ivec4(corner, bestSize), screenshot); + withOtherThreadContext([&] { + getBackend()->downloadFramebuffer(_compositeFramebuffer, ivec4(corner, bestSize), screenshot); + }); return screenshot.mirrored(false, true); } @@ -839,7 +841,9 @@ QImage OpenGLDisplayPlugin::getSecondaryCameraScreenshot() { gpu::Vec4i region(0, 0, secondaryCameraFramebuffer->getWidth(), secondaryCameraFramebuffer->getHeight()); QImage screenshot(region.z, region.w, QImage::Format_ARGB32); - getGLBackend()->downloadFramebuffer(secondaryCameraFramebuffer, region, screenshot); + withOtherThreadContext([&] { + getBackend()->downloadFramebuffer(secondaryCameraFramebuffer, region, screenshot); + }); return screenshot.mirrored(false, true); } @@ -876,19 +880,13 @@ bool OpenGLDisplayPlugin::beginFrameRender(uint32_t frameIndex) { return Parent::beginFrameRender(frameIndex); } -gpu::gl::GLBackend* OpenGLDisplayPlugin::getGLBackend() { - if (!_gpuContext || !_gpuContext->getBackend()) { - return nullptr; +const gpu::BackendPointer& OpenGLDisplayPlugin::getBackend() const { + static const gpu::BackendPointer EMPTY; + + if (!_gpuContext) { + return EMPTY; } - auto backend = _gpuContext->getBackend().get(); -#if defined(Q_OS_MAC) - // Should be dynamic_cast, but that doesn't work in plugins on OSX - auto glbackend = static_cast(backend); -#else - auto glbackend = dynamic_cast(backend); -#endif - - return glbackend; + return _gpuContext->getBackend(); } void OpenGLDisplayPlugin::render(std::function f) { @@ -908,6 +906,8 @@ void OpenGLDisplayPlugin::updateCompositeFramebuffer() { } void OpenGLDisplayPlugin::copyTextureToQuickFramebuffer(NetworkTexturePointer networkTexture, QOpenGLFramebufferObject* target, GLsync* fenceSync) { + +#if 0 #if !defined(USE_GLES) auto glBackend = const_cast(*this).getGLBackend(); withOtherThreadContext([&] { @@ -956,6 +956,7 @@ void OpenGLDisplayPlugin::copyTextureToQuickFramebuffer(NetworkTexturePointer ne *fenceSync = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0); }); #endif +#endif } gpu::PipelinePointer OpenGLDisplayPlugin::getRenderTexturePipeline() { diff --git a/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.h b/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.h index 0df0d9ac3e..a61d0f242f 100644 --- a/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.h +++ b/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.h @@ -196,7 +196,7 @@ protected: f(); } - gpu::gl::GLBackend* getGLBackend(); + const gpu::BackendPointer& getBackend() const; // Any resource shared by the main thread and the presentation thread must // be serialized through this mutex diff --git a/libraries/gpu/src/gpu/Context.h b/libraries/gpu/src/gpu/Context.h index 2b6490a67a..78804955c1 100644 --- a/libraries/gpu/src/gpu/Context.h +++ b/libraries/gpu/src/gpu/Context.h @@ -204,17 +204,17 @@ public: virtual void shutdown() {} virtual const std::string& getVersion() const = 0; - + virtual void setCameraCorrection(const Mat4& correction, const Mat4& prevRenderView, bool reset = false) = 0; + virtual uint32_t getTextureID(const TexturePointer& texture) = 0; void setStereoState(const StereoState& stereo) { _stereo = stereo; } - virtual void render(const Batch& batch) = 0; virtual void syncCache() = 0; virtual void syncProgram(const gpu::ShaderPointer& program) = 0; virtual void recycle() const = 0; virtual void downloadFramebuffer(const FramebufferPointer& srcFramebuffer, const Vec4i& region, QImage& destImage) = 0; virtual void setCameraCorrection(const Mat4& correction, const Mat4& prevRenderView, bool primary, bool reset = false) {} - virtual bool supportedTextureFormat(const gpu::Element& format) = 0; + virtual bool supportedTextureFormat(const gpu::Element& format) const = 0; // Shared header between C++ and GLSL #include "TransformCamera_shared.slh" @@ -264,6 +264,32 @@ public: static ContextMetricSize textureResourcePopulatedGPUMemSize; static ContextMetricSize textureResourceIdealGPUMemSize; +protected: + // MUST only be called on the rendering thread. + // + // Consuming a frame applies any updates queued from the recording thread and applies them to the + // shadow copy used by the rendering thread. + // + // EVERY frame generated MUST be consumed, regardless of whether the frame is actually executed, + // or the buffer shadow copies can become unsynced from the recording thread copies. + // + // Consuming a frame is idempotent, as the frame encapsulates the updates and clears them out as + // it applies them, so calling it more than once on a given frame will have no effect after the + // first time + // + // + // This is automatically called by executeFrame, so you only need to call it if you + // have frames you aren't going to otherwise execute, for instance when a display plugin is + // being disabled, or in the null display plugin where no rendering actually occurs + //void consumeFrameUpdates(const FramePointer& frame) const; + + // MUST only be called on the rendering thread + // + // Executes a frame, applying any updates contained in the frame batches to the rendering + // thread shadow copies. Either executeFrame or consumeFrameUpdates MUST be called on every frame + // generated, IN THE ORDER they were generated. + virtual void executeFrame(const FramePointer& frame) = 0; + virtual bool isStereo() const { return _stereo.isStereo(); } @@ -352,7 +378,7 @@ public: // have frames you aren't going to otherwise execute, for instance when a display plugin is // being disabled, or in the null display plugin where no rendering actually occurs void consumeFrameUpdates(const FramePointer& frame) const; - + const BackendPointer& getBackend() const { return _backend; } void enableStereo(bool enable = true); diff --git a/plugins/openvr/src/OpenVrDisplayPlugin.cpp b/plugins/openvr/src/OpenVrDisplayPlugin.cpp index b5c1f713e7..38c627cfc9 100644 --- a/plugins/openvr/src/OpenVrDisplayPlugin.cpp +++ b/plugins/openvr/src/OpenVrDisplayPlugin.cpp @@ -528,7 +528,7 @@ void OpenVrDisplayPlugin::customizeContext() { _renderTargetSize.y, gpu::Texture::SINGLE_MIP, gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_POINT)); } - _compositeInfos[i].textureID = getGLBackend()->getTextureID(_compositeInfos[i].texture); + _compositeInfos[i].textureID = getBackend()->getTextureID(_compositeInfos[i].texture); } _submitThread->_canvas = _submitCanvas; _submitThread->start(QThread::HighPriority); @@ -649,7 +649,7 @@ void OpenVrDisplayPlugin::compositeLayers() { glFlush(); if (!newComposite.textureID) { - newComposite.textureID = getGLBackend()->getTextureID(newComposite.texture); + newComposite.textureID = getBackend()->getTextureID(newComposite.texture); } withPresentThreadLock([&] { _submitThread->update(newComposite); }); } @@ -666,7 +666,7 @@ void OpenVrDisplayPlugin::hmdPresent() { _visionSqueezeParametersBuffer.edit()._rightProjection = _eyeProjections[1]; _visionSqueezeParametersBuffer.edit()._hmdSensorMatrix = _currentPresentFrameInfo.presentPose; - GLuint glTexId = getGLBackend()->getTextureID(_compositeFramebuffer->getRenderBuffer(0)); + GLuint glTexId = getBackend()->getTextureID(_compositeFramebuffer->getRenderBuffer(0)); vr::Texture_t vrTexture{ (void*)(uintptr_t)glTexId, vr::TextureType_OpenGL, vr::ColorSpace_Auto }; vr::VRCompositor()->Submit(vr::Eye_Left, &vrTexture, &OPENVR_TEXTURE_BOUNDS_LEFT); vr::VRCompositor()->Submit(vr::Eye_Right, &vrTexture, &OPENVR_TEXTURE_BOUNDS_RIGHT);