+
+Texture2D::AsyncLoader::AsyncLoader(Texture2D &t, IO::Seekable &i):
+ texture(t),
+ io(i)
+{
+ char magic[4] = { };
+ io.read(magic, 4);
+ io.seek(0, IO::S_BEG);
+
+ if(DataFile::RawData::detect_signature(string(magic, 4)))
+ {
+ raw_data = new DataFile::RawData;
+ raw_data->open_io(io, "async");
+ }
+ else
+ img_loader = Graphics::ImageLoader::open_io(io);
+}
+
+Texture2D::AsyncLoader::~AsyncLoader()
+{
+ delete img_loader;
+ delete raw_data;
+}
+
+bool Texture2D::AsyncLoader::needs_sync() const
+{
+ return phase%2;
+}
+
+bool Texture2D::AsyncLoader::process()
+{
+ if(phase==0)
+ {
+ if(raw_data)
+ n_bytes = raw_data->get_size();
+ else
+ {
+ image.load_headers(*img_loader);
+ n_bytes = image.get_stride()*image.get_height();
+ }
+ }
+ else if(phase==1)
+ {
+ if(img_loader)
+ {
+ unsigned w = image.get_width();
+ unsigned h = image.get_height();
+ texture.storage(pixelformat_from_image(image, texture.use_srgb_format), w, h);
+ }
+
+ transfer = texture.sub_image_async(0, 0, 0, texture.width, texture.height);
+ }
+ else if(phase==2)
+ {
+ if(texture.swizzle==RGBA_TO_RGB)
+ {
+ const void *data;
+ if(raw_data)
+ {
+ raw_data->load();
+ data = raw_data->get_data();
+ }
+ else
+ {
+ image.load(*img_loader);
+ data = image.get_pixels();
+ }
+ texture.stage_pixels(transfer.get_address(), data, texture.width*texture.height);
+ }
+ else if(raw_data)
+ raw_data->load_into(transfer.get_address());
+ else
+ image.load_into(*img_loader, transfer.get_address());
+ }
+ else if(phase==3)
+ {
+ transfer = Texture2D::AsyncTransfer();
+
+ if(texture.auto_gen_mipmap)
+ texture.generate_mipmap();
+ }
+
+ ++phase;
+ return phase>3;
+}
+