[Windows] Fix driver version detection of AMD RDNA+ GPU on Windows 10
[xbmc.git] / xbmc / guilib / GUITextureGL.cpp
blobc2f23ccdfb5942ad0dd3d38deb73905897b7a0c2
1 /*
2 * Copyright (C) 2005-2018 Team Kodi
3 * This file is part of Kodi - https://kodi.tv
5 * SPDX-License-Identifier: GPL-2.0-or-later
6 * See LICENSES/README.md for more information.
7 */
9 #include "GUITextureGL.h"
11 #include "ServiceBroker.h"
12 #include "Texture.h"
13 #include "rendering/gl/RenderSystemGL.h"
14 #include "utils/GLUtils.h"
15 #include "utils/Geometry.h"
16 #include "utils/log.h"
17 #include "windowing/WinSystem.h"
19 #include <cstddef>
21 #include "PlatformDefs.h"
23 void CGUITextureGL::Register()
25 CGUITexture::Register(CGUITextureGL::CreateTexture, CGUITextureGL::DrawQuad);
28 CGUITexture* CGUITextureGL::CreateTexture(
29 float posX, float posY, float width, float height, const CTextureInfo& texture)
31 return new CGUITextureGL(posX, posY, width, height, texture);
34 CGUITextureGL::CGUITextureGL(
35 float posX, float posY, float width, float height, const CTextureInfo& texture)
36 : CGUITexture(posX, posY, width, height, texture)
38 m_renderSystem = dynamic_cast<CRenderSystemGL*>(CServiceBroker::GetRenderSystem());
41 CGUITextureGL* CGUITextureGL::Clone() const
43 return new CGUITextureGL(*this);
46 void CGUITextureGL::Begin(UTILS::COLOR::Color color)
48 CTexture* texture = m_texture.m_textures[m_currentFrame].get();
49 texture->LoadToGPU();
50 if (m_diffuse.size())
51 m_diffuse.m_textures[0]->LoadToGPU();
53 texture->BindToUnit(0);
55 // Setup Colors
56 m_col[0] = KODI::UTILS::GL::GetChannelFromARGB(KODI::UTILS::GL::ColorChannel::R, color);
57 m_col[1] = KODI::UTILS::GL::GetChannelFromARGB(KODI::UTILS::GL::ColorChannel::G, color);
58 m_col[2] = KODI::UTILS::GL::GetChannelFromARGB(KODI::UTILS::GL::ColorChannel::B, color);
59 m_col[3] = KODI::UTILS::GL::GetChannelFromARGB(KODI::UTILS::GL::ColorChannel::A, color);
61 bool hasAlpha = m_texture.m_textures[m_currentFrame]->HasAlpha() || m_col[3] < 255;
63 if (m_diffuse.size())
65 if (m_col[0] == 255 && m_col[1] == 255 && m_col[2] == 255 && m_col[3] == 255 )
67 m_renderSystem->EnableShader(ShaderMethodGL::SM_MULTI);
69 else
71 m_renderSystem->EnableShader(ShaderMethodGL::SM_MULTI_BLENDCOLOR);
74 hasAlpha |= m_diffuse.m_textures[0]->HasAlpha();
76 m_diffuse.m_textures[0]->BindToUnit(1);
78 else
80 if (m_col[0] == 255 && m_col[1] == 255 && m_col[2] == 255 && m_col[3] == 255)
82 m_renderSystem->EnableShader(ShaderMethodGL::SM_TEXTURE_NOBLEND);
84 else
86 m_renderSystem->EnableShader(ShaderMethodGL::SM_TEXTURE);
90 if (hasAlpha)
92 glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE_MINUS_DST_ALPHA, GL_ONE);
93 glEnable(GL_BLEND);
95 else
97 glDisable(GL_BLEND);
99 m_packedVertices.clear();
100 m_idx.clear();
103 void CGUITextureGL::End()
105 if (m_packedVertices.size())
107 GLint posLoc = m_renderSystem->ShaderGetPos();
108 GLint tex0Loc = m_renderSystem->ShaderGetCoord0();
109 GLint tex1Loc = m_renderSystem->ShaderGetCoord1();
110 GLint uniColLoc = m_renderSystem->ShaderGetUniCol();
111 GLint depthLoc = m_renderSystem->ShaderGetDepth();
113 GLuint VertexVBO;
114 GLuint IndexVBO;
116 glGenBuffers(1, &VertexVBO);
117 glBindBuffer(GL_ARRAY_BUFFER, VertexVBO);
118 glBufferData(GL_ARRAY_BUFFER, sizeof(PackedVertex)*m_packedVertices.size(), &m_packedVertices[0], GL_STATIC_DRAW);
120 glUniform1f(depthLoc, m_depth);
122 if (uniColLoc >= 0)
124 glUniform4f(uniColLoc,(m_col[0] / 255.0f), (m_col[1] / 255.0f), (m_col[2] / 255.0f), (m_col[3] / 255.0f));
127 if (m_diffuse.size())
129 glVertexAttribPointer(tex1Loc, 2, GL_FLOAT, 0, sizeof(PackedVertex),
130 reinterpret_cast<const GLvoid*>(offsetof(PackedVertex, u2)));
131 glEnableVertexAttribArray(tex1Loc);
134 glVertexAttribPointer(posLoc, 3, GL_FLOAT, 0, sizeof(PackedVertex),
135 reinterpret_cast<const GLvoid*>(offsetof(PackedVertex, x)));
136 glEnableVertexAttribArray(posLoc);
137 glVertexAttribPointer(tex0Loc, 2, GL_FLOAT, 0, sizeof(PackedVertex),
138 reinterpret_cast<const GLvoid*>(offsetof(PackedVertex, u1)));
139 glEnableVertexAttribArray(tex0Loc);
141 glGenBuffers(1, &IndexVBO);
142 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, IndexVBO);
143 glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(ushort)*m_idx.size(), m_idx.data(), GL_STATIC_DRAW);
145 glDrawElements(GL_TRIANGLES, m_packedVertices.size()*6 / 4, GL_UNSIGNED_SHORT, 0);
147 if (m_diffuse.size())
148 glDisableVertexAttribArray(tex1Loc);
150 glDisableVertexAttribArray(posLoc);
151 glDisableVertexAttribArray(tex0Loc);
153 glBindBuffer(GL_ARRAY_BUFFER, 0);
154 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
155 glDeleteBuffers(1, &VertexVBO);
156 glDeleteBuffers(1, &IndexVBO);
159 if (m_diffuse.size())
160 glActiveTexture(GL_TEXTURE0);
161 glEnable(GL_BLEND);
163 m_renderSystem->DisableShader();
166 void CGUITextureGL::Draw(float *x, float *y, float *z, const CRect &texture, const CRect &diffuse, int orientation)
168 PackedVertex vertices[4];
170 // Setup texture coordinates
171 // TopLeft
172 vertices[0].u1 = texture.x1;
173 vertices[0].v1 = texture.y1;
175 // TopRight
176 if (orientation & 4)
178 vertices[1].u1 = texture.x1;
179 vertices[1].v1 = texture.y2;
181 else
183 vertices[1].u1 = texture.x2;
184 vertices[1].v1 = texture.y1;
187 // BottomRight
188 vertices[2].u1 = texture.x2;
189 vertices[2].v1 = texture.y2;
191 // BottomLeft
192 if (orientation & 4)
194 vertices[3].u1 = texture.x2;
195 vertices[3].v1 = texture.y1;
197 else
199 vertices[3].u1 = texture.x1;
200 vertices[3].v1 = texture.y2;
203 if (m_diffuse.size())
205 // TopLeft
206 vertices[0].u2 = diffuse.x1;
207 vertices[0].v2 = diffuse.y1;
209 // TopRight
210 if (m_info.orientation & 4)
212 vertices[1].u2 = diffuse.x1;
213 vertices[1].v2 = diffuse.y2;
215 else
217 vertices[1].u2 = diffuse.x2;
218 vertices[1].v2 = diffuse.y1;
221 // BottomRight
222 vertices[2].u2 = diffuse.x2;
223 vertices[2].v2 = diffuse.y2;
225 // BottomLeft
226 if (m_info.orientation & 4)
228 vertices[3].u2 = diffuse.x2;
229 vertices[3].v2 = diffuse.y1;
231 else
233 vertices[3].u2 = diffuse.x1;
234 vertices[3].v2 = diffuse.y2;
238 for (int i=0; i<4; i++)
240 vertices[i].x = x[i];
241 vertices[i].y = y[i];
242 vertices[i].z = z[i];
243 m_packedVertices.push_back(vertices[i]);
246 if ((m_packedVertices.size() / 4) > (m_idx.size() / 6))
248 size_t i = m_packedVertices.size() - 4;
249 m_idx.push_back(i+0);
250 m_idx.push_back(i+1);
251 m_idx.push_back(i+2);
252 m_idx.push_back(i+2);
253 m_idx.push_back(i+3);
254 m_idx.push_back(i+0);
258 void CGUITextureGL::DrawQuad(const CRect& rect,
259 UTILS::COLOR::Color color,
260 CTexture* texture,
261 const CRect* texCoords,
262 const float depth,
263 const bool blending)
265 CRenderSystemGL *renderSystem = dynamic_cast<CRenderSystemGL*>(CServiceBroker::GetRenderSystem());
266 if (texture)
268 texture->LoadToGPU();
269 texture->BindToUnit(0);
272 if (blending)
274 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
275 glEnable(GL_BLEND);
277 else
279 glDisable(GL_BLEND);
282 VerifyGLState();
284 GLubyte col[4];
285 GLubyte idx[4] = {0, 1, 3, 2}; //determines order of the vertices
286 GLuint vertexVBO;
287 GLuint indexVBO;
289 struct PackedVertex
291 float x, y, z;
292 float u1, v1;
293 }vertex[4];
295 if (texture)
296 renderSystem->EnableShader(ShaderMethodGL::SM_TEXTURE);
297 else
298 renderSystem->EnableShader(ShaderMethodGL::SM_DEFAULT);
300 GLint posLoc = renderSystem->ShaderGetPos();
301 GLint tex0Loc = renderSystem->ShaderGetCoord0();
302 GLint uniColLoc = renderSystem->ShaderGetUniCol();
303 GLint depthLoc = renderSystem->ShaderGetDepth();
305 // Setup Colors
306 col[0] = KODI::UTILS::GL::GetChannelFromARGB(KODI::UTILS::GL::ColorChannel::R, color);
307 col[1] = KODI::UTILS::GL::GetChannelFromARGB(KODI::UTILS::GL::ColorChannel::G, color);
308 col[2] = KODI::UTILS::GL::GetChannelFromARGB(KODI::UTILS::GL::ColorChannel::B, color);
309 col[3] = KODI::UTILS::GL::GetChannelFromARGB(KODI::UTILS::GL::ColorChannel::A, color);
311 glUniform4f(uniColLoc, col[0] / 255.0f, col[1] / 255.0f, col[2] / 255.0f, col[3] / 255.0f);
312 glUniform1f(depthLoc, depth);
314 // bottom left
315 vertex[0].x = rect.x1;
316 vertex[0].y = rect.y1;
317 vertex[0].z = 0;
319 // bottom right
320 vertex[1].x = rect.x2;
321 vertex[1].y = rect.y1;
322 vertex[1].z = 0;
324 // top right
325 vertex[2].x = rect.x2;
326 vertex[2].y = rect.y2;
327 vertex[2].z = 0;
329 // top left
330 vertex[3].x = rect.x1;
331 vertex[3].y = rect.y2;
332 vertex[3].z = 0;
334 if (texture)
336 CRect coords = texCoords ? *texCoords : CRect(0.0f, 0.0f, 1.0f, 1.0f);
337 vertex[0].u1 = vertex[3].u1 = coords.x1;
338 vertex[0].v1 = vertex[1].v1 = coords.y1;
339 vertex[1].u1 = vertex[2].u1 = coords.x2;
340 vertex[2].v1 = vertex[3].v1 = coords.y2;
343 glGenBuffers(1, &vertexVBO);
344 glBindBuffer(GL_ARRAY_BUFFER, vertexVBO);
345 glBufferData(GL_ARRAY_BUFFER, sizeof(PackedVertex)*4, &vertex[0], GL_STATIC_DRAW);
347 glVertexAttribPointer(posLoc, 3, GL_FLOAT, 0, sizeof(PackedVertex),
348 reinterpret_cast<const GLvoid*>(offsetof(PackedVertex, x)));
349 glEnableVertexAttribArray(posLoc);
351 if (texture)
353 glVertexAttribPointer(tex0Loc, 2, GL_FLOAT, 0, sizeof(PackedVertex),
354 reinterpret_cast<const GLvoid*>(offsetof(PackedVertex, u1)));
355 glEnableVertexAttribArray(tex0Loc);
358 glGenBuffers(1, &indexVBO);
359 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexVBO);
360 glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(GLubyte)*4, idx, GL_STATIC_DRAW);
362 glDrawElements(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_BYTE, 0);
364 glDisableVertexAttribArray(posLoc);
365 if (texture)
366 glDisableVertexAttribArray(tex0Loc);
368 glBindBuffer(GL_ARRAY_BUFFER, 0);
369 glDeleteBuffers(1, &vertexVBO);
370 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
371 glDeleteBuffers(1, &indexVBO);
373 renderSystem->DisableShader();