[cosmetics] update date in GPL header
[vuplus_xbmc] / xbmc / guilib / TextureGL.cpp
1 /*
2 *      Copyright (C) 2005-2013 Team XBMC
3 *      http://www.xbmc.org
4 *
5 *  This Program is free software; you can redistribute it and/or modify
6 *  it under the terms of the GNU General Public License as published by
7 *  the Free Software Foundation; either version 2, or (at your option)
8 *  any later version.
9 *
10 *  This Program is distributed in the hope that it will be useful,
11 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 *  GNU General Public License for more details.
14 *
15 *  You should have received a copy of the GNU General Public License
16 *  along with XBMC; see the file COPYING.  If not, see
17 *  <http://www.gnu.org/licenses/>.
18 *
19 */
20
21 #include "system.h"
22 #include "TextureGL.h"
23 #include "windowing/WindowingFactory.h"
24 #include "utils/log.h"
25 #include "utils/GLUtils.h"
26
27 #if defined(HAS_GL) || defined(HAS_GLES)
28
29 using namespace std;
30
31 /************************************************************************/
32 /*    CGLTexture                                                       */
33 /************************************************************************/
34 CGLTexture::CGLTexture(unsigned int width, unsigned int height, unsigned int format)
35 : CBaseTexture(width, height, format)
36 {
37   m_texture = 0;
38 }
39
40 CGLTexture::~CGLTexture()
41 {
42   DestroyTextureObject();
43 }
44
45 void CGLTexture::CreateTextureObject()
46 {
47   glGenTextures(1, (GLuint*) &m_texture);
48 }
49
50 void CGLTexture::DestroyTextureObject()
51 {
52   if (m_texture)
53     glDeleteTextures(1, (GLuint*) &m_texture);
54 }
55
56 void CGLTexture::LoadToGPU()
57 {
58   if (!m_pixels)
59   {
60     // nothing to load - probably same image (no change)
61     return;
62   }
63   if (m_texture == 0)
64   {
65     // Have OpenGL generate a texture object handle for us
66     // this happens only one time - the first time the texture is loaded
67     CreateTextureObject();
68   }
69
70   // Bind the texture object
71   glBindTexture(GL_TEXTURE_2D, m_texture);
72
73   // Set the texture's stretching properties
74   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
75   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
76   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
77   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
78
79   unsigned int maxSize = g_Windowing.GetMaxTextureSize();
80   if (m_textureHeight > maxSize)
81   {
82     CLog::Log(LOGERROR, "GL: Image height %d too big to fit into single texture unit, truncating to %u", m_textureHeight, maxSize);
83     m_textureHeight = maxSize;
84   }
85   if (m_textureWidth > maxSize)
86   {
87     CLog::Log(LOGERROR, "GL: Image width %d too big to fit into single texture unit, truncating to %u", m_textureWidth, maxSize);
88 #ifndef HAS_GLES
89     glPixelStorei(GL_UNPACK_ROW_LENGTH, m_textureWidth);
90     m_textureWidth = maxSize;
91   }
92
93   GLenum format = GL_BGRA;
94   GLint numcomponents = GL_RGBA;
95
96   switch (m_format)
97   {
98   case XB_FMT_DXT1:
99     format = GL_COMPRESSED_RGBA_S3TC_DXT1_EXT;
100     break;
101   case XB_FMT_DXT3:
102     format = GL_COMPRESSED_RGBA_S3TC_DXT3_EXT;
103     break;
104   case XB_FMT_DXT5:
105   case XB_FMT_DXT5_YCoCg:
106     format = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT;
107     break;
108   case XB_FMT_RGB8:
109     format = GL_RGB;
110     numcomponents = GL_RGB;
111     break;
112   case XB_FMT_A8R8G8B8:
113   default:
114     break;
115   }
116
117   if ((m_format & XB_FMT_DXT_MASK) == 0)
118   {
119     glTexImage2D(GL_TEXTURE_2D, 0, numcomponents, m_textureWidth, m_textureHeight, 0,
120       format, GL_UNSIGNED_BYTE, m_pixels);
121   }
122   else
123   {
124     // changed from glCompressedTexImage2D to support GL < 1.3
125     glCompressedTexImage2DARB(GL_TEXTURE_2D, 0, format,
126       m_textureWidth, m_textureHeight, 0, GetPitch() * GetRows(), m_pixels);
127   }
128
129   glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
130 #else   // GLES version
131     m_textureWidth = maxSize;
132   }
133
134   // All incoming textures are BGRA, which GLES does not necessarily support.
135   // Some (most?) hardware supports BGRA textures via an extension.
136   // If not, we convert to RGBA first to avoid having to swizzle in shaders.
137   // Explicitly define GL_BGRA_EXT here in the case that it's not defined by
138   // system headers, and trust the extension list instead.
139 #ifndef GL_BGRA_EXT
140 #define GL_BGRA_EXT 0x80E1
141 #endif
142
143   GLint internalformat;
144   GLenum pixelformat;
145
146   switch (m_format)
147   {
148     default:
149     case XB_FMT_RGBA8:
150       internalformat = pixelformat = GL_RGBA;
151       break;
152     case XB_FMT_RGB8:
153       internalformat = pixelformat = GL_RGB;
154       break;
155     case XB_FMT_A8R8G8B8:
156       if (g_Windowing.SupportsBGRA())
157       {
158         internalformat = pixelformat = GL_BGRA_EXT;
159       }
160       else if (g_Windowing.SupportsBGRAApple())
161       {
162         // Apple's implementation does not conform to spec. Instead, they require
163         // differing format/internalformat, more like GL.
164         internalformat = GL_RGBA;
165         pixelformat = GL_BGRA_EXT;
166       }
167       else
168       {
169         SwapBlueRed(m_pixels, m_textureHeight, GetPitch());
170         internalformat = pixelformat = GL_RGBA;
171       }
172       break;
173   }
174   glTexImage2D(GL_TEXTURE_2D, 0, internalformat, m_textureWidth, m_textureHeight, 0,
175     pixelformat, GL_UNSIGNED_BYTE, m_pixels);
176
177 #endif
178   VerifyGLState();
179
180   delete [] m_pixels;
181   m_pixels = NULL;
182
183   m_loadedToGPU = true;
184 }
185
186 void CGLTexture::BindToUnit(unsigned int unit)
187 {
188   // we support only 2 texture units at present
189 #ifndef HAS_GLES
190   glActiveTexture((unit == 1) ? GL_TEXTURE1_ARB : GL_TEXTURE0_ARB);
191   glBindTexture(GL_TEXTURE_2D, m_texture);
192   glEnable(GL_TEXTURE_2D);
193 #else // GLES
194   glActiveTexture((unit == 1) ? GL_TEXTURE1 : GL_TEXTURE0);
195   glBindTexture(GL_TEXTURE_2D, m_texture);
196 #endif
197 }
198
199 #endif // HAS_GL