GlTexture.cpp
Go to the documentation of this file.
1 #include "GlTexture.hpp"
2 #include "GlError.hpp"
3 #include "RenderTarget.hpp"
4 
6 
7 #include <cmath>
8 #include <algorithm>
9 
10 #include <ivorium_config.hpp>
11 
12 namespace iv
13 {
14 
16 {
17  { PixelFormat::RGBA, "RGBA" },
18  { PixelFormat::BGRA, "BGRA" }
19 };
20 
22 {
23  { ColorSpace::sRGB, "sRGB" },
24  { ColorSpace::Linear, "Linear" }
25 };
26 
28  _texture_id( 0 ),
29  _size( 0, 0 ),
30  _mipmaps( false ),
31  _format( PixelFormat::RGBA )
32 {
33 }
34 
36 {
37  return this->_size;
38 }
39 
40 GLuint GlTexture::texture_id() const
41 {
42  return this->_texture_id;
43 }
44 
46 {
47  return this->_texture_id;
48 }
49 
50 void GlTexture::CreateTexture( Context const * logger, RenderTarget * target, int2 size, GlMinFiltering min, GlMagFiltering mag, bool repeat, PixelFormat storage_format, ColorSpace color_space )
51 {
52  if( this->_texture_id )
53  this->DestroyTexture( logger, target );
54 
55  //
56  this->_size = size;
57  this->_format = storage_format;
58 
59  // compute mipmap requirements
60  GLsizei levels = 1;
62  if( this->_mipmaps )
63  levels = 1 + floor( log2( std::max( size.x, size.y ) ) );
64 
65  // generate texture id
66  glGenTextures( 1, &this->_texture_id );
67 
68  // bind texture
69  target->bind_texture( 0, this->_texture_id );
70 
71  // allocate storage
72  #if IV_GLPLATFORM_GLFW
73  this->_color_space = ColorSpace::Linear;
74  if( color_space == ColorSpace::sRGB )
75  {
76  if( storage_format == PixelFormat::RGBA )
77  glTexStorage2D( GL_TEXTURE_2D, 1, GL_SRGB8_ALPHA8, size.x, size.y );
78  else if( storage_format == PixelFormat::BGRA )
79  glTexStorage2D( GL_TEXTURE_2D, 1, GL_SRGB8_ALPHA8, size.x, size.y );
80  else
81  logger->log( SRC_INFO, iv::Defs::Log::Warning, "Pixel storage does not support storage format ", storage_format, " in sRGB space." );
82  }
83  else if( color_space == ColorSpace::Linear )
84  {
85  if( storage_format == PixelFormat::RGBA )
86  glTexStorage2D( GL_TEXTURE_2D, 1, GL_RGBA8, size.x, size.y );
87  else if( storage_format == PixelFormat::BGRA )
88  glTexStorage2D( GL_TEXTURE_2D, 1, GL_RGBA8, size.x, size.y );
89  else
90  logger->log( SRC_INFO, iv::Defs::Log::Warning, "Pixel storage does not support storage format ", storage_format, " in linear space." );
91  }
92  else
93  {
94  logger->log( SRC_INFO, iv::Defs::Log::Warning, "Pixel storage does not support color space ", color_space, "." );
95  }
96  #elif IV_GLPLATFORM_GLFM
97 
98  this->_color_space = color_space;
99  if( storage_format == PixelFormat::RGBA )
100  glTexStorage2D( GL_TEXTURE_2D, 1, GL_RGBA8, size.x, size.y );
101  else if( storage_format == PixelFormat::BGRA )
102  glTexStorage2D( GL_TEXTURE_2D, 1, GL_RGBA8, size.x, size.y );
103  else
104  logger->log( SRC_INFO, iv::Defs::Log::Warning, "Pixel storage does not support storage format ", storage_format, " in linear space." );
105 
106  #else
107  #error "Unimplemented colorspace handling for this GL platform."
108  #endif
109 
110  // parameter - repeat
111  glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, repeat ? GL_REPEAT : GL_CLAMP_TO_EDGE );
112  glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, repeat ? GL_REPEAT : GL_CLAMP_TO_EDGE );
113 
114  // parameter - filtering
115  glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, (GLint)mag );
116  glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, (GLint)min );
117 
118  //
119  GlError_Check( logger, SRC_INFO );
120 }
121 
122 void GlTexture::DestroyTexture( Context const * logger, RenderTarget * target )
123 {
124  if( this->_texture_id )
125  {
126  glDeleteTextures( 1, &this->_texture_id );
127  GlError_Check( logger, SRC_INFO );
128  this->_texture_id = 0;
129  this->_size = int2( 0, 0 );
130  this->_mipmaps = false;
131  }
132 }
133 
134 void GlTexture::DropTexture( Context const * logger, RenderTarget * target )
135 {
136  this->_texture_id = 0;
137  this->_size = int2( 0, 0 );
138  this->_mipmaps = false;
139 }
140 
141 void GlTexture::LoadData( Context const * logger, RenderTarget * target, uint8_t * values, size_t values_size, PixelFormat data_format )
142 {
143  // format to GL format
144  GLuint gl_format;
145  int bpp;
146  if( data_format == PixelFormat::RGBA )
147  gl_format = GL_RGBA,
148  bpp = 4;
149 #if IV_GLPLATFORM_GLFW
150  else if( data_format == PixelFormat::BGRA )
151  gl_format = GL_BGRA,
152  bpp = 4;
153 #endif
154  else
155  {
156  logger->log( SRC_INFO, Defs::Log::Warning, "Unsupported pixel format ", data_format," when loading texture data." );
157  return;
158  }
159 
160 
161  if( !this->_texture_id )
162  {
163  logger->log( SRC_INFO, Defs::Log::Warning, "Can not load pixel data. Texture is not allocated." );
164  return;
165  }
166 
167  if( values_size != this->_size.x * this->_size.y * bpp )
168  {
169  logger->log( SRC_INFO, Defs::Log::Warning, "Wrong number of color data values in pixel array." );
170  return;
171  }
172 
173  // check if formats are the same
174  if( data_format != this->_format )
175  logger->log( SRC_INFO, Defs::Log::Performance, "Loading data to texture with different PixelFormat (runtime transformation is needed)." );
176 
177  // bind texture
178  if( target )
179  target->bind_texture( 0, this->_texture_id );
180  else
181  glBindTexture( GL_TEXTURE_2D, this->_texture_id );
182 
183  glTexSubImage2D( GL_TEXTURE_2D, 0, 0, 0, this->_size.x, this->_size.y, gl_format, GL_UNSIGNED_BYTE, values );
184 
185  #warning "Disabled mimpams because it possibly causes crashes on Android."
186  //if( this->_mipmaps )
187  // glGenerateMipmap( GL_TEXTURE_2D );
188 
189  GlError_Check( logger, SRC_INFO );
190 }
191 
193 {
194  return this->_color_space;
195 }
196 
197 }