1 /*
2  *  Copyright (C) 2005-2018 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 #include "FrameBufferObject.h"
10 
11 #include "ServiceBroker.h"
12 #include "rendering/RenderSystem.h"
13 #include "utils/GLUtils.h"
14 #include "utils/log.h"
15 
16 //////////////////////////////////////////////////////////////////////
17 // CFrameBufferObject
18 //////////////////////////////////////////////////////////////////////
19 
CFrameBufferObject()20 CFrameBufferObject::CFrameBufferObject()
21 {
22   m_fbo = 0;
23   m_valid = false;
24   m_supported = false;
25   m_bound = false;
26   m_texid = 0;
27 }
28 
IsSupported()29 bool CFrameBufferObject::IsSupported()
30 {
31   if(CServiceBroker::GetRenderSystem()->IsExtSupported("GL_EXT_framebuffer_object"))
32     m_supported = true;
33   else
34     m_supported = false;
35   return m_supported;
36 }
37 
Initialize()38 bool CFrameBufferObject::Initialize()
39 {
40   if (!IsSupported())
41     return false;
42 
43   Cleanup();
44 
45   glGenFramebuffers(1, &m_fbo);
46   VerifyGLState();
47 
48   if (!m_fbo)
49     return false;
50 
51   m_valid = true;
52   return true;
53 }
54 
Cleanup()55 void CFrameBufferObject::Cleanup()
56 {
57   if (!IsValid())
58     return;
59 
60   if (m_fbo)
61     glDeleteFramebuffers(1, &m_fbo);
62 
63   if (m_texid)
64     glDeleteTextures(1, &m_texid);
65 
66   m_texid = 0;
67   m_fbo = 0;
68   m_valid = false;
69   m_bound = false;
70 }
71 
CreateAndBindToTexture(GLenum target,int width,int height,GLenum format,GLenum type,GLenum filter,GLenum clampmode)72 bool CFrameBufferObject::CreateAndBindToTexture(GLenum target, int width, int height, GLenum format, GLenum type,
73                                                 GLenum filter, GLenum clampmode)
74 {
75   if (!IsValid())
76     return false;
77 
78   if (m_texid)
79     glDeleteTextures(1, &m_texid);
80 
81   glGenTextures(1, &m_texid);
82   glBindTexture(target, m_texid);
83   glTexImage2D(target, 0, format,  width, height, 0, GL_RGBA, type, NULL);
84   glTexParameteri(target, GL_TEXTURE_WRAP_S, clampmode);
85   glTexParameteri(target, GL_TEXTURE_WRAP_T, clampmode);
86   glTexParameteri(target, GL_TEXTURE_MAG_FILTER, filter);
87   glTexParameteri(target, GL_TEXTURE_MIN_FILTER, filter);
88   VerifyGLState();
89 
90   m_bound = false;
91   glBindFramebuffer(GL_FRAMEBUFFER, m_fbo);
92   glBindTexture(target, m_texid);
93   glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, target, m_texid, 0);
94   VerifyGLState();
95   GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
96   glBindFramebuffer(GL_FRAMEBUFFER, 0);
97   if (status != GL_FRAMEBUFFER_COMPLETE)
98   {
99     VerifyGLState();
100     return false;
101   }
102   m_bound = true;
103   return true;
104 }
105 
SetFiltering(GLenum target,GLenum mode)106 void CFrameBufferObject::SetFiltering(GLenum target, GLenum mode)
107 {
108   glBindTexture(target, m_texid);
109   glTexParameteri(target, GL_TEXTURE_MAG_FILTER, mode);
110   glTexParameteri(target, GL_TEXTURE_MIN_FILTER, mode);
111 }
112 
113 // Begin rendering to FBO
BeginRender()114 bool CFrameBufferObject::BeginRender()
115 {
116   if (IsValid() && IsBound())
117   {
118     glBindFramebuffer(GL_FRAMEBUFFER, m_fbo);
119     return true;
120   }
121   return false;
122 }
123 
124 // Finish rendering to FBO
EndRender() const125 void CFrameBufferObject::EndRender() const
126 {
127   if (IsValid())
128     glBindFramebuffer(GL_FRAMEBUFFER, 0);
129 }
130