Fix compile/CMake errors and warnings on Linux
[blender.git] / intern / ghost / intern / GHOST_XrGraphicsBinding.cpp
1 /*
2  * This program is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU General Public License
4  * as published by the Free Software Foundation; either version 2
5  * of the License, or (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software Foundation,
14  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15  */
16
17 /** \file
18  * \ingroup GHOST
19  */
20
21 #include <algorithm>
22 #include <list>
23
24 #if defined(WITH_X11)
25 #  include "GHOST_ContextGLX.h"
26 #elif defined(WIN32)
27 #  include "GHOST_ContextWGL.h"
28 #  include "GHOST_ContextD3D.h"
29 #endif
30 #include "GHOST_C-api.h"
31 #include "GHOST_Xr_intern.h"
32
33 #include "GHOST_IXrGraphicsBinding.h"
34
35 static bool choose_swapchain_format_from_candidates(std::vector<int64_t> gpu_binding_formats,
36                                                     std::vector<int64_t> runtime_formats,
37                                                     int64_t *r_result)
38 {
39   if (gpu_binding_formats.empty()) {
40     return false;
41   }
42
43   auto res = std::find_first_of(gpu_binding_formats.begin(),
44                                 gpu_binding_formats.end(),
45                                 runtime_formats.begin(),
46                                 runtime_formats.end());
47   if (res == gpu_binding_formats.end()) {
48     return false;
49   }
50
51   *r_result = *res;
52   return true;
53 }
54
55 class GHOST_XrGraphicsBindingOpenGL : public GHOST_IXrGraphicsBinding {
56  public:
57   void initFromGhostContext(GHOST_Context *ghost_ctx) override
58   {
59 #if defined(WITH_X11)
60     GHOST_ContextGLX *ctx_glx = static_cast<GHOST_ContextGLX *>(ghost_ctx);
61     XVisualInfo *visual_info = glXGetVisualFromFBConfig(ctx_glx->m_display, ctx_glx->m_fbconfig);
62
63     oxr_binding.glx.type = XR_TYPE_GRAPHICS_BINDING_OPENGL_XLIB_KHR;
64     oxr_binding.glx.xDisplay = ctx_glx->m_display;
65     oxr_binding.glx.glxFBConfig = ctx_glx->m_fbconfig;
66     oxr_binding.glx.glxDrawable = ctx_glx->m_window;
67     oxr_binding.glx.glxContext = ctx_glx->m_context;
68     oxr_binding.glx.visualid = visual_info->visualid;
69 #elif defined(WIN32)
70     GHOST_ContextWGL *ctx_wgl = static_cast<GHOST_ContextWGL *>(ghost_ctx);
71
72     oxr_binding.wgl.type = XR_TYPE_GRAPHICS_BINDING_OPENGL_WIN32_KHR;
73     oxr_binding.wgl.hDC = ctx_wgl->m_hDC;
74     oxr_binding.wgl.hGLRC = ctx_wgl->m_hGLRC;
75 #endif
76   }
77
78   bool chooseSwapchainFormat(std::vector<int64_t> runtime_formats,
79                              int64_t *r_result) const override
80   {
81     std::vector<int64_t> gpu_binding_formats = {GL_RGBA8};
82     return choose_swapchain_format_from_candidates(gpu_binding_formats, runtime_formats, r_result);
83   }
84
85   std::vector<XrSwapchainImageBaseHeader *> createSwapchainImages(uint32_t image_count) override
86   {
87     std::vector<XrSwapchainImageOpenGLKHR> ogl_images(image_count);
88     std::vector<XrSwapchainImageBaseHeader *> base_images;
89
90     // Need to return vector of base header pointers, so of a different type. Need to build a new
91     // list with this type, and keep the initial one alive.
92     for (XrSwapchainImageOpenGLKHR &image : ogl_images) {
93       image.type = XR_TYPE_SWAPCHAIN_IMAGE_OPENGL_KHR;
94       base_images.push_back(reinterpret_cast<XrSwapchainImageBaseHeader *>(&image));
95     }
96
97     // Keep alive.
98     m_image_cache.push_back(std::move(ogl_images));
99
100     return base_images;
101   }
102
103   void drawViewBegin(XrSwapchainImageBaseHeader *swapchain_image) override
104   {
105     // TODO
106     (void)swapchain_image;
107   }
108   void drawViewEnd(XrSwapchainImageBaseHeader *swapchain_image) override
109   {
110     // TODO
111     (void)swapchain_image;
112   }
113
114  private:
115   std::list<std::vector<XrSwapchainImageOpenGLKHR>> m_image_cache;
116 };
117
118 #ifdef WIN32
119 class GHOST_XrGraphicsBindingD3D : public GHOST_IXrGraphicsBinding {
120  public:
121   void initFromGhostContext(GHOST_Context *ghost_ctx) override
122   {
123     GHOST_ContextD3D *ctx_d3d = static_cast<GHOST_ContextD3D *>(ghost_ctx);
124
125     oxr_binding.d3d11.type = XR_TYPE_GRAPHICS_BINDING_D3D11_KHR;
126     oxr_binding.d3d11.device = ctx_d3d->m_device;
127     m_ghost_ctx = ctx_d3d;
128   }
129
130   bool chooseSwapchainFormat(std::vector<int64_t> runtime_formats,
131                              int64_t *r_result) const override
132   {
133     std::vector<int64_t> gpu_binding_formats = {DXGI_FORMAT_R8G8B8A8_UNORM};
134     return choose_swapchain_format_from_candidates(gpu_binding_formats, runtime_formats, r_result);
135   }
136
137   std::vector<XrSwapchainImageBaseHeader *> createSwapchainImages(uint32_t image_count) override
138   {
139     std::vector<XrSwapchainImageD3D11KHR> d3d_images(image_count);
140     std::vector<XrSwapchainImageBaseHeader *> base_images;
141
142     // Need to return vector of base header pointers, so of a different type. Need to build a new
143     // list with this type, and keep the initial one alive.
144     for (XrSwapchainImageD3D11KHR &image : d3d_images) {
145       image.type = XR_TYPE_SWAPCHAIN_IMAGE_D3D11_KHR;
146       base_images.push_back(reinterpret_cast<XrSwapchainImageBaseHeader *>(&image));
147     }
148
149     // Keep alive.
150     m_image_cache.push_back(std::move(d3d_images));
151
152     return base_images;
153   }
154
155   void drawViewBegin(XrSwapchainImageBaseHeader *swapchain_image) override
156   {
157     // Can't we simply use the backbuffer texture? Didn't work in initial test.
158
159     XrSwapchainImageD3D11KHR *d3d_swapchain_image = reinterpret_cast<XrSwapchainImageD3D11KHR *>(
160         swapchain_image);
161     const CD3D11_RENDER_TARGET_VIEW_DESC render_target_view_desc(D3D11_RTV_DIMENSION_TEXTURE2D,
162                                                                  DXGI_FORMAT_R8G8B8A8_UNORM);
163     ID3D11RenderTargetView *render_target_view;
164     m_ghost_ctx->m_device->CreateRenderTargetView(
165         d3d_swapchain_image->texture, &render_target_view_desc, &render_target_view);
166
167     const float clear_col[] = {0.2f, 0.5f, 0.8f, 1.0f};
168     m_ghost_ctx->m_device_ctx->ClearRenderTargetView(render_target_view, clear_col);
169
170     render_target_view->Release();
171   }
172   void drawViewEnd(XrSwapchainImageBaseHeader *swapchain_image) override
173   {
174     // TODO
175     (void)swapchain_image;
176   }
177
178  private:
179   GHOST_ContextD3D *m_ghost_ctx;
180   std::list<std::vector<XrSwapchainImageD3D11KHR>> m_image_cache;
181 };
182 #endif  // WIN32
183
184 std::unique_ptr<GHOST_IXrGraphicsBinding> GHOST_XrGraphicsBindingCreateFromType(
185     GHOST_TXrGraphicsBinding type)
186 {
187   switch (type) {
188     case GHOST_kXrGraphicsOpenGL:
189       return std::unique_ptr<GHOST_XrGraphicsBindingOpenGL>(new GHOST_XrGraphicsBindingOpenGL());
190 #ifdef WIN32
191     case GHOST_kXrGraphicsD3D11:
192       return std::unique_ptr<GHOST_XrGraphicsBindingD3D>(new GHOST_XrGraphicsBindingD3D());
193 #endif
194     default:
195       return nullptr;
196   }
197 }