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():
35 Texture(GL_TEXTURE_2D)
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;
47 GLenum gl_fmt = get_gl_pixelformat(storage_fmt);
48 if(ARB_texture_storage)
50 if(ARB_direct_state_access)
51 glTextureStorage2D(id, levels, gl_fmt, width, height);
55 glTexStorage2D(target, levels, gl_fmt, width, height);
61 glTexParameteri(target, GL_TEXTURE_MAX_LEVEL, levels-1);
62 GLenum comp = get_gl_components(get_components(storage_fmt));
63 GLenum type = get_gl_type(get_component_type(storage_fmt));
64 for(unsigned i=0; i<levels; ++i)
66 auto lv_size = static_cast<const Texture2D *>(this)->get_level_size(i);
67 glTexImage2D(target, i, gl_fmt, lv_size.x, lv_size.y, 0, comp, type, 0);
74 void OpenGLTexture2D::sub_image(unsigned level, int x, int y, unsigned wd, unsigned ht, const void *data)
76 GLenum comp = get_gl_components(get_components(storage_fmt));
77 GLenum type = get_gl_type(get_component_type(storage_fmt));
78 if(ARB_direct_state_access)
79 glTextureSubImage2D(id, level, x, y, wd, ht, comp, type, data);
83 glTexSubImage2D(target, level, x, y, wd, ht, comp, type, data);
87 void OpenGLTexture2D::sub_image(unsigned level, int x, int y, unsigned wd, unsigned ht, const Buffer &buffer, unsigned offset)
89 glBindBuffer(GL_PIXEL_UNPACK_BUFFER, buffer.id);
90 sub_image(level, x, y, wd, ht, reinterpret_cast<void *>(offset));
91 glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
94 Resource::AsyncLoader *OpenGLTexture2D::create_async_loader(IO::Seekable &io)
96 return new AsyncLoader(static_cast<Texture2D &>(*this), io);
99 void OpenGLTexture2D::unload()
101 glDeleteTextures(1, &id);
106 OpenGLTexture2D::AsyncLoader::AsyncLoader(Texture2D &t, IO::Seekable &i):
110 img_loader(Graphics::ImageLoader::open_io(io)),
114 OpenGLTexture2D::AsyncLoader::~AsyncLoader()
117 pixel_buffer.unmap();
121 bool OpenGLTexture2D::AsyncLoader::needs_sync() const
126 bool OpenGLTexture2D::AsyncLoader::process()
130 image.load_headers(*img_loader);
131 n_bytes = image.get_stride()*image.get_height();
135 pixel_buffer.storage(n_bytes);
136 mapped_address = reinterpret_cast<char *>(pixel_buffer.map());
139 image.load_into(*img_loader, mapped_address);
143 if(!pixel_buffer.unmap())
152 unsigned w = image.get_width();
153 unsigned h = image.get_height();
154 texture.storage(pixelformat_from_image(image, texture.use_srgb_format), w, h);
155 texture.OpenGLTexture2D::sub_image(0, 0, 0, w, h, pixel_buffer, 0);
157 if(texture.auto_gen_mipmap)
158 texture.generate_mipmap();