|
|
|
|
@@ -19,6 +19,34 @@
|
|
|
|
|
#ifndef FENNEC_RENDERERS_OPENGL_LIB_TEXTURE_H
|
|
|
|
|
#define FENNEC_RENDERERS_OPENGL_LIB_TEXTURE_H
|
|
|
|
|
|
|
|
|
|
/* Because our implementation targets minimum OpenGL ES 3.2,
|
|
|
|
|
* we are guaranteed to have the following relevant extensions (Starting from OpenGL ES 3.0):
|
|
|
|
|
*
|
|
|
|
|
* OES_texture_compression_astc
|
|
|
|
|
* EXT_texture_border_clamp
|
|
|
|
|
* OES_EGL_image_external_essl3
|
|
|
|
|
* ARB_shader_image_load_store
|
|
|
|
|
* ARB_stencil_texturing
|
|
|
|
|
* ARG_shader_image_size
|
|
|
|
|
* ARB_texture_multisample
|
|
|
|
|
* ARB_texture_storage_multisample
|
|
|
|
|
* ARB_sample_locations
|
|
|
|
|
* OES_texture_view
|
|
|
|
|
* NV_image_formats
|
|
|
|
|
* EXT_render_snorm
|
|
|
|
|
* EXT_render_norm16
|
|
|
|
|
* EXT_color_buffer_float
|
|
|
|
|
* OES_copy_image
|
|
|
|
|
* OES_shader_image_atomic
|
|
|
|
|
* OES_texture_border_clamp
|
|
|
|
|
* OES_texture_buffer
|
|
|
|
|
* OES_texture_cube_map_array
|
|
|
|
|
* OES_texture_stencil8
|
|
|
|
|
* OES_texture_storage_multisample_2d_array
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#include <fennec/math/common.h>
|
|
|
|
|
#include <fennec/renderers/opengl/lib/fwd.h>
|
|
|
|
|
#include <fennec/renderers/opengl/lib/enum.h>
|
|
|
|
|
|
|
|
|
|
@@ -28,35 +56,229 @@ namespace fennec
|
|
|
|
|
namespace gl
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
template<GLint FormatV, GLboolean ImmutableV> using texture1d = texture<TEX_1D, FormatV, ImmutableV>;
|
|
|
|
|
template<GLint FormatV, GLboolean ImmutableV> using texture1dv = texture<TEX_1D_V, FormatV, ImmutableV>;
|
|
|
|
|
template<GLint FormatV, GLboolean ImmutableV> using texture2d = texture<TEX_2D, FormatV, ImmutableV>;
|
|
|
|
|
template<GLint FormatV, GLboolean ImmutableV> using texture2dv = texture<TEX_2D_V, FormatV, ImmutableV>;
|
|
|
|
|
template<GLint FormatV, GLboolean ImmutableV> using texture_rect = texture<TEX_RECT, FormatV, ImmutableV>;
|
|
|
|
|
template<GLint FormatV, GLboolean ImmutableV> using texture2d_ms = texture<TEX_2D_MS, FormatV, ImmutableV>;
|
|
|
|
|
template<GLint FormatV, GLboolean ImmutableV> using texture2dv_ms = texture<TEX_2D_MS_V, FormatV, ImmutableV>;
|
|
|
|
|
template<GLint FormatV, GLboolean ImmutableV> using cubemap = texture<TEX_CUBEMAP, FormatV, ImmutableV>;
|
|
|
|
|
template<GLint FormatV, GLboolean ImmutableV> using cubemapv = texture<TEX_CUBEMAP_V, FormatV, ImmutableV>;
|
|
|
|
|
template<GLint FormatV, GLboolean ImmutableV> using texture3d = texture<TEX_3D, FormatV, ImmutableV>;
|
|
|
|
|
template<GLint FormatV, GLboolean ImmutableV> using buffer_texture = texture<TEX_BUFFER, FormatV, ImmutableV>;
|
|
|
|
|
|
|
|
|
|
///
|
|
|
|
|
/// \brief Wrapper for OpenGL Texture Objects
|
|
|
|
|
/// \tparam TypeV The type of the texture
|
|
|
|
|
/// \tparam FormatV The internal format of the texels
|
|
|
|
|
/// \tparam ImmutableV Whether the texture is immutable, i.e. cannot be resized after creation
|
|
|
|
|
///
|
|
|
|
|
/// \details Immutable textures require EXT_texture_storage or ARB_texture_storage
|
|
|
|
|
/// Immutable multisample textures require ARB_texture_storage_multisample of OES_texture_storage_multisample_2d_array
|
|
|
|
|
template<GLenum TypeV, GLint FormatV, GLboolean ImmutableV>
|
|
|
|
|
class texture {
|
|
|
|
|
public:
|
|
|
|
|
static constexpr GLenum type = TypeV;
|
|
|
|
|
static constexpr GLint format = FormatV;
|
|
|
|
|
static constexpr bool immutable = ImmutableV;
|
|
|
|
|
static constexpr bool sampled = TypeV == TEX_2D_MS or TypeV == TEX_2D_MS_V;
|
|
|
|
|
static constexpr bool is_rect = TypeV == TEX_RECT;
|
|
|
|
|
static constexpr bool is_buffered = TypeV == TEX_BUFFER;
|
|
|
|
|
static constexpr bool is_2d = sampled or is_rect or TypeV == TEX_2D or TypeV == TEX_2D_V;
|
|
|
|
|
static constexpr bool is_1d = TypeV == TEX_1D or TypeV == TEX_1D_V;
|
|
|
|
|
static constexpr bool is_array = TypeV == TEX_1D_V or TypeV == TEX_2D_V or TypeV == TEX_2D_MS_V or TypeV == TEX_CUBEMAP_V;
|
|
|
|
|
static constexpr bool has_mipmaps = not(sampled or is_rect or is_buffered);
|
|
|
|
|
|
|
|
|
|
texture(GLsizei width, GLint mips, void* data) requires is_1d and not is_array
|
|
|
|
|
// Constants ===========================================================================================================
|
|
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
static constexpr GLenum type = TypeV;
|
|
|
|
|
static constexpr GLint format = FormatV;
|
|
|
|
|
static constexpr GLboolean immutable = ImmutableV;
|
|
|
|
|
static constexpr GLboolean is_rect = type == TEX_RECT;
|
|
|
|
|
static constexpr GLboolean is_buffered = type == TEX_BUFFER;
|
|
|
|
|
static constexpr GLboolean sampled = type == TEX_2D_MS or type == TEX_2D_MS_V;
|
|
|
|
|
static constexpr GLboolean cubemap = type == TEX_CUBEMAP or type == TEX_CUBEMAP_V;
|
|
|
|
|
static constexpr GLboolean is_1d = type == TEX_1D or type == TEX_1D_V;
|
|
|
|
|
static constexpr GLboolean is_2d = sampled or is_rect or type == TEX_2D or type == TEX_2D_V or cubemap;
|
|
|
|
|
static constexpr GLboolean is_array = TypeV == TEX_1D_V or TypeV == TEX_2D_V or type == TEX_2D_MS_V or type == TEX_CUBEMAP_V;
|
|
|
|
|
static constexpr GLboolean is_3d = TypeV == TEX_3D;
|
|
|
|
|
static constexpr GLboolean has_mipmaps = not(sampled or is_rect or is_buffered);
|
|
|
|
|
|
|
|
|
|
static constexpr GLboolean use_1d = is_1d and not is_array;
|
|
|
|
|
static constexpr GLboolean use_2d = (is_2d and not is_array) or (is_1d and is_array) and not sampled;
|
|
|
|
|
static constexpr GLboolean use_3d = is_3d or (is_2d and is_array) and not sampled and not cubemap;
|
|
|
|
|
|
|
|
|
|
static constexpr GLint cubemap_faces = 6;
|
|
|
|
|
static constexpr GLenum base_cubemap_face = GL_TEXTURE_CUBE_MAP_POSITIVE_X;
|
|
|
|
|
|
|
|
|
|
static constexpr GLboolean compressed = type == RGB_DXT1 or type == RGBA_DXT1 or type == RGBA_DXT3 or type == RGBA_DXT5
|
|
|
|
|
or type == SRGB_DXT1 or type == SRGBA_DXT1 or type == SRGBA_DXT3 or type == SRGBA_DXT5;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Constructors ========================================================================================================
|
|
|
|
|
|
|
|
|
|
///
|
|
|
|
|
/// \brief 1D Texture Constructor
|
|
|
|
|
/// \param width The width of the texture
|
|
|
|
|
/// \param mips The number of mipmap levels
|
|
|
|
|
/// \param data A pointer to a buffer containing pixel values, used as an offset if a PIXEL_UNPACK_BUFFER is bound.
|
|
|
|
|
/// \param component The type of each component
|
|
|
|
|
/// \param layout The layout of components in each pixel
|
|
|
|
|
texture(GLsizei width, GLint mips,
|
|
|
|
|
void* data = nullptr, GLenum component = BYTE, GLenum layout = R, GLsizei size = 0) requires use_1d
|
|
|
|
|
: _handle(NULL)
|
|
|
|
|
, _width(width), _height(1), _depth(1)
|
|
|
|
|
, _samples(1)
|
|
|
|
|
, _mips(mips) {
|
|
|
|
|
, _samples(1), _mips(mips) {
|
|
|
|
|
glGenTextures(1, &_handle);
|
|
|
|
|
start();
|
|
|
|
|
if constexpr(immutable) {
|
|
|
|
|
glTexStorage1D(type, _mips, format, _width);
|
|
|
|
|
glTexSubImage1D(type, 0, 0, _width, layout, component, data);
|
|
|
|
|
} else if constexpr(compressed) {
|
|
|
|
|
glCompressedTexImage1D(type, 0, format, _width, 0, size, data);
|
|
|
|
|
} else {
|
|
|
|
|
glTexImage1D(type, 0, format, _width, 0, layout, component, data);
|
|
|
|
|
}
|
|
|
|
|
genmips();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
texture(GLsizei width, GLsizei height, GLint mips) requires is_2d and not (is_array or sampled) or (is_1d and is_array)
|
|
|
|
|
///
|
|
|
|
|
/// \brief 2D Texture Constructor
|
|
|
|
|
/// \param width The width of the texture
|
|
|
|
|
/// \param height The height of the texture, or number of layers for arrays
|
|
|
|
|
/// \param mips The number of mipmap levels
|
|
|
|
|
/// \param data A pointer to a buffer containing pixel values, used as an offset if a PIXEL_UNPACK_BUFFER is bound.
|
|
|
|
|
/// \param component The type of each component
|
|
|
|
|
/// \param layout The layout of components in each pixel
|
|
|
|
|
texture(GLsizei width, GLsizei height, GLint mips,
|
|
|
|
|
void* data = nullptr, GLenum component = BYTE, GLenum layout = R, GLsizei size = 0) requires use_2d and not cubemap
|
|
|
|
|
: _handle(NULL)
|
|
|
|
|
, _width(width), _height(height), _depth(1)
|
|
|
|
|
, _samples(1)
|
|
|
|
|
, _mips(mips) {
|
|
|
|
|
, _samples(1), _mips(mips) {
|
|
|
|
|
glGenTextures(1, &_handle);
|
|
|
|
|
start();
|
|
|
|
|
if constexpr(immutable) {
|
|
|
|
|
glTexStorage2D(type, _mips, format, _width, _height);
|
|
|
|
|
glTexSubImage2D(type, 0, 0, 0, _width, _height, layout, component, data);
|
|
|
|
|
} else if constexpr(compressed) {
|
|
|
|
|
glCompressedTexImage2D(type, 0, format, _width, _height, 0, size, data);
|
|
|
|
|
} else {
|
|
|
|
|
glTexImage2D(type, 0, format, _width, _height, 0, layout, component, data);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
///
|
|
|
|
|
/// \brief 2D Texture Constructor
|
|
|
|
|
/// \param width The width of the texture
|
|
|
|
|
/// \param height The height of the texture
|
|
|
|
|
/// \param depth The depth of the texture, or number of layers for arrays
|
|
|
|
|
/// \param mips The number of mipmap levels
|
|
|
|
|
/// \param data A pointer to a buffer containing pixel values, used as an offset if a PIXEL_UNPACK_BUFFER is bound.
|
|
|
|
|
/// \param component The type of each component
|
|
|
|
|
/// \param layout The layout of components in each pixel
|
|
|
|
|
texture(GLsizei width, GLsizei height, GLsizei depth, GLsizei mips,
|
|
|
|
|
void* data = nullptr, GLenum component = BYTE, GLenum layout = R, GLsizei size = 0) requires use_3d and not cubemap
|
|
|
|
|
: _handle(NULL)
|
|
|
|
|
, _width(width), _height(height), _depth(depth)
|
|
|
|
|
, _samples(1), _mips(mips) {
|
|
|
|
|
glGenTextures(1, &_handle);
|
|
|
|
|
start();
|
|
|
|
|
if constexpr(immutable) {
|
|
|
|
|
glTexStorage3D(type, _mips, format, _width, _height, _depth);
|
|
|
|
|
glTexSubImage3D(type, 0, 0, 0, 0, _width, _height, _depth, layout, component, data);
|
|
|
|
|
} else if constexpr(compressed) {
|
|
|
|
|
glCompressedTexImage3D(type, 0, format, _width, _height, _depth, 0, size, data);
|
|
|
|
|
} else {
|
|
|
|
|
glTexImage3D(type, 0, format, _width, _height, _depth, 0, layout, component, data);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
///
|
|
|
|
|
/// \brief 2D Multisample Texture Constructor
|
|
|
|
|
/// \param width The width of the texture
|
|
|
|
|
/// \param height The height of the texture
|
|
|
|
|
/// \param samples The number of samples per pixel
|
|
|
|
|
/// \param fixed When true, a fixed set of sample locations is used
|
|
|
|
|
texture(GLsizei width, GLsizei height, GLsizei samples, GLboolean fixed = true) requires sampled and not is_array
|
|
|
|
|
: _handle(NULL)
|
|
|
|
|
, _width(width), _height(height), _depth(1)
|
|
|
|
|
, _samples(samples), _mips(0) {
|
|
|
|
|
glGenTextures(1, &_handle);
|
|
|
|
|
start();
|
|
|
|
|
if constexpr(immutable) {
|
|
|
|
|
glTexStorage2DMultisample(type, _samples, format, _width, _height, fixed);
|
|
|
|
|
} else {
|
|
|
|
|
glTexImage2DMultisample(type, _samples, format, _width, _height, fixed);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
///
|
|
|
|
|
/// \brief 2D Multisample Array Texture Constructor
|
|
|
|
|
/// \param width The width of the texture
|
|
|
|
|
/// \param height The height of the texture
|
|
|
|
|
/// \param depth The number of layers in the array
|
|
|
|
|
/// \param samples The number of samples per pixel
|
|
|
|
|
/// \param fixed When true, a fixed set of sample locations is used
|
|
|
|
|
texture(GLsizei width, GLsizei height, GLsizei depth, GLsizei samples, GLboolean fixed = true) requires sampled and is_array
|
|
|
|
|
: _handle(NULL)
|
|
|
|
|
, _width(width), _height(height), _depth(depth)
|
|
|
|
|
, _samples(samples), _mips(0) {
|
|
|
|
|
glGenTextures(1, &_handle);
|
|
|
|
|
start();
|
|
|
|
|
if constexpr(immutable) {
|
|
|
|
|
glTexStorage3DMultisample(type, _samples, format, _width, _height, _depth, fixed);
|
|
|
|
|
} else {
|
|
|
|
|
glTexImage3DMultisample(type, _samples, format, _width, _height, _depth, fixed);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
///
|
|
|
|
|
/// \brief Cubemap Constructor
|
|
|
|
|
/// \param size The size of each face texture
|
|
|
|
|
/// \param mips The number of mipmap layers
|
|
|
|
|
/// \param faces An array of pointers to textures containing pixel data for each face
|
|
|
|
|
/// \param component The component type of the data
|
|
|
|
|
/// \param layout The layout of the components in the pixel
|
|
|
|
|
texture(GLsizei size, GLsizei mips,
|
|
|
|
|
const void* faces[6], GLenum component = BYTE, GLenum layout = R, GLsizei size = 0) requires is_2d and cubemap
|
|
|
|
|
: _handle(NULL)
|
|
|
|
|
, _width(size), _height(size), _depth(1)
|
|
|
|
|
, _samples(1), _mips(mips) {
|
|
|
|
|
glGenTextures(1, &_handle);
|
|
|
|
|
start();
|
|
|
|
|
if constexpr(immutable) {
|
|
|
|
|
glTexStorage2D(type, _mips, format, _width, _height);
|
|
|
|
|
for (int i = 0; i < cubemap_faces; ++i) {
|
|
|
|
|
glTexSubImage2D(base_cubemap_face + i, 0, 0, 0, _width, _height, layout, component, faces[i]);
|
|
|
|
|
}
|
|
|
|
|
} else if constexpr(compressed) {
|
|
|
|
|
} else {
|
|
|
|
|
for (int i = 0; i < cubemap_faces; ++i) {
|
|
|
|
|
glTexImage2D(base_cubemap_face + i, 0, format, _width, _height, 0, layout, component, faces[i]);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
///
|
|
|
|
|
/// \brief Cubemap Array Constructor
|
|
|
|
|
/// \param size The size of each face texture
|
|
|
|
|
/// \param depth The number of layers in the array
|
|
|
|
|
/// \param mips The number of mipmap layers
|
|
|
|
|
/// \param data A pointer to a buffer containing image data
|
|
|
|
|
/// \param component The component type of the data
|
|
|
|
|
/// \param layout The layout of the components in the pixel
|
|
|
|
|
///
|
|
|
|
|
/// \details Requires OES_texture_cube_map_array
|
|
|
|
|
texture(GLsizei size, GLsizei depth, GLsizei mips,
|
|
|
|
|
const void* data, GLenum component = BYTE, GLenum layout = R, GLsizei size = 0) requires is_2d and cubemap
|
|
|
|
|
: _handle(NULL)
|
|
|
|
|
, _width(size), _height(size), _depth(depth)
|
|
|
|
|
, _samples(1), _mips(mips) {
|
|
|
|
|
glGenTextures(1, &_handle);
|
|
|
|
|
start();
|
|
|
|
|
if constexpr(immutable) {
|
|
|
|
|
glTexStorage3D(type, _mips, format, _width, _height, _depth * 6);
|
|
|
|
|
glTexSubImage3D(type, 0, 0, 0, 0, _width, _height, _depth * 6, layout, component, data);
|
|
|
|
|
} else if constexpr(compressed) {
|
|
|
|
|
} else {
|
|
|
|
|
glTexImage3D(type, 0, format, _width, _height, _depth * 6, 0, layout, component, data);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Basic Functions =====================================================================================================
|
|
|
|
|
|
|
|
|
|
void start() {
|
|
|
|
|
glBindTexture(type, _handle);
|
|
|
|
|
}
|
|
|
|
|
@@ -70,6 +292,10 @@ public:
|
|
|
|
|
start();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void genmips() {
|
|
|
|
|
glGenerateMipmap(type);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
GLuint _handle;
|
|
|
|
|
GLsizei _width;
|
|
|
|
|
@@ -83,4 +309,4 @@ private:
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#endif // FENNEC_RENDERERS_OPENGL_TEXTURE_H
|
|
|
|
|
#endif // FENNEC_RENDERERS_OPENGL_LIB_TEXTURE_H
|
|
|
|
|
|