|
- //
- // Lol Engine
- //
- // Copyright © 2010—2017 Sam Hocevar <sam@hocevar.net>
- //
- // Lol Engine is free software. It comes without any warranty, to
- // the extent permitted by applicable law. You can redistribute it
- // and/or modify it under the terms of the Do What the Fuck You Want
- // to Public License, Version 2, as published by the WTFPL Task Force.
- // See http://www.wtfpl.net/ for more details.
- //
-
- #include <lol/engine-internal.h>
-
- #include "lolgl.h"
-
- // FIXME: fine-tune this define
- #if defined LOL_USE_GLEW || defined HAVE_GL_2X || defined HAVE_GLES_2X
-
- namespace lol
- {
-
- //
- // The TextureData class
- // ---------------------
- //
-
- class TextureData
- {
- friend class Texture;
-
- ivec2 m_size;
- PixelFormat m_format;
-
- GLuint m_texture;
- GLint m_internal_format;
- GLenum m_gl_format, m_gl_type;
- int m_bytes_per_elem;
- };
-
- //
- // The Texture class
- // -----------------
- //
-
- #define GET_CLAMPED(array, index) \
- array[std::max(0, std::min((int)(index), \
- (int)sizeof(array) / (int)sizeof(*array)))]
-
- Texture::Texture(ivec2 size, PixelFormat format)
- : m_data(new TextureData)
- {
- m_data->m_size = size;
- m_data->m_format = format;
-
- static struct
- {
- GLint internal_format;
- GLenum format, type;
- int bytes;
- }
- const gl_formats[] =
- {
- { 0, 0, 0, 0 }, /* Unknown */
-
- /* FIXME: this is all mixed up for the RGBA/ARGB combinations */
- #if defined __native_client__ || defined HAVE_GLES_2X
- { GL_LUMINANCE, GL_LUMINANCE, GL_UNSIGNED_BYTE, 1 },
- { GL_RGB, GL_RGB, GL_UNSIGNED_BYTE, 3 },
- { GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, 4 },
- /* FIXME: if GL_RGBA is not available, we should advertise
- * this format as "not available" on this platform. */
- #else
- { GL_R8, GL_RED, GL_UNSIGNED_BYTE, 1 }, /* A8 */
- { GL_RGB8, GL_RGB, GL_UNSIGNED_BYTE, 3 }, /* RGB_8 */
- /* Seems efficient for little endian textures */
- { GL_RGBA8, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, 4 }, /* ARGB_8 */
- #endif
- { 0, 0, 0, 0 }, /* Y_F32 */
- { 0, 0, 0, 0 }, /* RGB_F32 */
- { 0, 0, 0, 0 }, /* RGBA_F32 */
- };
-
- m_data->m_internal_format = GET_CLAMPED(gl_formats, format).internal_format;
- m_data->m_gl_format = GET_CLAMPED(gl_formats, format).format;
- m_data->m_gl_type = GET_CLAMPED(gl_formats, format).type;
- m_data->m_bytes_per_elem = GET_CLAMPED(gl_formats, format).bytes;
-
- glGenTextures(1, &m_data->m_texture);
- glBindTexture(GL_TEXTURE_2D, m_data->m_texture);
-
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
- }
-
- TextureUniform Texture::GetTextureUniform() const
- {
- TextureUniform ret;
- ret.m_flags = m_data->m_texture;
- return ret;
- }
-
- void Texture::Bind()
- {
- #if !defined HAVE_GLES_2X
- glEnable(GL_TEXTURE_2D);
- #endif
- glBindTexture(GL_TEXTURE_2D, m_data->m_texture);
- }
-
- void Texture::SetData(void *data)
- {
- glTexImage2D(GL_TEXTURE_2D, 0, m_data->m_internal_format,
- m_data->m_size.x, m_data->m_size.y, 0,
- m_data->m_gl_format, m_data->m_gl_type, data);
- }
-
- void Texture::SetSubData(ivec2 origin, ivec2 size, void *data)
- {
- glTexSubImage2D(GL_TEXTURE_2D, 0, origin.x, origin.y, size.x, size.y,
- m_data->m_gl_format, m_data->m_gl_type, data);
- }
-
- void Texture::SetMagFiltering(TextureMagFilter filter)
- {
- glBindTexture(GL_TEXTURE_2D, m_data->m_texture);
- GLenum gl_filter;
- switch (filter)
- {
- case TextureMagFilter::LINEAR_TEXEL:
- gl_filter = GL_LINEAR;
- break;
- case TextureMagFilter::NEAREST_TEXEL:
- default:
- gl_filter = GL_NEAREST;
- break;
- }
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_filter);
- }
-
- void Texture::SetMinFiltering(TextureMinFilter filter)
- {
- glBindTexture(GL_TEXTURE_2D, m_data->m_texture);
- GLenum gl_filter;
- switch (filter)
- {
- case TextureMinFilter::LINEAR_TEXEL_NO_MIPMAP:
- gl_filter = GL_LINEAR;
- break;
- case TextureMinFilter::NEAREST_TEXEL_NEAREST_MIPMAP:
- gl_filter = GL_NEAREST_MIPMAP_NEAREST;
- break;
- case TextureMinFilter::NEAREST_TEXEL_LINEAR_MIPMAP:
- gl_filter = GL_NEAREST_MIPMAP_LINEAR;
- break;
- case TextureMinFilter::LINEAR_TEXEL_NEAREST_MIPMAP:
- gl_filter = GL_LINEAR_MIPMAP_NEAREST;
- break;
- case TextureMinFilter::LINEAR_TEXEL_LINEAR_MIPMAP:
- gl_filter = GL_LINEAR_MIPMAP_LINEAR;
- break;
- case TextureMinFilter::NEAREST_TEXEL_NO_MIPMAP:
- default:
- gl_filter = GL_NEAREST;
- break;
- }
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl_filter);
- }
-
- void Texture::GenerateMipmaps()
- {
- glBindTexture(GL_TEXTURE_2D, m_data->m_texture);
- glGenerateMipmap(GL_TEXTURE_2D);
- }
-
- Texture::~Texture()
- {
- glDeleteTextures(1, &m_data->m_texture);
- delete m_data;
- }
-
- } /* namespace lol */
-
- #endif
|