ifmt(RGB),
min_filter(NEAREST_MIPMAP_LINEAR),
mag_filter(LINEAR),
- mipmap_levels(0),
max_anisotropy(1.0f),
wrap_s(REPEAT),
wrap_t(REPEAT),
glTexParameteriv(target, GL_TEXTURE_SWIZZLE_RGBA, swizzle_orders+swizzle*4);
}
}
- if(mask&MIPMAP_LEVELS)
- set_parameter_i(GL_TEXTURE_MAX_LEVEL, (mipmap_levels ? mipmap_levels-1 : 1000));
}
void Texture::set_parameter_i(GLenum param, int value) const
set_mag_filter(f==NEAREST ? NEAREST : LINEAR);
}
-void Texture::set_mipmap_levels(unsigned l)
-{
- mipmap_levels = l;
- update_parameter(MIPMAP_LEVELS);
-}
-
void Texture::set_max_anisotropy(float a)
{
if(a<1.0f)
}
void Texture::load_image(const string &fn, bool srgb)
+{
+ load_image(fn, 0, srgb);
+}
+
+void Texture::load_image(const string &fn, unsigned lv, bool srgb)
{
Graphics::Image img;
img.load_file(fn);
- image(img, srgb);
+ image(img, lv, srgb);
+}
+
+void Texture::image(const Graphics::Image &img, bool srgb)
+{
+ image(img, 0, srgb);
}
void Texture::bind_to(unsigned i) const
void Texture::Loader::init()
{
+ levels = 0;
if(Resources *res = dynamic_cast<Resources *>(coll))
srgb = res->get_srgb_conversion();
else
throw IO::file_not_found(fn);
img.load_io(*io);
- obj.image(img, srgb);
+ obj.image(img, levels, srgb);
}
void Texture::Loader::filter(TextureFilter f)
IO::Memory mem(data.data(), data.size());
img.load_io(mem);
- obj.image(img, srgb);
+ obj.image(img, levels, srgb);
}
void Texture::Loader::mag_filter(TextureFilter f)
void Texture::Loader::mipmap_levels(unsigned l)
{
- obj.set_mipmap_levels(l);
+ levels = l;
}
void Texture::Loader::wrap(TextureWrap w)
class Loader: public DataFile::CollectionObjectLoader<Texture>
{
protected:
+ unsigned levels;
bool srgb;
public:
COMPARE = 64,
COMPARE_FUNC = 128,
MAX_ANISOTROPY = 256,
- FORMAT_SWIZZLE = 512,
- MIPMAP_LEVELS = 1024
+ FORMAT_SWIZZLE = 512
};
enum FormatSwizzle
FormatSwizzle swizzle;
TextureFilter min_filter;
TextureFilter mag_filter;
- unsigned mipmap_levels;
float max_anisotropy;
TextureWrap wrap_s;
TextureWrap wrap_t;
is not applicable to magnification, LINEAR is used instead. */
void set_filter(TextureFilter);
- void set_mipmap_levels(unsigned);
+ DEPRECATED void set_mipmap_levels(unsigned) { }
void set_max_anisotropy(float);
/// Loads a Graphics::Image from a file and uploads it to the texture.
virtual void load_image(const std::string &, bool srgb = false);
+ virtual void load_image(const std::string &, unsigned, bool srgb = false);
+
/** Uploads an image to the texture. If storage has not been defined, it
will be set to match the image. Otherwise the image must be compatible
with the defined storage. Semantics depend on the type of texture.
If srgb is true and storage is determined by this call, then an sRGB pixel
format will be used. */
- virtual void image(const Graphics::Image &, bool srgb = false) = 0;
+ virtual void image(const Graphics::Image &, bool srgb = false);
+
+ virtual void image(const Graphics::Image &, unsigned, bool srgb = false) = 0;
GLenum get_target() const { return target; }
unsigned get_id() const { return id; }
return sub_image(level, 0, w, fmt, type, data);
BindRestore _bind(this);
+
+ if(!allocated)
+ glTexParameteri(target, GL_TEXTURE_MAX_LEVEL, levels-1);
glTexImage1D(target, level, ifmt, w, 0, get_upload_format(fmt), type, data);
allocated |= 1<<level;
if(auto_gen_mipmap && level==0)
{
generate_mipmap();
- allocated |= (1<<get_n_levels())-1;
+ allocated |= (1<<levels)-1;
}
}
generate_mipmap();
}
-void Texture1D::image(const Graphics::Image &img, bool srgb)
+void Texture1D::image(const Graphics::Image &img, unsigned lv, bool srgb)
{
if(img.get_height()!=1)
throw incompatible_data("Texture1D::image");
PixelFormat fmt = pixelformat_from_graphics(img.get_format());
if(width==0)
{
- unsigned l = (is_mipmapped(min_filter) ? mipmap_levels ? mipmap_levels : 0 : 1);
+ unsigned l = (is_mipmapped(min_filter) ? lv : 1);
storage(storage_pixelformat_from_graphics(img.get_format(), srgb), w, l);
}
else if(w!=width)
void allocate(unsigned);
void image(unsigned, PixelFormat, DataType, const void *);
void sub_image(unsigned, int, unsigned, PixelFormat, DataType, const void *);
- virtual void image(const Graphics::Image &, bool = false);
+ virtual void image(const Graphics::Image &, unsigned, bool = false);
+ using Texture::image;
unsigned get_width() const { return width; }
private:
return sub_image(level, 0, 0, w, h, fmt, type, data);
BindRestore _bind(this);
+
+ if(!allocated)
+ glTexParameteri(target, GL_TEXTURE_MAX_LEVEL, levels-1);
glTexImage2D(target, level, ifmt, w, h, 0, get_upload_format(fmt), type, data);
allocated |= 1<<level;
if(auto_gen_mipmap && level==0)
{
generate_mipmap();
- allocated |= (1<<get_n_levels())-1;
+ allocated |= (1<<levels)-1;
}
}
generate_mipmap();
}
-void Texture2D::image(const Graphics::Image &img, bool srgb)
+void Texture2D::image(const Graphics::Image &img, unsigned lv, bool srgb)
{
- image(img, srgb, false);
+ image(img, lv, srgb, false);
}
-void Texture2D::image(const Graphics::Image &img, bool srgb, bool from_buffer)
+void Texture2D::image(const Graphics::Image &img, unsigned lv, bool srgb, bool from_buffer)
{
unsigned w = img.get_width();
unsigned h = img.get_height();
PixelFormat fmt = pixelformat_from_graphics(img.get_format());
if(width==0)
{
- unsigned l = (is_mipmapped(min_filter) ? mipmap_levels ? mipmap_levels : 0 : 1);
+ unsigned l = (is_mipmapped(min_filter) ? lv : 1);
storage(storage_pixelformat_from_graphics(img.get_format(), srgb), w, h, l);
}
- else if(w!=width || h!=height)
+ else if(w!=width || h!=height || (lv && lv!=levels))
throw incompatible_data("Texture2D::image");
PixelStore pstore = PixelStore::from_image(img);
else
glGenTextures(1, &texture.id);
}
- texture.image(image, srgb_conversion, true);
+ texture.image(image, 0, srgb_conversion, true);
}
++phase;
If srgb is true and storage is determined by this call, then an sRGB pixel
format will be used. */
- virtual void image(const Graphics::Image &, bool srgb = false);
+ virtual void image(const Graphics::Image &, unsigned lv, bool srgb = false);
+
+ using Texture::image;
private:
- void image(const Graphics::Image &, bool, bool);
+ void image(const Graphics::Image &, unsigned, bool, bool);
public:
unsigned get_width() const { return width; }
return sub_image(level, 0, 0, 0, w, h, d, fmt, type, data);
BindRestore _bind(this);
+
+ if(!allocated)
+ glTexParameteri(target, GL_TEXTURE_MAX_LEVEL, levels-1);
glTexImage3D(target, level, ifmt, width, height, depth, 0, get_upload_format(fmt), type, data);
allocated |= 1<<level;
if(auto_gen_mipmap && level==0)
{
generate_mipmap();
- allocated |= (1<<get_n_levels())-1;
+ allocated |= (1<<levels)-1;
}
}
image(0, fmt, UNSIGNED_BYTE, img.get_data());
}
-void Texture3D::image(const Graphics::Image &img, bool srgb)
+void Texture3D::image(const Graphics::Image &img, unsigned lv, bool srgb)
{
unsigned w = img.get_width();
unsigned h = img.get_height();
PixelFormat fmt = pixelformat_from_graphics(img.get_format());
if(width==0)
{
- unsigned l = (is_mipmapped(min_filter) ? mipmap_levels ? mipmap_levels : 0 : 1);
+ unsigned l = (is_mipmapped(min_filter) ? lv : 1);
storage(storage_pixelformat_from_graphics(img.get_format(), srgb), w, h, d, l);
}
else if(w!=width || h!=height || d!=depth)
If srgb is true and storage is determined by this call, then an sRGB pixel
format will be used. */
- virtual void image(const Graphics::Image &, bool = false);
+ virtual void image(const Graphics::Image &, unsigned, bool = false);
+
+ using Texture::image;
unsigned get_width() const { return width; }
unsigned get_height() const { return height; }
return sub_image(face, level, 0, 0, s, s, fmt, type, data);
BindRestore _bind(this);
+
+ if(!allocated)
+ glTexParameteri(target, GL_TEXTURE_MAX_LEVEL, levels-1);
glTexImage2D(face, level, ifmt, s, s, 0, get_upload_format(fmt), type, data);
// XXX Allocation should be tracked per-face, but we'll run out of bits
{
// TODO Only do this once all faces are created
generate_mipmap();
- allocated |= (1<<get_n_levels())-1;
+ allocated |= (1<<levels)-1;
}
}
image(face, 0, fmt, UNSIGNED_BYTE, img.get_data());
}
-void TextureCube::image(const Graphics::Image &img, bool srgb)
+void TextureCube::image(const Graphics::Image &img, unsigned lv, bool srgb)
{
unsigned w = img.get_width();
unsigned h = img.get_height();
PixelFormat fmt = pixelformat_from_graphics(img.get_format());
if(size==0)
{
- unsigned l = (is_mipmapped(min_filter) ? mipmap_levels ? mipmap_levels : 0 : 1);
+ unsigned l = (is_mipmapped(min_filter) ? lv : 1);
storage(storage_pixelformat_from_graphics(img.get_format(), srgb), w, l);
}
else if(w!=size || h!=size)
void image(TextureCubeFace, const Graphics::Image &, bool = false);
- virtual void image(const Graphics::Image &, bool = false);
+ virtual void image(const Graphics::Image &, unsigned, bool = false);
+ using Texture::image;
unsigned get_size() const { return size; }
private: