13#if defined(WIN32) && defined(HAS_ANGLE)
17#include <d3dcompiler.h>
18#include <kodi/AddonBase.h>
19#include <kodi/gui/General.h>
20#include <wrl/client.h>
23#include <EGL/eglext.h>
25#pragma comment(lib, "d3dcompiler.lib")
26#ifndef GL_CLIENT_VERSION
27#define GL_CLIENT_VERSION 3
40 explicit CGLonDX() : m_pContext(reinterpret_cast<ID3D11DeviceContext*>(kodi::gui::
GetHWContext()))
43 ~CGLonDX()
override { destruct(); }
47 EGLint egl_display_attrs[] = {EGL_PLATFORM_ANGLE_TYPE_ANGLE,
48 EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE,
49 EGL_PLATFORM_ANGLE_MAX_VERSION_MAJOR_ANGLE,
51 EGL_PLATFORM_ANGLE_MAX_VERSION_MAJOR_ANGLE,
53 EGL_EXPERIMENTAL_PRESENT_PATH_ANGLE,
54 EGL_EXPERIMENTAL_PRESENT_PATH_FAST_ANGLE,
56 EGLint egl_config_attrs[] = {EGL_RED_SIZE,
64 EGL_BIND_TO_TEXTURE_RGBA,
67 GL_CLIENT_VERSION == 3 ? EGL_OPENGL_ES3_BIT : EGL_OPENGL_ES2_BIT,
71 EGLint egl_context_attrs[] = {EGL_CONTEXT_CLIENT_VERSION, GL_CLIENT_VERSION, EGL_NONE};
74 eglGetPlatformDisplayEXT(EGL_PLATFORM_ANGLE_ANGLE, EGL_DEFAULT_DISPLAY, egl_display_attrs);
75 if (m_eglDisplay == EGL_NO_DISPLAY)
81 if (eglInitialize(m_eglDisplay,
nullptr,
nullptr) != EGL_TRUE)
87 EGLint numConfigs = 0;
88 if (eglChooseConfig(m_eglDisplay, egl_config_attrs, &m_eglConfig, 1, &numConfigs) != EGL_TRUE ||
95 m_eglContext = eglCreateContext(m_eglDisplay, m_eglConfig,
nullptr, egl_context_attrs);
96 if (m_eglContext == EGL_NO_CONTEXT)
98 Log(
ADDON_LOG_ERROR,
"GLonDX: unable to create EGL context (%s)", eglGetErrorString());
102 if (!createD3DResources())
105 if (eglMakeCurrent(m_eglDisplay, m_eglBuffer, m_eglBuffer, m_eglContext) != EGL_TRUE)
113 void CheckGL(ID3D11DeviceContext* device)
115 if (m_pContext != device)
118 m_pVShader =
nullptr;
119 m_pPShader =
nullptr;
122 if (m_eglBuffer != EGL_NO_SURFACE)
124 eglMakeCurrent(m_eglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
125 eglDestroySurface(m_eglDisplay, m_eglBuffer);
126 m_eglBuffer = EGL_NO_SURFACE;
130 if (!createD3DResources())
133 eglMakeCurrent(m_eglDisplay, m_eglBuffer, m_eglBuffer, m_eglContext);
137 void Begin()
override
142 glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
143 glClear(GL_COLOR_BUFFER_BIT);
151 m_pContext->VSSetShader(m_pVShader.Get(),
nullptr, 0);
152 m_pContext->PSSetShader(m_pPShader.Get(),
nullptr, 0);
153 m_pContext->PSSetShaderResources(0, 1, m_pSRView.GetAddressOf());
155 m_pContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP);
156 m_pContext->IASetVertexBuffers(0, 0,
nullptr,
nullptr,
nullptr);
157 m_pContext->IASetInputLayout(
nullptr);
158 m_pContext->Draw(4, 0);
160 m_pContext->PSSetShader(
nullptr,
nullptr, 0);
161 m_pContext->VSSetShader(
nullptr,
nullptr, 0);
163 ID3D11ShaderResourceView* views[1] = {};
164 m_pContext->PSSetShaderResources(0, 1, views);
174 bool createD3DResources()
177 Microsoft::WRL::ComPtr<ID3D11Device> pDevice;
178 Microsoft::WRL::ComPtr<ID3D11RenderTargetView> pRTView;
179 Microsoft::WRL::ComPtr<ID3D11Resource> pRTResource;
180 Microsoft::WRL::ComPtr<ID3D11Texture2D> pRTTexture;
181 Microsoft::WRL::ComPtr<ID3D11Texture2D> pOffScreenTexture;
182 Microsoft::WRL::ComPtr<IDXGIResource> dxgiResource;
184 m_pContext->GetDevice(&pDevice);
185 m_pContext->OMGetRenderTargets(1, &pRTView,
nullptr);
189 pRTView->GetResource(&pRTResource);
190 if (FAILED(pRTResource.As(&pRTTexture)))
193 D3D11_TEXTURE2D_DESC texDesc;
194 pRTTexture->GetDesc(&texDesc);
195 texDesc.Format = DXGI_FORMAT_B8G8R8A8_UNORM;
196 texDesc.BindFlags = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET;
197 texDesc.MiscFlags = D3D11_RESOURCE_MISC_SHARED;
198 if (FAILED(pDevice->CreateTexture2D(&texDesc,
nullptr, &pOffScreenTexture)))
204 CD3D11_SHADER_RESOURCE_VIEW_DESC srvDesc(pOffScreenTexture.Get(),
205 D3D11_SRV_DIMENSION_TEXTURE2D);
206 if (FAILED(pDevice->CreateShaderResourceView(pOffScreenTexture.Get(), &srvDesc, &m_pSRView)))
212 if (FAILED(pOffScreenTexture.As(&dxgiResource)) ||
213 FAILED(dxgiResource->GetSharedHandle(&sharedHandle)))
220 if (FAILED(d3dCreateShader(VERTEX_SHADER, vs_out_shader_text, &m_pVShader)))
226 if (FAILED(d3dCreateShader(PIXEL_SHADER, ps_out_shader_text, &m_pPShader)))
233 EGLint egl_buffer_attrs[] = {EGL_WIDTH,
234 static_cast<EGLint
>(texDesc.Width),
236 static_cast<EGLint
>(texDesc.Height),
244 eglCreatePbufferFromClientBuffer(m_eglDisplay, EGL_D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE,
245 sharedHandle, m_eglConfig, egl_buffer_attrs);
247 if (m_eglBuffer == EGL_NO_SURFACE)
249 Log(
ADDON_LOG_ERROR,
"GLonDX: unable to create EGL buffer (%s)", eglGetErrorString());
255 HRESULT d3dCreateShader(ShaderType shaderType,
256 const std::string& source,
257 IUnknown** ppShader)
const
259 Microsoft::WRL::ComPtr<ID3DBlob> pBlob;
260 Microsoft::WRL::ComPtr<ID3DBlob> pErrors;
262 auto hr = D3DCompile(source.c_str(), source.length(),
nullptr,
nullptr,
nullptr,
"main",
263 shaderType == PIXEL_SHADER ?
"ps_4_0" :
"vs_4_0", 0, 0, &pBlob, &pErrors);
267 Microsoft::WRL::ComPtr<ID3D11Device> pDevice;
268 m_pContext->GetDevice(&pDevice);
270 if (shaderType == PIXEL_SHADER)
272 hr = pDevice->CreatePixelShader(pBlob->GetBufferPointer(), pBlob->GetBufferSize(),
nullptr,
273 reinterpret_cast<ID3D11PixelShader**
>(ppShader));
277 hr = pDevice->CreateVertexShader(pBlob->GetBufferPointer(), pBlob->GetBufferSize(),
nullptr,
278 reinterpret_cast<ID3D11VertexShader**
>(ppShader));
284 shaderType == PIXEL_SHADER ?
"pixel" :
"vertex");
289 Log(
ADDON_LOG_ERROR,
"GLonDX: unable to compile shader (%s)", pErrors->GetBufferPointer());
294 static const char* eglGetErrorString()
296#define CASE_STR(value) \
299 switch (eglGetError())
301 CASE_STR(EGL_SUCCESS);
302 CASE_STR(EGL_NOT_INITIALIZED);
303 CASE_STR(EGL_BAD_ACCESS);
304 CASE_STR(EGL_BAD_ALLOC);
305 CASE_STR(EGL_BAD_ATTRIBUTE);
306 CASE_STR(EGL_BAD_CONTEXT);
307 CASE_STR(EGL_BAD_CONFIG);
308 CASE_STR(EGL_BAD_CURRENT_SURFACE);
309 CASE_STR(EGL_BAD_DISPLAY);
310 CASE_STR(EGL_BAD_SURFACE);
311 CASE_STR(EGL_BAD_MATCH);
312 CASE_STR(EGL_BAD_PARAMETER);
313 CASE_STR(EGL_BAD_NATIVE_PIXMAP);
314 CASE_STR(EGL_BAD_NATIVE_WINDOW);
315 CASE_STR(EGL_CONTEXT_LOST);
324 if (m_eglDisplay != EGL_NO_DISPLAY)
326 eglMakeCurrent(m_eglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
328 if (m_eglBuffer != EGL_NO_SURFACE)
330 eglDestroySurface(m_eglDisplay, m_eglBuffer);
331 m_eglBuffer = EGL_NO_SURFACE;
334 if (m_eglContext != EGL_NO_CONTEXT)
336 eglDestroyContext(m_eglDisplay, m_eglContext);
337 m_eglContext = EGL_NO_CONTEXT;
340 eglTerminate(m_eglDisplay);
341 m_eglDisplay = EGL_NO_DISPLAY;
345 m_pVShader =
nullptr;
346 m_pPShader =
nullptr;
347 m_pContext =
nullptr;
350 EGLConfig m_eglConfig = EGL_NO_CONFIG_KHR;
351 EGLDisplay m_eglDisplay = EGL_NO_DISPLAY;
352 EGLContext m_eglContext = EGL_NO_CONTEXT;
353 EGLSurface m_eglBuffer = EGL_NO_SURFACE;
355 ID3D11DeviceContext* m_pContext =
nullptr;
356 Microsoft::WRL::ComPtr<ID3D11ShaderResourceView> m_pSRView =
nullptr;
357 Microsoft::WRL::ComPtr<ID3D11VertexShader> m_pVShader =
nullptr;
358 Microsoft::WRL::ComPtr<ID3D11PixelShader> m_pPShader =
nullptr;
360#define TO_STRING(...) #__VA_ARGS__
361 std::string vs_out_shader_text = TO_STRING(
void main(uint
id
362 : SV_VertexId, out float2 tex
363 : TEXCOORD0, out float4 pos
365 tex = float2(
id % 2, (
id % 4) >> 1);
366 pos = float4((tex.x - 0.5f) * 2, -(tex.y - 0.5f) * 2, 0, 1);
369 std::string ps_out_shader_text = TO_STRING(
370 Texture2D texMain :
register(t0);
373 Filter = MIN_MAG_MIP_LINEAR;
379 float4 main(in float2 tex : TEXCOORD0) : SV_TARGET
381 return texMain.Sample(Sampler, tex);
388using CRenderHelper = gl::CGLonDX;
393#pragma message("WARNING: GLonDX.h only be available on Windows by use of Angle as depend!")
@ ADDON_LOG_ERROR
3 : To report error messages in the log file.
Definition addon_base.h:193
kodi::HardwareContext GetHWContext()
To get hardware specific device context interface.
Definition General.h:165
void ATTR_DLL_LOCAL Log(const ADDON_LOG loglevel, const char *format,...)
Add a message to Kodi's log.
Definition AddonBase.h:1938
Definition renderHelper.h:20