1 #include <msp/gl/extensions/arb_direct_state_access.h>
2 #include <msp/gl/extensions/arb_texture_storage.h>
3 #include <msp/gl/extensions/arb_vertex_buffer_object.h>
4 #include <msp/graphics/imageloader.h>
8 #include "texture2d_backend.h"
13 class OpenGLTexture2D::AsyncLoader: public Resource::AsyncLoader
20 Graphics::Image image;
21 Graphics::ImageLoader *img_loader;
26 AsyncLoader(Texture2D &, IO::Seekable &);
29 virtual bool needs_sync() const;
30 virtual bool process();
34 OpenGLTexture2D::OpenGLTexture2D(ResourceManager *m):
35 Texture(GL_TEXTURE_2D, m)
38 void OpenGLTexture2D::allocate()
40 unsigned width = static_cast<const Texture2D *>(this)->width;
41 unsigned height = static_cast<const Texture2D *>(this)->height;
42 unsigned levels = static_cast<const Texture2D *>(this)->levels;
44 GLenum gl_fmt = get_gl_pixelformat(storage_fmt);
45 if(ARB_texture_storage)
47 if(ARB_direct_state_access)
48 glTextureStorage2D(id, levels, gl_fmt, width, height);
52 glTexStorage2D(target, levels, gl_fmt, width, height);
58 glTexParameteri(target, GL_TEXTURE_MAX_LEVEL, levels-1);
59 GLenum comp = get_gl_components(get_components(storage_fmt));
60 GLenum type = get_gl_type(get_component_type(storage_fmt));
61 for(unsigned i=0; i<levels; ++i)
63 auto lv_size = static_cast<const Texture2D *>(this)->get_level_size(i);
64 glTexImage2D(target, i, gl_fmt, lv_size.x, lv_size.y, 0, comp, type, 0);
71 void OpenGLTexture2D::sub_image(unsigned level, int x, int y, unsigned wd, unsigned ht, const void *data)
73 GLenum comp = get_gl_components(get_components(storage_fmt));
74 GLenum type = get_gl_type(get_component_type(storage_fmt));
75 if(ARB_direct_state_access)
76 glTextureSubImage2D(id, level, x, y, wd, ht, comp, type, data);
80 glTexSubImage2D(target, level, x, y, wd, ht, comp, type, data);
84 void OpenGLTexture2D::sub_image(unsigned level, int x, int y, unsigned wd, unsigned ht, const Buffer &buffer, unsigned offset)
86 glBindBuffer(GL_PIXEL_UNPACK_BUFFER, buffer.id);
87 sub_image(level, x, y, wd, ht, reinterpret_cast<void *>(offset));
88 glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
91 Resource::AsyncLoader *OpenGLTexture2D::create_async_loader(IO::Seekable &io)
93 return new AsyncLoader(static_cast<Texture2D &>(*this), io);
96 void OpenGLTexture2D::unload()
98 glDeleteTextures(1, &id);
103 OpenGLTexture2D::AsyncLoader::AsyncLoader(Texture2D &t, IO::Seekable &i):
107 img_loader(Graphics::ImageLoader::open_io(io)),
111 OpenGLTexture2D::AsyncLoader::~AsyncLoader()
114 pixel_buffer.unmap();
118 bool OpenGLTexture2D::AsyncLoader::needs_sync() const
123 bool OpenGLTexture2D::AsyncLoader::process()
127 image.load_headers(*img_loader);
128 n_bytes = image.get_stride()*image.get_height();
132 pixel_buffer.storage(n_bytes);
133 mapped_address = reinterpret_cast<char *>(pixel_buffer.map());
136 image.load_into(*img_loader, mapped_address);
140 if(!pixel_buffer.unmap())
147 texture.generate_id();
149 unsigned w = image.get_width();
150 unsigned h = image.get_height();
151 texture.storage(pixelformat_from_image(image, texture.use_srgb_format), w, h);
152 texture.OpenGLTexture2D::sub_image(0, 0, 0, w, h, pixel_buffer, 0);
154 if(texture.auto_gen_mipmap)
155 texture.generate_mipmap();