summaryrefslogtreecommitdiffstats
path: root/xbmc/addons/kodi-addon-dev-kit/include/kodi/gui/gl/GLonDX.h
diff options
context:
space:
mode:
authormanuel <manuel@mausz.at>2020-07-02 23:09:26 +0200
committermanuel <manuel@mausz.at>2020-07-02 23:09:26 +0200
commit5f8335c1e49ce108ef3481863833c98efa00411b (patch)
treef02b5c1c9765bb6a14c8eb42bb4f81b9face0b55 /xbmc/addons/kodi-addon-dev-kit/include/kodi/gui/gl/GLonDX.h
parente317daf081a1048904fdf0b548946fa3ba6593a7 (diff)
downloadkodi-pvr-build-master.tar.gz
kodi-pvr-build-master.tar.bz2
kodi-pvr-build-master.zip
sync with upstreamHEADmaster
Diffstat (limited to 'xbmc/addons/kodi-addon-dev-kit/include/kodi/gui/gl/GLonDX.h')
-rw-r--r--xbmc/addons/kodi-addon-dev-kit/include/kodi/gui/gl/GLonDX.h369
1 files changed, 369 insertions, 0 deletions
diff --git a/xbmc/addons/kodi-addon-dev-kit/include/kodi/gui/gl/GLonDX.h b/xbmc/addons/kodi-addon-dev-kit/include/kodi/gui/gl/GLonDX.h
new file mode 100644
index 0000000..7a6a0a1
--- /dev/null
+++ b/xbmc/addons/kodi-addon-dev-kit/include/kodi/gui/gl/GLonDX.h
@@ -0,0 +1,369 @@
1/*
2 * Copyright (C) 2005-2019 Team Kodi
3 * This file is part of Kodi - https://kodi.tv
4 *
5 * SPDX-License-Identifier: GPL-2.0-or-later
6 * See LICENSES/README.md for more information.
7 */
8
9#pragma once
10
11#include <angle_gl.h>
12#include <d3d11.h>
13#include <d3dcompiler.h>
14#include <EGL/egl.h>
15#include <EGL/eglext.h>
16#include <kodi/AddonBase.h>
17#include <kodi/gui/General.h>
18#include <wrl/client.h>
19
20#pragma comment( lib, "d3dcompiler.lib" )
21#ifndef GL_CLIENT_VERSION
22#define GL_CLIENT_VERSION 3
23#endif
24
25namespace kodi
26{
27namespace gui
28{
29namespace gl
30{
31
32class ATTRIBUTE_HIDDEN CGLonDX : public kodi::gui::IRenderHelper
33{
34public:
35 explicit CGLonDX() : m_pContext(reinterpret_cast<ID3D11DeviceContext*>(kodi::gui::GetHWContext())) {}
36 ~CGLonDX() override { destruct(); }
37
38 bool Init() override
39 {
40 EGLint egl_display_attrs[] =
41 {
42 EGL_PLATFORM_ANGLE_TYPE_ANGLE, EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE,
43 EGL_PLATFORM_ANGLE_MAX_VERSION_MAJOR_ANGLE, EGL_DONT_CARE,
44 EGL_PLATFORM_ANGLE_MAX_VERSION_MAJOR_ANGLE, EGL_DONT_CARE,
45 EGL_EXPERIMENTAL_PRESENT_PATH_ANGLE, EGL_EXPERIMENTAL_PRESENT_PATH_FAST_ANGLE,
46 EGL_NONE
47 };
48 EGLint egl_config_attrs[] =
49 {
50 EGL_RED_SIZE, 8, EGL_GREEN_SIZE, 8, EGL_BLUE_SIZE, 8, EGL_ALPHA_SIZE, 8,
51 EGL_BIND_TO_TEXTURE_RGBA, EGL_TRUE,
52 EGL_RENDERABLE_TYPE, GL_CLIENT_VERSION == 3 ? EGL_OPENGL_ES3_BIT : EGL_OPENGL_ES2_BIT,
53 EGL_SURFACE_TYPE, EGL_PBUFFER_BIT,
54 EGL_NONE
55 };
56 EGLint egl_context_attrs[] =
57 {
58 EGL_CONTEXT_CLIENT_VERSION, GL_CLIENT_VERSION, EGL_NONE
59 };
60
61 m_eglDisplay = eglGetPlatformDisplayEXT(EGL_PLATFORM_ANGLE_ANGLE, EGL_DEFAULT_DISPLAY, egl_display_attrs);
62 if (m_eglDisplay == EGL_NO_DISPLAY)
63 {
64 Log(ADDON_LOG_ERROR, "GLonDX: unable to get EGL display (%s)", eglGetErrorString());
65 return false;
66 }
67
68 if (eglInitialize(m_eglDisplay, nullptr, nullptr) != EGL_TRUE)
69 {
70 Log(ADDON_LOG_ERROR, "GLonDX: unable to init EGL display (%s)", eglGetErrorString());
71 return false;
72 }
73
74 EGLint numConfigs = 0;
75 if (eglChooseConfig(m_eglDisplay, egl_config_attrs, &m_eglConfig, 1, &numConfigs) != EGL_TRUE || numConfigs == 0)
76 {
77 Log(ADDON_LOG_ERROR, "GLonDX: unable to get EGL config (%s)", eglGetErrorString());
78 return false;
79 }
80
81 m_eglContext = eglCreateContext(m_eglDisplay, m_eglConfig, nullptr, egl_context_attrs);
82 if (m_eglContext == EGL_NO_CONTEXT)
83 {
84 Log(ADDON_LOG_ERROR, "GLonDX: unable to create EGL context (%s)", eglGetErrorString());
85 return false;
86 }
87
88 if (!createD3DResources())
89 return false;
90
91 if (eglMakeCurrent(m_eglDisplay, m_eglBuffer, m_eglBuffer, m_eglContext) != EGL_TRUE)
92 {
93 Log(ADDON_LOG_ERROR, "GLonDX: unable to make current EGL (%s)", eglGetErrorString());
94 return false;
95 }
96 return true;
97 }
98
99 void CheckGL(ID3D11DeviceContext* device)
100 {
101 if (m_pContext != device)
102 {
103 m_pSRView = nullptr;
104 m_pVShader = nullptr;
105 m_pPShader = nullptr;
106 m_pContext = device;
107
108 if (m_eglBuffer != EGL_NO_SURFACE)
109 {
110 eglMakeCurrent(m_eglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
111 eglDestroySurface(m_eglDisplay, m_eglBuffer);
112 m_eglBuffer = EGL_NO_SURFACE;
113 }
114
115 // create new resources
116 if (!createD3DResources())
117 return;
118
119 eglMakeCurrent(m_eglDisplay, m_eglBuffer, m_eglBuffer, m_eglContext);
120 }
121 }
122
123 void Begin() override
124 {
125 // confirm on begin D3D context is correct
126 CheckGL(reinterpret_cast<ID3D11DeviceContext*>(kodi::gui::GetHWContext()));
127
128 glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
129 glClear(GL_COLOR_BUFFER_BIT);
130 }
131
132 void End() override
133 {
134 glFlush();
135
136 // set our primitive shaders
137 m_pContext->VSSetShader(m_pVShader.Get(), nullptr, 0);
138 m_pContext->PSSetShader(m_pPShader.Get(), nullptr, 0);
139 m_pContext->PSSetShaderResources(0, 1, m_pSRView.GetAddressOf());
140 // draw texture
141 m_pContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP);
142 m_pContext->IASetVertexBuffers(0, 0, nullptr, nullptr, nullptr);
143 m_pContext->IASetInputLayout(nullptr);
144 m_pContext->Draw(4, 0);
145 // unset shaders
146 m_pContext->PSSetShader(nullptr, nullptr, 0);
147 m_pContext->VSSetShader(nullptr, nullptr, 0);
148 // unbind our view
149 ID3D11ShaderResourceView* views[1] = {};
150 m_pContext->PSSetShaderResources(0, 1, views);
151 }
152
153private:
154 enum ShaderType
155 {
156 VERTEX_SHADER,
157 PIXEL_SHADER
158 };
159
160 bool createD3DResources()
161 {
162 HANDLE sharedHandle;
163 Microsoft::WRL::ComPtr<ID3D11Device> pDevice;
164 Microsoft::WRL::ComPtr<ID3D11RenderTargetView> pRTView;
165 Microsoft::WRL::ComPtr<ID3D11Resource> pRTResource;
166 Microsoft::WRL::ComPtr<ID3D11Texture2D> pRTTexture;
167 Microsoft::WRL::ComPtr<ID3D11Texture2D> pOffScreenTexture;
168 Microsoft::WRL::ComPtr<IDXGIResource> dxgiResource;
169
170 m_pContext->GetDevice(&pDevice);
171 m_pContext->OMGetRenderTargets(1, &pRTView, nullptr);
172 if (!pRTView)
173 return false;
174
175 pRTView->GetResource(&pRTResource);
176 if (FAILED(pRTResource.As(&pRTTexture)))
177 return false;
178
179 D3D11_TEXTURE2D_DESC texDesc;
180 pRTTexture->GetDesc(&texDesc);
181 texDesc.Format = DXGI_FORMAT_B8G8R8A8_UNORM;
182 texDesc.BindFlags = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET;
183 texDesc.MiscFlags = D3D11_RESOURCE_MISC_SHARED;
184 if (FAILED(pDevice->CreateTexture2D(&texDesc, nullptr, &pOffScreenTexture)))
185 {
186 Log(ADDON_LOG_ERROR, "GLonDX: unable to create intermediate texture");
187 return false;
188 }
189
190 CD3D11_SHADER_RESOURCE_VIEW_DESC srvDesc(pOffScreenTexture.Get(), D3D11_SRV_DIMENSION_TEXTURE2D);
191 if (FAILED(pDevice->CreateShaderResourceView(pOffScreenTexture.Get(), &srvDesc, &m_pSRView)))
192 {
193 Log(ADDON_LOG_ERROR, "GLonDX: unable to create shader view");
194 return false;
195 }
196
197 if (FAILED(pOffScreenTexture.As(&dxgiResource)) ||
198 FAILED(dxgiResource->GetSharedHandle(&sharedHandle)))
199 {
200 Log(ADDON_LOG_ERROR, "GLonDX: unable get shared handle for texture");
201 return false;
202 }
203
204 // initiate simple shaders
205 if (FAILED(d3dCreateShader(VERTEX_SHADER, vs_out_shader_text, &m_pVShader)))
206 {
207 Log(ADDON_LOG_ERROR, "GLonDX: unable to create vertex shader view");
208 return false;
209 }
210
211 if (FAILED(d3dCreateShader(PIXEL_SHADER, ps_out_shader_text, &m_pPShader)))
212 {
213 Log(ADDON_LOG_ERROR, "GLonDX: unable to create pixel shader view");
214 return false;
215 }
216
217 // create EGL buffer from D3D shared texture
218 EGLint egl_buffer_attrs[] =
219 {
220 EGL_WIDTH, static_cast<EGLint>(texDesc.Width),
221 EGL_HEIGHT, static_cast<EGLint>(texDesc.Height),
222 EGL_TEXTURE_TARGET, EGL_TEXTURE_2D,
223 EGL_TEXTURE_FORMAT, EGL_TEXTURE_RGBA,
224 EGL_NONE
225 };
226
227 m_eglBuffer = eglCreatePbufferFromClientBuffer(m_eglDisplay,
228 EGL_D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE,
229 sharedHandle, m_eglConfig, egl_buffer_attrs);
230
231 if (m_eglBuffer == EGL_NO_SURFACE)
232 {
233 Log(ADDON_LOG_ERROR, "GLonDX: unable to create EGL buffer (%s)", eglGetErrorString());
234 return false;
235 }
236 return true;
237 }
238
239 HRESULT d3dCreateShader(ShaderType shaderType, const std::string& source, IUnknown** ppShader) const
240 {
241 Microsoft::WRL::ComPtr<ID3DBlob> pBlob;
242 Microsoft::WRL::ComPtr<ID3DBlob> pErrors;
243
244 auto hr = D3DCompile(source.c_str(), source.length(), nullptr, nullptr, nullptr, "main",
245 shaderType == PIXEL_SHADER ? "ps_4_0" : "vs_4_0", 0, 0, &pBlob, &pErrors);
246
247 if (SUCCEEDED(hr))
248 {
249 Microsoft::WRL::ComPtr<ID3D11Device> pDevice;
250 m_pContext->GetDevice(&pDevice);
251
252 if (shaderType == PIXEL_SHADER)
253 {
254 hr = pDevice->CreatePixelShader(pBlob->GetBufferPointer(), pBlob->GetBufferSize(), nullptr,
255 reinterpret_cast<ID3D11PixelShader**>(ppShader));
256 }
257 else
258 {
259 hr = pDevice->CreateVertexShader(pBlob->GetBufferPointer(), pBlob->GetBufferSize(), nullptr,
260 reinterpret_cast<ID3D11VertexShader**>(ppShader));
261 }
262
263 if (FAILED(hr))
264 {
265 Log(ADDON_LOG_ERROR, "GLonDX: unable to create %s shader",
266 shaderType == PIXEL_SHADER ? "pixel" : "vertex");
267 }
268 }
269 else
270 {
271 Log(ADDON_LOG_ERROR, "GLonDX: unable to compile shader (%s)", pErrors->GetBufferPointer());
272 }
273 return hr;
274 }
275
276 static const char* eglGetErrorString()
277 {
278#define CASE_STR( value ) case value: return #value
279 switch (eglGetError())
280 {
281 CASE_STR(EGL_SUCCESS);
282 CASE_STR(EGL_NOT_INITIALIZED);
283 CASE_STR(EGL_BAD_ACCESS);
284 CASE_STR(EGL_BAD_ALLOC);
285 CASE_STR(EGL_BAD_ATTRIBUTE);
286 CASE_STR(EGL_BAD_CONTEXT);
287 CASE_STR(EGL_BAD_CONFIG);
288 CASE_STR(EGL_BAD_CURRENT_SURFACE);
289 CASE_STR(EGL_BAD_DISPLAY);
290 CASE_STR(EGL_BAD_SURFACE);
291 CASE_STR(EGL_BAD_MATCH);
292 CASE_STR(EGL_BAD_PARAMETER);
293 CASE_STR(EGL_BAD_NATIVE_PIXMAP);
294 CASE_STR(EGL_BAD_NATIVE_WINDOW);
295 CASE_STR(EGL_CONTEXT_LOST);
296 default:
297 return "Unknown";
298 }
299#undef CASE_STR
300 }
301
302 void destruct()
303 {
304 if (m_eglDisplay != EGL_NO_DISPLAY)
305 {
306 eglMakeCurrent(m_eglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
307
308 if (m_eglBuffer != EGL_NO_SURFACE)
309 {
310 eglDestroySurface(m_eglDisplay, m_eglBuffer);
311 m_eglBuffer = EGL_NO_SURFACE;
312 }
313
314 if (m_eglContext != EGL_NO_CONTEXT)
315 {
316 eglDestroyContext(m_eglDisplay, m_eglContext);
317 m_eglContext = EGL_NO_CONTEXT;
318 }
319
320 eglTerminate(m_eglDisplay);
321 m_eglDisplay = EGL_NO_DISPLAY;
322 }
323
324 m_pSRView = nullptr;
325 m_pVShader = nullptr;
326 m_pPShader = nullptr;
327 m_pContext = nullptr;
328 }
329
330 EGLConfig m_eglConfig = EGL_NO_CONFIG_KHR;
331 EGLDisplay m_eglDisplay = EGL_NO_DISPLAY;
332 EGLContext m_eglContext = EGL_NO_CONTEXT;
333 EGLSurface m_eglBuffer = EGL_NO_SURFACE;
334
335 ID3D11DeviceContext* m_pContext = nullptr; // don't hold context
336 Microsoft::WRL::ComPtr<ID3D11ShaderResourceView> m_pSRView = nullptr;
337 Microsoft::WRL::ComPtr<ID3D11VertexShader> m_pVShader = nullptr;
338 Microsoft::WRL::ComPtr<ID3D11PixelShader> m_pPShader = nullptr;
339
340#define TO_STRING(...) #__VA_ARGS__
341 std::string vs_out_shader_text = TO_STRING(
342 void main(uint id : SV_VertexId, out float2 tex : TEXCOORD0, out float4 pos : SV_POSITION)
343 {
344 tex = float2(id % 2, (id % 4) >> 1);
345 pos = float4((tex.x - 0.5f) * 2, -(tex.y - 0.5f) * 2, 0, 1);
346 });
347
348 std::string ps_out_shader_text = TO_STRING(
349 Texture2D texMain : register(t0);
350 SamplerState Sampler
351 {
352 Filter = MIN_MAG_MIP_LINEAR;
353 AddressU = CLAMP;
354 AddressV = CLAMP;
355 Comparison = NEVER;
356 };
357
358 float4 main(in float2 tex : TEXCOORD0) : SV_TARGET
359 {
360 return texMain.Sample(Sampler, tex);
361 });
362#undef TO_STRING
363}; /* class CGLonDX */
364
365} /* namespace gl */
366
367using CRenderHelper = gl::CGLonDX;
368} /* namespace gui */
369} /* namespace kodi */