StreamTexture.cpp
Go to the documentation of this file.
1 #include "StreamTexture.hpp"
2 #include "ImageLoader.hpp"
3 
4 namespace iv
5 {
6 
7 //======================== TextureMetadata ==============================
10  cm( inst, this, "StreamTexture_Subprovider" )
11 {
13 
14  provider->with_metadata_stream(
15  [&]( std::istream & metadata_file )
16  {
17  this->Parse_EachResource( metadata_file );
18  }
19  );
20 }
21 
22 void StreamTexture_Subprovider::Resource( std::string const & resource_class, ResourcePath path )
23 {
24  if( resource_class == "texture" )
25  {
26  Texture::Metadata vals;
27 
28  this->Parse_EachParameter(
29  [ & ]( std::string const & param, std::string const & value )
30  {
31  if( param == "width" )
32  vals.size.x = atoi( value.c_str() );
33  else if( param == "height" )
34  vals.size.y = atoi( value.c_str() );
35  else if( param == "density" )
36  vals.density = atof( value.c_str() );
37  else if( param == "hitmap" )
38  vals.hitmap = value == "True";
39  else if( param == "instant_loading" )
40  vals.instant_loading = value == "True";
41  else if( param == "filtering" )
42  {
43  if( value == "Nearest" )
44  vals.filtering = Texture::Filtering::Nearest;
45  else if( value == "SmoothMsdf" )
46  vals.filtering = Texture::Filtering::SmoothMsdf;
47  else if( value == "Smooth2D" )
48  vals.filtering = Texture::Filtering::Smooth2D;
49  else if( value == "Smooth3D" )
50  vals.filtering = Texture::Filtering::Smooth3D;
51  else
52  {
53  this->cm.warning( SRC_INFO, "Unrecognized 'filtering' value '",value,"'." );
54  vals.filtering = Texture::Filtering::Nearest;
55  }
56  }
57  else if( param == "color_space" )
58  {
59  if( value == "linear" )
61  else if( value == "sRGB" )
63  else
64  {
65  this->cm.warning( SRC_INFO, "Unrecognized 'color_space' value '",value,"'." );
66  vals.color_space = ColorSpace::sRGB;
67  }
68  }
69  else if( param == "msdf_pixelRange" )
70  vals.msdf_pixelRange = atof( value.c_str() );
71  else if( param == "pixel_format" )
72  {
73  if( value == "RGBA" )
74  vals.format = PixelFormat::RGBA;
75  else
76  {
77  this->cm.warning( SRC_INFO, "Unrecognized 'pixel_format' value '",value,"'." );
78  vals.format = PixelFormat::RGBA;
79  }
80  }
81  else
82  {
83  this->cm.warning( SRC_INFO, "Unrecognized metadata parameter '",param,"'." );
84  }
85  }
86  );
87 
88  this->_textures[ path ] = vals;
89  }
90  else
91  {
92  this->Parse_EachParameter();
93  }
94 }
95 
96 void StreamTexture_Subprovider::each_resource( std::function< void( ResourcePath const & ) > const & f ) const
97 {
98  for( auto & [ path, metadata ] : this->_textures )
99  f( path );
100 }
101 
102 bool StreamTexture_Subprovider::has_resource( ResourcePath const & path ) const
103 {
104  return this->_textures.count( path );
105 }
106 
107 Texture::Metadata const & StreamTexture_Subprovider::get( ResourcePath const & path ) const
108 {
109  auto it = this->_textures.find( path );
110  if( it != this->_textures.end() )
111  {
112  return it->second;
113  }
114  else
115  {
116  this->cm.warning( SRC_INFO, "ImageMetadata not found for resource '", path.string(), "'." );
117  return this->_empty;
118  }
119 }
120 
121 //============================== StreamTexture ================================================================
122 StreamTexture::StreamTexture( Instance * inst, StreamResourceProvider const * provider, StreamTexture_Subprovider const * subprovider, ResourcePath const & path ) :
123  Texture( inst ),
124  StreamResource( inst, provider, path ),
125  GlListener( inst ),
126  DelayedLoad( inst ),
127  cm( inst, this, "StreamTexture" )
128 {
129  // mark
130  this->cm.inherits( this->Texture::cm, this->StreamResource::cm, this->DelayedLoad::cm );
131 
132  // load metadata
133  this->_metadata = subprovider->get( path );
134 
135  // gl enable
136  this->cm.log( SRC_INFO, ::iv::Defs::Log::TextureState, "Texture created." );
137  if( this->GlIsEnabled() )
138  this->GlEnable();
139  else
140  this->cm.log( SRC_INFO, ::iv::Defs::Log::TextureState, "Not loading - OpenGL not enabled yet." );
141 }
142 
144 {
145  GlInfo gl_info( this->instance() );
146  this->_gl_texture.DestroyTexture( &this->cm, gl_info.render_target() );
147 }
148 
150 {
151  if( this->_metadata.instant_loading )
152  {
153  this->cm.log( SRC_INFO, ::iv::Defs::Log::TextureState, "Loading to GPU (instant loading is enabled for this texture)." );
154  this->Load();
155  }
156  else
157  {
158  auto complexity_bytes = this->_metadata.size.x * this->_metadata.size.y * 4;
159  if( this->_metadata.hitmap )
160  complexity_bytes *= 2;
161  this->cm.log( SRC_INFO, ::iv::Defs::Log::TextureState, "Queuing delayed load (instant loading is disabled for this texture)." );
162  this->RequestDelayedLoad( complexity_bytes );
163  }
164 }
165 
167 {
168  this->cm.log( SRC_INFO, ::iv::Defs::Log::TextureState, "Unloading texture - OpenGl is disabled." );
169  GlInfo gl_info( this->instance() );
170  this->_gl_texture.DestroyTexture( &this->cm, gl_info.render_target() );
171 }
172 
174 {
175  this->cm.log( SRC_INFO, ::iv::Defs::Log::TextureState, "Dropping texture - OpenGl is dropped." );
176  GlInfo gl_info( this->instance() );
177  this->_gl_texture.DropTexture( &this->cm, gl_info.render_target() );
178 }
179 
181 {
182  if( !this->GlIsEnabled() )
183  {
184  this->cm.log( SRC_INFO, ::iv::Defs::Log::TextureState, "Texture load skipped - OpenGL is disabled." );
185  return;
186  }
187 
188  this->cm.log( SRC_INFO, ::iv::Defs::Log::TextureState, "Calling ImageLoader." );
189  ImageLoader_Load( this, this->_metadata.format,
190  [&]( ImageLoader_Metadata const & metadata, uint8_t * bytes, size_t bytes_count )
191  {
192  // load texture to GPU
193  this->cm.log( SRC_INFO, ::iv::Defs::Log::TextureState, "Loading texture to GPU." );
194  GlInfo gl_info( this->instance() );
195  this->_gl_texture.CreateTexture( &this->cm, gl_info.render_target(), metadata.size, this->min_filtering(), this->mag_filtering(), false, metadata.pixel_format, this->_metadata.color_space );
196  this->_gl_texture.LoadData( &this->cm, gl_info.render_target(), bytes, bytes_count, metadata.pixel_format );
197 
198  // load hitmap
199  if( this->_metadata.hitmap )
200  if( this->_hitmap.empty() )
201  {
202  this->cm.log( SRC_INFO, ::iv::Defs::Log::TextureState, "Loading hitmap for texture." );
203 
204  // load hittest data
205  this->_hitmap.resize( metadata.size.x * metadata.size.y );
206  for( size_t x = 0; x < metadata.size.x; x++ )
207  for( size_t y = 0; y < metadata.size.y; y++ )
208  {
209  uint8_t pixel = 0;
210  if( metadata.pixel_format == PixelFormat::RGBA || metadata.pixel_format == PixelFormat::BGRA )
211  pixel = bytes[ ( y * metadata.size.x + x ) * 4 + 3 ];
212  else
213  this->cm.log( SRC_INFO, Defs::Log::Warning, "Unsupported pixel format when generating hitmap." );
214 
215  this->_hitmap[ y * metadata.size.x + x ] = pixel > 0;
216  }
217  }
218  }
219  );
220 }
221 
223 {
225  return GlMinFiltering::Linear;
230  else
232 }
233 
235 {
237  return GlMagFiltering::Linear;
239  return GlMagFiltering::Linear;
241  return GlMagFiltering::Linear;
242  else
244 }
245 
246 }