Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'intern/vamr/intern/GraphicsBinding.cc')
-rw-r--r--intern/vamr/intern/GraphicsBinding.cc308
1 files changed, 308 insertions, 0 deletions
diff --git a/intern/vamr/intern/GraphicsBinding.cc b/intern/vamr/intern/GraphicsBinding.cc
new file mode 100644
index 00000000000..f9b4216b3e3
--- /dev/null
+++ b/intern/vamr/intern/GraphicsBinding.cc
@@ -0,0 +1,308 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+/** \file
+ * \ingroup VAMR
+ */
+
+#include <algorithm>
+#include <list>
+#include <sstream>
+
+#if 0
+# if defined(WITH_X11)
+# include "GHOST_ContextGLX.h"
+# elif defined(WIN32)
+# include "GHOST_ContextWGL.h"
+# include "GHOST_ContextD3D.h"
+# endif
+#endif
+#include "VAMR_capi.h"
+
+#include "IGraphicsBinding.h"
+#include "utils.h"
+
+namespace VAMR {
+
+static bool choose_swapchain_format_from_candidates(std::vector<int64_t> gpu_binding_formats,
+ std::vector<int64_t> runtime_formats,
+ int64_t *r_result)
+{
+ if (gpu_binding_formats.empty()) {
+ return false;
+ }
+
+ auto res = std::find_first_of(gpu_binding_formats.begin(),
+ gpu_binding_formats.end(),
+ runtime_formats.begin(),
+ runtime_formats.end());
+ if (res == gpu_binding_formats.end()) {
+ return false;
+ }
+
+ *r_result = *res;
+ return true;
+}
+
+class GraphicsBindingOpenGL : public IGraphicsBinding {
+ public:
+ ~GraphicsBindingOpenGL()
+ {
+ if (m_fbo != 0) {
+ glDeleteFramebuffers(1, &m_fbo);
+ }
+ }
+
+ bool checkVersionRequirements(GHOST_Context *ghost_ctx,
+ XrInstance instance,
+ XrSystemId system_id,
+ std::string *r_requirement_info) const override
+ {
+#if 0
+# if defined(WITH_X11)
+ GHOST_ContextGLX *ctx_gl = static_cast<GHOST_ContextGLX *>(ghost_ctx);
+# else
+ GHOST_ContextWGL *ctx_gl = static_cast<GHOST_ContextWGL *>(ghost_ctx);
+# endif
+ XrGraphicsRequirementsOpenGLKHR gpu_requirements{XR_TYPE_GRAPHICS_REQUIREMENTS_OPENGL_KHR};
+ const XrVersion gl_version = XR_MAKE_VERSION(
+ ctx_gl->m_contextMajorVersion, ctx_gl->m_contextMinorVersion, 0);
+
+ xrGetOpenGLGraphicsRequirementsKHR(instance, system_id, &gpu_requirements);
+
+ if (r_requirement_info) {
+ std::ostringstream strstream;
+ strstream << "Min OpenGL version "
+ << XR_VERSION_MAJOR(gpu_requirements.minApiVersionSupported) << "."
+ << XR_VERSION_MINOR(gpu_requirements.minApiVersionSupported) << std::endl;
+ strstream << "Max OpenGL version "
+ << XR_VERSION_MAJOR(gpu_requirements.maxApiVersionSupported) << "."
+ << XR_VERSION_MINOR(gpu_requirements.maxApiVersionSupported) << std::endl;
+
+ *r_requirement_info = strstream.str();
+ }
+
+ return (gl_version >= gpu_requirements.minApiVersionSupported) &&
+ (gl_version <= gpu_requirements.maxApiVersionSupported);
+#endif
+ return true;
+ }
+
+ void initFromGhostContext(GHOST_Context *ghost_ctx) override
+ {
+#if 0
+# if defined(WITH_X11)
+ GHOST_ContextGLX *ctx_glx = static_cast<GHOST_ContextGLX *>(ghost_ctx);
+ XVisualInfo *visual_info = glXGetVisualFromFBConfig(ctx_glx->m_display, ctx_glx->m_fbconfig);
+
+ oxr_binding.glx.type = XR_TYPE_GRAPHICS_BINDING_OPENGL_XLIB_KHR;
+ oxr_binding.glx.xDisplay = ctx_glx->m_display;
+ oxr_binding.glx.glxFBConfig = ctx_glx->m_fbconfig;
+ oxr_binding.glx.glxDrawable = ctx_glx->m_window;
+ oxr_binding.glx.glxContext = ctx_glx->m_context;
+ oxr_binding.glx.visualid = visual_info->visualid;
+# elif defined(WIN32)
+ GHOST_ContextWGL *ctx_wgl = static_cast<GHOST_ContextWGL *>(ghost_ctx);
+
+ oxr_binding.wgl.type = XR_TYPE_GRAPHICS_BINDING_OPENGL_WIN32_KHR;
+ oxr_binding.wgl.hDC = ctx_wgl->m_hDC;
+ oxr_binding.wgl.hGLRC = ctx_wgl->m_hGLRC;
+# endif
+#endif
+
+ /* Generate a framebuffer to use for blitting into the texture */
+ glGenFramebuffers(1, &m_fbo);
+ }
+
+ bool chooseSwapchainFormat(const std::vector<int64_t> &runtime_formats,
+ int64_t *r_result) const override
+ {
+ std::vector<int64_t> gpu_binding_formats = {GL_RGBA8};
+ return choose_swapchain_format_from_candidates(gpu_binding_formats, runtime_formats, r_result);
+ }
+
+ std::vector<XrSwapchainImageBaseHeader *> createSwapchainImages(uint32_t image_count) override
+ {
+ std::vector<XrSwapchainImageOpenGLKHR> ogl_images(image_count);
+ std::vector<XrSwapchainImageBaseHeader *> base_images;
+
+ // Need to return vector of base header pointers, so of a different type. Need to build a new
+ // list with this type, and keep the initial one alive.
+ for (XrSwapchainImageOpenGLKHR &image : ogl_images) {
+ image.type = XR_TYPE_SWAPCHAIN_IMAGE_OPENGL_KHR;
+ base_images.push_back(reinterpret_cast<XrSwapchainImageBaseHeader *>(&image));
+ }
+
+ // Keep alive.
+ m_image_cache.push_back(std::move(ogl_images));
+
+ return base_images;
+ }
+
+ void submitToSwapchain(XrSwapchainImageBaseHeader *swapchain_image,
+ const VAMR_DrawViewInfo *draw_info) override
+ {
+ XrSwapchainImageOpenGLKHR *ogl_swapchain_image = reinterpret_cast<XrSwapchainImageOpenGLKHR *>(
+ swapchain_image);
+
+ glBindFramebuffer(GL_DRAW_FRAMEBUFFER, m_fbo);
+
+ glFramebufferTexture2D(
+ GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, ogl_swapchain_image->image, 0);
+
+ glBlitFramebuffer(draw_info->ofsx,
+ draw_info->ofsy,
+ draw_info->ofsx + draw_info->width,
+ draw_info->ofsy + draw_info->height,
+ draw_info->ofsx,
+ draw_info->ofsy,
+ draw_info->ofsx + draw_info->width,
+ draw_info->ofsy + draw_info->height,
+ GL_COLOR_BUFFER_BIT,
+ GL_LINEAR);
+
+ glBindFramebuffer(GL_FRAMEBUFFER, 0);
+ }
+
+ private:
+ std::list<std::vector<XrSwapchainImageOpenGLKHR>> m_image_cache;
+ GLuint m_fbo{0};
+};
+
+#ifdef WIN32
+class GraphicsBindingD3D : public IGraphicsBinding {
+ public:
+ ~GraphicsBindingD3D()
+ {
+ if (m_shared_resource) {
+ m_ghost_ctx->disposeSharedOpenGLResource(m_shared_resource);
+ }
+ }
+
+ bool checkVersionRequirements(GHOST_Context *ghost_ctx,
+ XrInstance instance,
+ XrSystemId system_id,
+ std::string *r_requirement_info) const override
+ {
+
+ GHOST_ContextD3D *ctx_dx = static_cast<GHOST_ContextD3D *>(ghost_ctx);
+ XrGraphicsRequirementsD3D11KHR gpu_requirements{XR_TYPE_GRAPHICS_REQUIREMENTS_D3D11_KHR};
+
+ xrGetD3D11GraphicsRequirementsKHR(instance, system_id, &gpu_requirements);
+
+ if (r_requirement_info) {
+ std::ostringstream strstream;
+ strstream << "Min DirectX 11 Feature Level " << gpu_requirements.minFeatureLevel
+ << std::endl;
+
+ *r_requirement_info = std::move(strstream.str());
+ }
+
+ return ctx_dx->m_device->GetFeatureLevel() >= gpu_requirements.minFeatureLevel;
+ }
+
+ void initFromGhostContext(GHOST_Context *ghost_ctx) override
+ {
+ GHOST_ContextD3D *ctx_d3d = static_cast<GHOST_ContextD3D *>(ghost_ctx);
+
+ oxr_binding.d3d11.type = XR_TYPE_GRAPHICS_BINDING_D3D11_KHR;
+ oxr_binding.d3d11.device = ctx_d3d->m_device;
+ m_ghost_ctx = ctx_d3d;
+ }
+
+ bool chooseSwapchainFormat(const std::vector<int64_t> &runtime_formats,
+ int64_t *r_result) const override
+ {
+ std::vector<int64_t> gpu_binding_formats = {DXGI_FORMAT_R8G8B8A8_UNORM};
+ return choose_swapchain_format_from_candidates(gpu_binding_formats, runtime_formats, r_result);
+ }
+
+ std::vector<XrSwapchainImageBaseHeader *> createSwapchainImages(uint32_t image_count) override
+ {
+ std::vector<XrSwapchainImageD3D11KHR> d3d_images(image_count);
+ std::vector<XrSwapchainImageBaseHeader *> base_images;
+
+ // Need to return vector of base header pointers, so of a different type. Need to build a new
+ // list with this type, and keep the initial one alive.
+ for (XrSwapchainImageD3D11KHR &image : d3d_images) {
+ image.type = XR_TYPE_SWAPCHAIN_IMAGE_D3D11_KHR;
+ base_images.push_back(reinterpret_cast<XrSwapchainImageBaseHeader *>(&image));
+ }
+
+ // Keep alive.
+ m_image_cache.push_back(std::move(d3d_images));
+
+ return base_images;
+ }
+
+ void submitToSwapchain(XrSwapchainImageBaseHeader *swapchain_image,
+ const VAMR_DrawViewInfo *draw_info) override
+ {
+ XrSwapchainImageD3D11KHR *d3d_swapchain_image = reinterpret_cast<XrSwapchainImageD3D11KHR *>(
+ swapchain_image);
+
+# if 0
+ /* Ideally we'd just create a render target view for the OpenXR swapchain image texture and
+ * blit from the OpenGL context into it. The NV_DX_interop extension doesn't want to work with
+ * this though. At least not with Optimus hardware. See:
+ * https://github.com/mpv-player/mpv/issues/2949#issuecomment-197262807.
+ */
+
+ ID3D11RenderTargetView *rtv;
+ CD3D11_RENDER_TARGET_VIEW_DESC rtv_desc(D3D11_RTV_DIMENSION_TEXTURE2D,
+ DXGI_FORMAT_R8G8B8A8_UNORM);
+
+ m_ghost_ctx->m_device->CreateRenderTargetView(d3d_swapchain_image->texture, &rtv_desc, &rtv);
+ if (!m_shared_resource) {
+ m_shared_resource = m_ghost_ctx->createSharedOpenGLResource(
+ draw_info->width, draw_info->height, rtv);
+ }
+ m_ghost_ctx->blitFromOpenGLContext(m_shared_resource, draw_info->width, draw_info->height);
+# else
+ if (!m_shared_resource) {
+ m_shared_resource = m_ghost_ctx->createSharedOpenGLResource(draw_info->width,
+ draw_info->height);
+ }
+ m_ghost_ctx->blitFromOpenGLContext(m_shared_resource, draw_info->width, draw_info->height);
+
+ m_ghost_ctx->m_device_ctx->OMSetRenderTargets(0, nullptr, nullptr);
+ m_ghost_ctx->m_device_ctx->CopyResource(d3d_swapchain_image->texture,
+ m_ghost_ctx->getSharedTexture2D(m_shared_resource));
+# endif
+ }
+
+ private:
+ GHOST_ContextD3D *m_ghost_ctx;
+ GHOST_SharedOpenGLResource *m_shared_resource;
+ std::list<std::vector<XrSwapchainImageD3D11KHR>> m_image_cache;
+};
+#endif // WIN32
+
+std::unique_ptr<IGraphicsBinding> GraphicsBindingCreateFromType(VAMR_GraphicsBindingType type)
+{
+ switch (type) {
+ case VAMR_GraphicsBindingTypeOpenGL:
+ return std::unique_ptr<GraphicsBindingOpenGL>(new GraphicsBindingOpenGL());
+#ifdef WIN32
+ case VAMR_GraphicsBindingTypeD3D11:
+ return std::unique_ptr<GraphicsBindingD3D>(new GraphicsBindingD3D());
+#endif
+ default:
+ return nullptr;
+ }
+}
+
+} // namespace VAMR