diff --git a/src/gpu/texture.cpp b/src/gpu/texture.cpp index c4d56d5a..77c2275b 100644 --- a/src/gpu/texture.cpp +++ b/src/gpu/texture.cpp @@ -53,6 +53,7 @@ class TextureData GLint m_internal_format; GLenum m_gl_format, m_gl_type; #endif + int m_bytes_per_elem; }; // @@ -71,28 +72,41 @@ Texture::Texture(ivec2 size, PixelFormat format) m_data->m_format = format; #if defined USE_D3D9 || defined _XBOX - static D3DFORMAT const d3d_formats[] = + static struct + { + D3DFORMAT format; + int bytes; + } + const d3d_formats[] = { /* Unknown */ - D3DFMT_UNKNOWN, + { D3DFMT_UNKNOWN, 0 }, /* R8G8B8 */ # if defined USE_D3D9 - D3DFMT_R8G8B8, + { D3DFMT_R8G8B8, 3 }, # else - D3DFMT_UNKNOWN, + { D3DFMT_UNKNOWN, 0 }, # endif /* A8R8G8B8 */ # if defined USE_D3D9 - D3DFMT_A8R8G8B8, + { D3DFMT_A8R8G8B8, 4 }, # else /* By default the X360 will swizzle the texture. Ask for linear. */ - D3DFMT_LIN_A8R8G8B8, + { D3DFMT_LIN_A8R8G8B8, 4 }, +# endif + + /* Y8 */ +# if defined USE_D3D9 + { D3DFMT_L8, 1 }, +# else + /* By default the X360 will swizzle the texture. Ask for linear. */ + { D3DFMT_LIN_L8, 1 }, # endif }; - D3DFORMAT d3d_format = GET_CLAMPED(d3d_formats, format); + D3DFORMAT d3d_format = GET_CLAMPED(d3d_formats, format).format; # if defined USE_D3D9 int d3d_usage = D3DUSAGE_DYNAMIC; # else @@ -102,46 +116,41 @@ Texture::Texture(ivec2 size, PixelFormat format) g_d3ddevice->CreateTexture(m_data->m_size.x, m_data->m_size.y, 1, d3d_usage, d3d_format, D3DPOOL_DEFAULT, &m_data->m_texture, NULL); + m_data->m_bytes_per_elem = GET_CLAMPED(d3d_formats, format).bytes; #else static struct { GLint internal_format; GLenum format, type; + int bytes; } const gl_formats[] = { - /* Unknown */ - { 0, 0, 0 }, - - /* R8G8B8 */ - { GL_RGB, GL_RGB, GL_UNSIGNED_BYTE }, - - /* A8R8G8B8 */ -#if __CELLOS_LV2__ - { GL_ARGB_SCE, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV }, -#elif defined __native_client__ || defined HAVE_GLES_2X - { GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE }, -#else - /* Seems efficient for little endian textures */ - { GL_RGBA, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV }, -#endif + { 0, 0, 0, 0 }, /* Unknown */ + { GL_RGB8, GL_RGB, GL_UNSIGNED_BYTE, 3 }, /* RGB_8 */ - /* A8B8G8R8 */ #if __CELLOS_LV2__ - { GL_ARGB_SCE, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV }, + { GL_ARGB_SCE, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8, 4 }, + { GL_ARGB_SCE, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8, 4 }, + { GL_LUMINANCE8, GL_LUMINANCE, GL_UNSIGNED_BYTE, 1 }, #elif defined __native_client__ || defined HAVE_GLES_2X + { GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE, 4 }, /* FIXME: if GL_RGBA is not available, we should advertise * this format as "not available" on this platform. */ - { GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE }, + { GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE, 4 }, + { GL_R8, GL_R8, GL_UNSIGNED_BYTE, 1 }, #else /* Seems efficient for little endian textures */ - { GL_RGBA, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV }, + { GL_RGBA8, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, 4 }, /* ARGB_8 */ + { GL_RGBA8, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, 4 }, /* ABGR_8 */ + { GL_R8, GL_RED, GL_UNSIGNED_BYTE, 1 }, /* A8 */ #endif }; 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); @@ -207,12 +216,12 @@ void Texture::SetSubData(ivec2 origin, ivec2 size, void *data) D3DLOCKED_RECT rect; m_data->m_texture->LockRect(0, &rect, NULL, 0); + int stride = size.x * m_data->m_bytes_per_elem; for (int j = 0; j < size.y; j++) { uint8_t *dst = (uint8_t *)rect.pBits + (origin.y + j) * rect.Pitch; - /* FIXME: the source or destination pitch isn't necessarily 4! */ - uint8_t *src = (uint8_t *)data + j * size.x * 4; - memcpy(dst, src, size.x * 4); + uint8_t *src = (uint8_t *)data + j * stride; + memcpy(dst, src, stride); } m_data->m_texture->UnlockRect(0); diff --git a/src/gpu/texture.h b/src/gpu/texture.h index 0339d23b..1846f509 100644 --- a/src/gpu/texture.h +++ b/src/gpu/texture.h @@ -25,9 +25,10 @@ struct PixelFormat enum Value { Unknown = 0, - R8G8B8, - A8R8G8B8, - A8B8G8R8, + RGB_8, + ARGB_8, + ABGR_8, + Y_8, } m_value; diff --git a/src/tileset.cpp b/src/tileset.cpp index 24ba8ef3..b385ddee 100644 --- a/src/tileset.cpp +++ b/src/tileset.cpp @@ -123,12 +123,12 @@ void TileSet::TickDraw(float seconds) switch (data->img->GetFormat()) { case Image::FORMAT_RGB: - format = PixelFormat::R8G8B8; + format = PixelFormat::RGB_8; planes = 3; break; case Image::FORMAT_RGBA: default: - format = PixelFormat::A8R8G8B8; + format = PixelFormat::ARGB_8; planes = 4; break; } diff --git a/tutorial/04_texture.cpp b/tutorial/04_texture.cpp index b670c4ea..e0a1b0be 100644 --- a/tutorial/04_texture.cpp +++ b/tutorial/04_texture.cpp @@ -36,7 +36,7 @@ public: m_vertices << vec2( 1.0, -1.0); m_vertices << vec2( 1.0, 1.0); - m_heightmap = new uint8_t[4 * TEXTURE_WIDTH * 1]; + m_heightmap = new uint8_t[TEXTURE_WIDTH * 1]; } virtual ~TextureDemo() @@ -50,16 +50,16 @@ public: /* Generate a new heightmap at the beginning */ if (m_frames == 0) - memset(m_heightmap, 255, 4 * TEXTURE_WIDTH); + memset(m_heightmap, 255, TEXTURE_WIDTH); /* Scroll left */ for (int i = 0; i < TEXTURE_WIDTH - 1; i++) - m_heightmap[4 * i] = m_heightmap[4 * i + 4]; + m_heightmap[i] = m_heightmap[i + 1]; - int height = m_heightmap[4 * (TEXTURE_WIDTH - 1)]; + int height = m_heightmap[TEXTURE_WIDTH - 1]; height = (height + 127 + 40 * lol::sin(m_frames * 0.03) + rand() % 97 - 38) / 2; height = std::max(15, std::min(height, 240)); - m_heightmap[4 * (TEXTURE_WIDTH - 1)] = height; + m_heightmap[TEXTURE_WIDTH - 1] = height; /* Update frame counter */ ++m_frames; @@ -72,7 +72,7 @@ public: /* Initialise GPU data */ if (!m_ready) { - m_texture = new Texture(ivec2(TEXTURE_WIDTH, 1), PixelFormat::A8R8G8B8); + m_texture = new Texture(ivec2(TEXTURE_WIDTH, 1), PixelFormat::Y_8); m_shader = Shader::Create(LOLFX_RESOURCE_NAME(04_texture)); m_coord = m_shader->GetAttribLocation("in_Position", VertexUsage::Position, 0); @@ -117,7 +117,7 @@ int main(int argc, char **argv) { System::Init(argc, argv); - Application app("Tutorial 4: Texture", ivec2(640, 480), 60.0f); + Application app("Tutorial 4: Texture", ivec2(1280, 720), 60.0f); new TextureDemo(); diff --git a/tutorial/11_fractal.cpp b/tutorial/11_fractal.cpp index c9a4b7c2..86fcd082 100644 --- a/tutorial/11_fractal.cpp +++ b/tutorial/11_fractal.cpp @@ -442,7 +442,7 @@ public: /* Create a texture of half the width and twice the height * so that we can upload four different subimages each frame. */ m_texture = new Texture(ivec2(m_size.x / 2, m_size.y * 2), - PixelFormat::A8B8G8R8); + PixelFormat::ABGR_8); /* Ensure the texture data is complete at least once, otherwise * uploading subimages will not work. */