Buffer *Buffer::scratch_binding = 0;
Buffer::Buffer():
- size(0),
- allocated(false)
+ size(0)
{
static Require _req(ARB_vertex_buffer_object);
throw invalid_argument("Buffer::storage");
size = sz;
-}
-
-void Buffer::allocate()
-{
- if(size==0)
- throw invalid_operation("Buffer::allocate");
- if(allocated)
- return;
if(ARB_buffer_storage)
{
bind_scratch();
glBufferStorage(GL_ARRAY_BUFFER, size, 0, flags);
}
-
- allocated = true;
}
- else
- data(0);
-}
-
-void Buffer::data(const void *d)
-{
- if(size==0)
- throw invalid_operation("Buffer::data");
-
- if(ARB_buffer_storage)
- return sub_data(0, size, d);
-
- if(ARB_direct_state_access)
- glNamedBufferData(id, size, d, GL_STATIC_DRAW);
+ else if(ARB_direct_state_access)
+ glNamedBufferData(id, size, 0, GL_STATIC_DRAW);
else
{
bind_scratch();
- glBufferData(GL_ARRAY_BUFFER, size, d, GL_STATIC_DRAW);
+ glBufferData(GL_ARRAY_BUFFER, size, 0, GL_STATIC_DRAW);
}
+}
- allocated = true;
+void Buffer::data(const void *d)
+{
+ return sub_data(0, size, d);
}
void Buffer::sub_data(unsigned off, unsigned sz, const void *d)
if(size==0)
throw invalid_operation("Buffer::sub_data");
- allocate();
-
if(ARB_direct_state_access)
glNamedBufferSubData(id, off, sz, d);
else
{
static Require _req(ARB_map_buffer_range);
- allocate();
if(ARB_direct_state_access)
return glMapNamedBufferRange(id, 0, size, GL_MAP_READ_BIT|GL_MAP_WRITE_BIT);
else
private:
unsigned id;
unsigned size;
- bool allocated;
static Buffer *scratch_binding;
be uploaded. Storage cannot be changed once set. */
void storage(unsigned);
- /** Allocates storage for the buffer. The contents are initially undefined.
- If storage has already been allocated, does nothing. */
- void allocate();
-
/** Uploads data into the buffer, completely replacing any previous
contents. Storage must be defined beforehand. The data must have size
matching the defined storage. */
void Framebuffer::attach(FrameAttachment attch, Texture2D &tex, unsigned level)
{
- tex.allocate(level);
set_attachment(make_typed_attachment(attch, tex.get_format()), tex, level, 0, 0);
}
void Framebuffer::attach(FrameAttachment attch, Texture3D &tex, unsigned layer, unsigned level)
{
- tex.allocate(level);
set_attachment(make_typed_attachment(attch, tex.get_format()), tex, level, layer, 0);
}
void Framebuffer::attach(FrameAttachment attch, TextureCube &tex, TextureCubeFace face, unsigned level)
{
- tex.allocate(level);
set_attachment(make_typed_attachment(attch, tex.get_format()), tex, level, TextureCube::get_face_index(face), 0);
}
void Framebuffer::attach_layered(FrameAttachment attch, Texture3D &tex, unsigned level)
{
static Require _req(ARB_geometry_shader4);
- tex.allocate(level);
set_attachment(make_typed_attachment(attch, tex.get_format()), tex, level, -1, 0);
}
void Framebuffer::attach_layered(FrameAttachment attch, TextureCube &tex, unsigned level)
{
static Require _req(ARB_geometry_shader4);
- tex.allocate(level);
set_attachment(make_typed_attachment(attch, tex.get_format()), tex, level, -1, 0);
}
Texture1D::Texture1D():
Texture(GL_TEXTURE_1D),
- width(0),
- allocated(0)
+ width(0)
{
static Require _req(MSP_texture1D);
}
levels = get_n_levels();
if(lv)
levels = min(levels, lv);
-}
-
-void Texture1D::allocate(unsigned level)
-{
- if(width==0)
- throw invalid_operation("Texture1D::allocate");
- if(level>=levels)
- throw invalid_argument("Texture1D::allocate");
- if(allocated&(1<<level))
- return;
+ GLenum gl_fmt = get_gl_pixelformat(storage_fmt);
if(ARB_texture_storage)
{
- GLenum fmt = get_gl_pixelformat(storage_fmt);
if(ARB_direct_state_access)
- glTextureStorage1D(id, levels, fmt, width);
+ glTextureStorage1D(id, levels, gl_fmt, width);
else
{
bind_scratch();
- glTexStorage1D(target, levels, fmt, width);
+ glTexStorage1D(target, levels, gl_fmt, width);
}
- apply_swizzle();
- allocated |= (1<<levels)-1;
}
else
- image(level, 0);
-}
-
-void Texture1D::image(unsigned level, const void *data)
-{
- if(width==0)
- throw invalid_operation("Texture1D::image");
- if(level>=levels)
- throw out_of_range("Texture1D::image");
-
- if(ARB_texture_storage)
- return sub_image(level, 0, get_level_size(level), data);
-
- bind_scratch();
-
- if(!allocated)
{
+ bind_scratch();
glTexParameteri(target, GL_TEXTURE_MAX_LEVEL, levels-1);
- apply_swizzle();
+ GLenum comp = get_gl_components(get_components(storage_fmt));
+ GLenum type = get_gl_type(get_component_type(storage_fmt));
+ for(unsigned i=0; i<levels; ++i)
+ glTexImage1D(target, i, gl_fmt, get_level_size(i), 0, comp, type, 0);
}
- GLenum fmt = get_gl_pixelformat(storage_fmt);
- GLenum comp = get_gl_components(get_components(storage_fmt));
- GLenum type = get_gl_type(get_component_type(storage_fmt));
- glTexImage1D(target, level, fmt, get_level_size(level), 0, comp, type, data);
+ apply_swizzle();
+}
- allocated |= 1<<level;
+void Texture1D::image(unsigned level, const void *data)
+{
+ return sub_image(level, 0, get_level_size(level), data);
}
void Texture1D::sub_image(unsigned level, int x, unsigned wd, const void *data)
if(level>=levels)
throw out_of_range("Texture1D::sub_image");
- allocate(level);
-
GLenum comp = get_gl_components(get_components(storage_fmt));
GLenum type = get_gl_type(get_component_type(storage_fmt));
if(ARB_direct_state_access)
private:
unsigned width;
unsigned levels;
- unsigned allocated;
public:
Texture1D();
void storage(PixelFormat, unsigned, unsigned = 0);
- void allocate(unsigned);
void image(unsigned, const void *);
void sub_image(unsigned, int, unsigned, const void *);
virtual void image(const Graphics::Image &, unsigned = 0);
Texture2D::Texture2D(ResourceManager *m):
Texture(GL_TEXTURE_2D, m),
width(0),
- height(0),
- allocated(0)
+ height(0)
{ }
Texture2D::~Texture2D()
levels = get_n_levels();
if(lv>0)
levels = min(levels, lv);
-}
-
-void Texture2D::allocate(unsigned level)
-{
- if(width==0 || height==0)
- throw invalid_operation("Texture2D::allocate");
- if(level>=levels)
- throw invalid_argument("Texture2D::allocate");
- if(allocated&(1<<level))
- return;
+ GLenum gl_fmt = get_gl_pixelformat(storage_fmt);
if(ARB_texture_storage)
{
- GLenum fmt = get_gl_pixelformat(storage_fmt);
if(ARB_direct_state_access)
- glTextureStorage2D(id, levels, fmt, width, height);
+ glTextureStorage2D(id, levels, gl_fmt, width, height);
else
{
bind_scratch();
- glTexStorage2D(target, levels, fmt, width, height);
+ glTexStorage2D(target, levels, gl_fmt, width, height);
}
- apply_swizzle();
- allocated |= (1<<levels)-1;
}
else
- image(level, 0);
-}
-
-void Texture2D::image(unsigned level, const void *data)
-{
- if(width==0 || height==0)
- throw invalid_operation("Texture2D::image");
- if(level>=levels)
- throw out_of_range("Texture2D::image");
-
- LinAl::Vector<unsigned, 2> size = get_level_size(level);
-
- if(ARB_texture_storage)
- return sub_image(level, 0, 0, size.x, size.y, data);
-
- bind_scratch();
-
- if(!allocated)
{
+ bind_scratch();
glTexParameteri(target, GL_TEXTURE_MAX_LEVEL, levels-1);
- apply_swizzle();
+ GLenum comp = get_gl_components(get_components(storage_fmt));
+ GLenum type = get_gl_type(get_component_type(storage_fmt));
+ for(unsigned i=0; i<levels; ++i)
+ {
+ LinAl::Vector<unsigned, 2> lv_size = get_level_size(i);
+ glTexImage2D(target, i, gl_fmt, lv_size.x, lv_size.y, 0, comp, type, 0);
+ }
}
- GLenum fmt = get_gl_pixelformat(storage_fmt);
- GLenum comp = get_gl_components(get_components(storage_fmt));
- GLenum type = get_gl_type(get_component_type(storage_fmt));
- glTexImage2D(target, level, fmt, size.x, size.y, 0, comp, type, data);
+ apply_swizzle();
+}
- allocated |= 1<<level;
+void Texture2D::image(unsigned level, const void *data)
+{
+ LinAl::Vector<unsigned, 2> size = get_level_size(level);
+ return sub_image(level, 0, 0, size.x, size.y, data);
}
void Texture2D::sub_image(unsigned level, int x, int y, unsigned wd, unsigned ht, const void *data)
if(level>=levels)
throw out_of_range("Texture2D::sub_image");
- allocate(level);
-
GLenum comp = get_gl_components(get_components(storage_fmt));
GLenum type = get_gl_type(get_component_type(storage_fmt));
if(ARB_direct_state_access)
{
glDeleteTextures(1, &id);
id = 0;
- allocated = 0;
}
unsigned width;
unsigned height;
unsigned levels;
- unsigned allocated;
public:
Texture2D(ResourceManager * = 0);
it can't be changed. */
void storage(PixelFormat fmt, unsigned wd, unsigned ht, unsigned lv = 0);
- /** Allocates storage for the texture. The contents are initially
- undefined. If storage has already been allocated, does nothing. */
- void allocate(unsigned level);
-
/** Updates the contents of the entire texture. Storage must be defined
beforehand. The image data must have dimensions and format matching the
defined storage. */
Texture(t),
width(0),
height(0),
- depth(0),
- allocated(0)
+ depth(0)
{ }
Texture3D::Texture3D():
Texture(GL_TEXTURE_3D),
width(0),
height(0),
- depth(0),
- allocated(0)
+ depth(0)
{
static Require _req(EXT_texture3D);
}
levels = get_n_levels();
if(lv>0)
levels = min(levels, lv);
-}
-
-void Texture3D::allocate(unsigned level)
-{
- if(width==0 || height==0 || depth==0)
- throw invalid_operation("Texture3D::allocate");
- if(level>=levels)
- throw invalid_argument("Texture3D::allocate");
- if(allocated&(1<<level))
- return;
+ GLenum gl_fmt = get_gl_pixelformat(storage_fmt);
if(ARB_texture_storage)
{
- GLenum fmt = get_gl_pixelformat(storage_fmt);
if(ARB_direct_state_access)
- glTextureStorage3D(id, levels, fmt, width, height, depth);
+ glTextureStorage3D(id, levels, gl_fmt, width, height, depth);
else
{
bind_scratch();
- glTexStorage3D(target, levels, fmt, width, height, depth);
+ glTexStorage3D(target, levels, gl_fmt, width, height, depth);
}
- apply_swizzle();
- allocated |= (1<<levels)-1;
}
else
- image(level, 0);
-}
-
-void Texture3D::image(unsigned level, const void *data)
-{
- if(width==0 || height==0 || depth==0)
- throw invalid_operation("Texture3D::image");
- if(level>=levels)
- throw out_of_range("Texture3D::image");
-
- LinAl::Vector<unsigned, 3> size = get_level_size(level);
-
- if(ARB_texture_storage)
- return sub_image(level, 0, 0, 0, size.x, size.y, size.z, data);
-
- bind_scratch();
-
- if(!allocated)
{
+ bind_scratch();
+ GLenum comp = get_gl_components(get_components(storage_fmt));
+ GLenum type = get_gl_type(get_component_type(storage_fmt));
+ for(unsigned i=0; i<levels; ++i)
+ {
+ LinAl::Vector<unsigned, 3> lv_size = get_level_size(i);
+ glTexImage3D(target, i, gl_fmt, lv_size.x, lv_size.y, lv_size.z, 0, comp, type, 0);
+ }
glTexParameteri(target, GL_TEXTURE_MAX_LEVEL, levels-1);
- apply_swizzle();
}
- GLenum fmt = get_gl_pixelformat(storage_fmt);
- GLenum comp = get_gl_components(get_components(storage_fmt));
- GLenum type = get_gl_type(get_component_type(storage_fmt));
- glTexImage3D(target, level, fmt, size.x, size.y, size.z, 0, comp, type, data);
+ apply_swizzle();
+}
- allocated |= 1<<level;
+void Texture3D::image(unsigned level, const void *data)
+{
+ LinAl::Vector<unsigned, 3> size = get_level_size(level);
+ return sub_image(level, 0, 0, 0, size.x, size.y, size.z, data);
}
void Texture3D::sub_image(unsigned level, int x, int y, int z, unsigned wd, unsigned ht, unsigned dp, const void *data)
if(level>=levels)
throw out_of_range("Texture3D::sub_image");
- allocate(level);
-
GLenum comp = get_gl_components(get_components(storage_fmt));
GLenum type = get_gl_type(get_component_type(storage_fmt));
if(ARB_direct_state_access)
unsigned height;
unsigned depth;
unsigned levels;
- unsigned allocated;
Texture3D(GLenum);
public:
it can't be changed. */
void storage(PixelFormat fmt, unsigned wd, unsigned ht, unsigned dp, unsigned lv = 0);
- /** Allocates storage for the texture. The contents are initially
- undefined. If storage has already been allocated, does nothing. */
- void allocate(unsigned level);
-
/** Updates the contents of the entire texture. Storage must be defined
beforehand. The image data must have dimensions and format matching the
defined storage. */
TextureCube::TextureCube():
Texture(GL_TEXTURE_CUBE_MAP),
- size(0),
- allocated(0)
+ size(0)
{
static Require _req(ARB_texture_cube_map);
if(ARB_seamless_cube_map)
levels = get_n_levels();
if(lv>0)
levels = min(levels, lv);
-}
-
-void TextureCube::allocate(unsigned level)
-{
- if(size==0)
- throw invalid_operation("TextureCube::allocate");
- if(level>=levels)
- throw invalid_argument("TextureCube::allocate");
- if(allocated&(64<<level))
- return;
+ GLenum gl_fmt = get_gl_pixelformat(storage_fmt);
if(ARB_texture_storage)
{
- GLenum fmt = get_gl_pixelformat(storage_fmt);
if(ARB_direct_state_access)
- glTextureStorage2D(id, levels, fmt, size, size);
+ glTextureStorage2D(id, levels, gl_fmt, size, size);
else
{
bind_scratch();
- glTexStorage2D(target, levels, fmt, size, size);
+ glTexStorage2D(target, levels, gl_fmt, size, size);
}
- apply_swizzle();
- allocated |= (64<<levels)-1;
}
else
{
- for(unsigned i=0; i<6; ++i)
- image(enumerate_faces(i), level, 0);
+ bind_scratch();
+ GLenum comp = get_gl_components(get_components(storage_fmt));
+ GLenum type = get_gl_type(get_component_type(storage_fmt));
+ for(unsigned i=0; i<levels; ++i)
+ {
+ unsigned lv_size = get_level_size(i);
+ for(unsigned j=0; j<6; ++j)
+ glTexImage2D(enumerate_faces(j), i, gl_fmt, lv_size, lv_size, 0, comp, type, 0);
+ }
+ glTexParameteri(target, GL_TEXTURE_MAX_LEVEL, levels-1);
}
+
+ apply_swizzle();
}
void TextureCube::image(TextureCubeFace face, unsigned level, const void *data)
{
- if(size==0)
- throw invalid_operation("TextureCube::image");
- if(level>=levels)
- throw out_of_range("TextureCube::image");
-
unsigned lsz = get_level_size(level);
-
- if(ARB_texture_storage)
- return sub_image(face, level, 0, 0, lsz, lsz, data);
-
- if(!allocated)
- {
- glTexParameteri(target, GL_TEXTURE_MAX_LEVEL, levels-1);
- apply_swizzle();
- }
-
- GLenum fmt = get_gl_pixelformat(storage_fmt);
- GLenum comp = get_gl_components(get_components(storage_fmt));
- GLenum type = get_gl_type(get_component_type(storage_fmt));
- glTexImage2D(face, level, fmt, lsz, lsz, 0, comp, type, data);
-
- if(level==0)
- {
- allocated |= 1<<get_face_index(face);
- if((allocated&63)==63)
- allocated |= 64;
- }
- else if(!(allocated&(64<<level)))
- {
- for(unsigned i=0; i<6; ++i)
- if(enumerate_faces(i)!=face)
- glTexImage2D(enumerate_faces(i), level, fmt, lsz, lsz, 0, comp, type, 0);
-
- allocated |= 64<<level;
- }
+ return sub_image(face, level, 0, 0, lsz, lsz, data);
}
void TextureCube::sub_image(TextureCubeFace face, unsigned level, int x, int y, unsigned wd, unsigned ht, const void *data)
if(level>=levels)
throw out_of_range("TextureCube::sub_image");
- allocate(level);
-
GLenum comp = get_gl_components(get_components(storage_fmt));
GLenum type = get_gl_type(get_component_type(storage_fmt));
if(ARB_direct_state_access)
private:
unsigned size;
unsigned levels;
- /* Lowest six bits track allocation status of faces on the base level. Bit
- seven is set if the entire base level is allocated. */
- unsigned allocated;
static TextureCubeFace face_order[6];
static Vector3 directions[6];
it can't be changed. */
void storage(PixelFormat fmt, unsigned size, unsigned lv = 0);
- /** Allocates storage for the cube faces. The contents are initially
- undefined. If storage has already been allocated, does nothing. */
- void allocate(unsigned level);
-
/** Updates the contents of a face. Storage must be defined beforehand.
The image data must have dimensions and format matching the defined
storage. */