diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-10 18:07:22 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-10 18:07:22 +0000 |
commit | c04dcc2e7d834218ef2d4194331e383402495ae1 (patch) | |
tree | 7333e38d10d75386e60f336b80c2443c1166031d /xbmc/guilib/GUITextureGL.cpp | |
parent | Initial commit. (diff) | |
download | kodi-c04dcc2e7d834218ef2d4194331e383402495ae1.tar.xz kodi-c04dcc2e7d834218ef2d4194331e383402495ae1.zip |
Adding upstream version 2:20.4+dfsg.upstream/2%20.4+dfsg
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to '')
-rw-r--r-- | xbmc/guilib/GUITextureGL.cpp | 361 |
1 files changed, 361 insertions, 0 deletions
diff --git a/xbmc/guilib/GUITextureGL.cpp b/xbmc/guilib/GUITextureGL.cpp new file mode 100644 index 0000000..6e46aa7 --- /dev/null +++ b/xbmc/guilib/GUITextureGL.cpp @@ -0,0 +1,361 @@ +/* + * Copyright (C) 2005-2018 Team Kodi + * This file is part of Kodi - https://kodi.tv + * + * SPDX-License-Identifier: GPL-2.0-or-later + * See LICENSES/README.md for more information. + */ + +#include "GUITextureGL.h" + +#include "ServiceBroker.h" +#include "Texture.h" +#include "rendering/gl/RenderSystemGL.h" +#include "utils/GLUtils.h" +#include "utils/Geometry.h" +#include "utils/log.h" +#include "windowing/WinSystem.h" + +#include <cstddef> + +#include "PlatformDefs.h" + +void CGUITextureGL::Register() +{ + CGUITexture::Register(CGUITextureGL::CreateTexture, CGUITextureGL::DrawQuad); +} + +CGUITexture* CGUITextureGL::CreateTexture( + float posX, float posY, float width, float height, const CTextureInfo& texture) +{ + return new CGUITextureGL(posX, posY, width, height, texture); +} + +CGUITextureGL::CGUITextureGL( + float posX, float posY, float width, float height, const CTextureInfo& texture) + : CGUITexture(posX, posY, width, height, texture) +{ + m_renderSystem = dynamic_cast<CRenderSystemGL*>(CServiceBroker::GetRenderSystem()); +} + +CGUITextureGL* CGUITextureGL::Clone() const +{ + return new CGUITextureGL(*this); +} + +void CGUITextureGL::Begin(UTILS::COLOR::Color color) +{ + CTexture* texture = m_texture.m_textures[m_currentFrame].get(); + texture->LoadToGPU(); + if (m_diffuse.size()) + m_diffuse.m_textures[0]->LoadToGPU(); + + texture->BindToUnit(0); + + // Setup Colors + m_col[0] = KODI::UTILS::GL::GetChannelFromARGB(KODI::UTILS::GL::ColorChannel::R, color); + m_col[1] = KODI::UTILS::GL::GetChannelFromARGB(KODI::UTILS::GL::ColorChannel::G, color); + m_col[2] = KODI::UTILS::GL::GetChannelFromARGB(KODI::UTILS::GL::ColorChannel::B, color); + m_col[3] = KODI::UTILS::GL::GetChannelFromARGB(KODI::UTILS::GL::ColorChannel::A, color); + + bool hasAlpha = m_texture.m_textures[m_currentFrame]->HasAlpha() || m_col[3] < 255; + + if (m_diffuse.size()) + { + if (m_col[0] == 255 && m_col[1] == 255 && m_col[2] == 255 && m_col[3] == 255 ) + { + m_renderSystem->EnableShader(ShaderMethodGL::SM_MULTI); + } + else + { + m_renderSystem->EnableShader(ShaderMethodGL::SM_MULTI_BLENDCOLOR); + } + + hasAlpha |= m_diffuse.m_textures[0]->HasAlpha(); + + m_diffuse.m_textures[0]->BindToUnit(1); + } + else + { + if (m_col[0] == 255 && m_col[1] == 255 && m_col[2] == 255 && m_col[3] == 255) + { + m_renderSystem->EnableShader(ShaderMethodGL::SM_TEXTURE_NOBLEND); + } + else + { + m_renderSystem->EnableShader(ShaderMethodGL::SM_TEXTURE); + } + } + + if (hasAlpha) + { + glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE_MINUS_DST_ALPHA, GL_ONE); + glEnable(GL_BLEND); + } + else + { + glDisable(GL_BLEND); + } + m_packedVertices.clear(); + m_idx.clear(); +} + +void CGUITextureGL::End() +{ + if (m_packedVertices.size()) + { + GLint posLoc = m_renderSystem->ShaderGetPos(); + GLint tex0Loc = m_renderSystem->ShaderGetCoord0(); + GLint tex1Loc = m_renderSystem->ShaderGetCoord1(); + GLint uniColLoc = m_renderSystem->ShaderGetUniCol(); + + GLuint VertexVBO; + GLuint IndexVBO; + + glGenBuffers(1, &VertexVBO); + glBindBuffer(GL_ARRAY_BUFFER, VertexVBO); + glBufferData(GL_ARRAY_BUFFER, sizeof(PackedVertex)*m_packedVertices.size(), &m_packedVertices[0], GL_STATIC_DRAW); + + if (uniColLoc >= 0) + { + glUniform4f(uniColLoc,(m_col[0] / 255.0f), (m_col[1] / 255.0f), (m_col[2] / 255.0f), (m_col[3] / 255.0f)); + } + + if (m_diffuse.size()) + { + glVertexAttribPointer(tex1Loc, 2, GL_FLOAT, 0, sizeof(PackedVertex), + reinterpret_cast<const GLvoid*>(offsetof(PackedVertex, u2))); + glEnableVertexAttribArray(tex1Loc); + } + + glVertexAttribPointer(posLoc, 3, GL_FLOAT, 0, sizeof(PackedVertex), + reinterpret_cast<const GLvoid*>(offsetof(PackedVertex, x))); + glEnableVertexAttribArray(posLoc); + glVertexAttribPointer(tex0Loc, 2, GL_FLOAT, 0, sizeof(PackedVertex), + reinterpret_cast<const GLvoid*>(offsetof(PackedVertex, u1))); + glEnableVertexAttribArray(tex0Loc); + + glGenBuffers(1, &IndexVBO); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, IndexVBO); + glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(ushort)*m_idx.size(), m_idx.data(), GL_STATIC_DRAW); + + glDrawElements(GL_TRIANGLES, m_packedVertices.size()*6 / 4, GL_UNSIGNED_SHORT, 0); + + if (m_diffuse.size()) + glDisableVertexAttribArray(tex1Loc); + + glDisableVertexAttribArray(posLoc); + glDisableVertexAttribArray(tex0Loc); + + glBindBuffer(GL_ARRAY_BUFFER, 0); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); + glDeleteBuffers(1, &VertexVBO); + glDeleteBuffers(1, &IndexVBO); + } + + if (m_diffuse.size()) + glActiveTexture(GL_TEXTURE0); + glEnable(GL_BLEND); + + m_renderSystem->DisableShader(); +} + +void CGUITextureGL::Draw(float *x, float *y, float *z, const CRect &texture, const CRect &diffuse, int orientation) +{ + PackedVertex vertices[4]; + + // Setup texture coordinates + // TopLeft + vertices[0].u1 = texture.x1; + vertices[0].v1 = texture.y1; + + // TopRight + if (orientation & 4) + { + vertices[1].u1 = texture.x1; + vertices[1].v1 = texture.y2; + } + else + { + vertices[1].u1 = texture.x2; + vertices[1].v1 = texture.y1; + } + + // BottomRight + vertices[2].u1 = texture.x2; + vertices[2].v1 = texture.y2; + + // BottomLeft + if (orientation & 4) + { + vertices[3].u1 = texture.x2; + vertices[3].v1 = texture.y1; + } + else + { + vertices[3].u1 = texture.x1; + vertices[3].v1 = texture.y2; + } + + if (m_diffuse.size()) + { + // TopLeft + vertices[0].u2 = diffuse.x1; + vertices[0].v2 = diffuse.y1; + + // TopRight + if (m_info.orientation & 4) + { + vertices[1].u2 = diffuse.x1; + vertices[1].v2 = diffuse.y2; + } + else + { + vertices[1].u2 = diffuse.x2; + vertices[1].v2 = diffuse.y1; + } + + // BottomRight + vertices[2].u2 = diffuse.x2; + vertices[2].v2 = diffuse.y2; + + // BottomLeft + if (m_info.orientation & 4) + { + vertices[3].u2 = diffuse.x2; + vertices[3].v2 = diffuse.y1; + } + else + { + vertices[3].u2 = diffuse.x1; + vertices[3].v2 = diffuse.y2; + } + } + + for (int i=0; i<4; i++) + { + vertices[i].x = x[i]; + vertices[i].y = y[i]; + vertices[i].z = z[i]; + m_packedVertices.push_back(vertices[i]); + } + + if ((m_packedVertices.size() / 4) > (m_idx.size() / 6)) + { + size_t i = m_packedVertices.size() - 4; + m_idx.push_back(i+0); + m_idx.push_back(i+1); + m_idx.push_back(i+2); + m_idx.push_back(i+2); + m_idx.push_back(i+3); + m_idx.push_back(i+0); + } +} + +void CGUITextureGL::DrawQuad(const CRect& rect, + UTILS::COLOR::Color color, + CTexture* texture, + const CRect* texCoords) +{ + CRenderSystemGL *renderSystem = dynamic_cast<CRenderSystemGL*>(CServiceBroker::GetRenderSystem()); + if (texture) + { + texture->LoadToGPU(); + texture->BindToUnit(0); + } + + glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA); + glEnable(GL_BLEND); // Turn Blending On + + VerifyGLState(); + + GLubyte col[4]; + GLubyte idx[4] = {0, 1, 3, 2}; //determines order of the vertices + GLuint vertexVBO; + GLuint indexVBO; + + struct PackedVertex + { + float x, y, z; + float u1, v1; + }vertex[4]; + + if (texture) + renderSystem->EnableShader(ShaderMethodGL::SM_TEXTURE); + else + renderSystem->EnableShader(ShaderMethodGL::SM_DEFAULT); + + GLint posLoc = renderSystem->ShaderGetPos(); + GLint tex0Loc = renderSystem->ShaderGetCoord0(); + GLint uniColLoc = renderSystem->ShaderGetUniCol(); + + // Setup Colors + col[0] = KODI::UTILS::GL::GetChannelFromARGB(KODI::UTILS::GL::ColorChannel::R, color); + col[1] = KODI::UTILS::GL::GetChannelFromARGB(KODI::UTILS::GL::ColorChannel::G, color); + col[2] = KODI::UTILS::GL::GetChannelFromARGB(KODI::UTILS::GL::ColorChannel::B, color); + col[3] = KODI::UTILS::GL::GetChannelFromARGB(KODI::UTILS::GL::ColorChannel::A, color); + + glUniform4f(uniColLoc, col[0] / 255.0f, col[1] / 255.0f, col[2] / 255.0f, col[3] / 255.0f); + + // bottom left + vertex[0].x = rect.x1; + vertex[0].y = rect.y1; + vertex[0].z = 0; + + // bottom right + vertex[1].x = rect.x2; + vertex[1].y = rect.y1; + vertex[1].z = 0; + + // top right + vertex[2].x = rect.x2; + vertex[2].y = rect.y2; + vertex[2].z = 0; + + // top left + vertex[3].x = rect.x1; + vertex[3].y = rect.y2; + vertex[3].z = 0; + + if (texture) + { + CRect coords = texCoords ? *texCoords : CRect(0.0f, 0.0f, 1.0f, 1.0f); + vertex[0].u1 = vertex[3].u1 = coords.x1; + vertex[0].v1 = vertex[1].v1 = coords.y1; + vertex[1].u1 = vertex[2].u1 = coords.x2; + vertex[2].v1 = vertex[3].v1 = coords.y2; + } + + glGenBuffers(1, &vertexVBO); + glBindBuffer(GL_ARRAY_BUFFER, vertexVBO); + glBufferData(GL_ARRAY_BUFFER, sizeof(PackedVertex)*4, &vertex[0], GL_STATIC_DRAW); + + glVertexAttribPointer(posLoc, 3, GL_FLOAT, 0, sizeof(PackedVertex), + reinterpret_cast<const GLvoid*>(offsetof(PackedVertex, x))); + glEnableVertexAttribArray(posLoc); + + if (texture) + { + glVertexAttribPointer(tex0Loc, 2, GL_FLOAT, 0, sizeof(PackedVertex), + reinterpret_cast<const GLvoid*>(offsetof(PackedVertex, u1))); + glEnableVertexAttribArray(tex0Loc); + } + + glGenBuffers(1, &indexVBO); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexVBO); + glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(GLubyte)*4, idx, GL_STATIC_DRAW); + + glDrawElements(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_BYTE, 0); + + glDisableVertexAttribArray(posLoc); + if (texture) + glDisableVertexAttribArray(tex0Loc); + + glBindBuffer(GL_ARRAY_BUFFER, 0); + glDeleteBuffers(1, &vertexVBO); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); + glDeleteBuffers(1, &indexVBO); + + renderSystem->DisableShader(); +} + |