From 82682ecf02febfce8c6f298028f93fdef132b1eb Mon Sep 17 00:00:00 2001 From: Alexis Maiquez Murcia Date: Tue, 2 Apr 2019 17:08:34 +0200 Subject: [PATCH] + Added LZ4 lib to the compilation process + Basic draft for the texture custom loader, only ARGB (partially) supported for now Signed-off-by: Alexis Maiquez Murcia --- CMakeLists.txt | 7 +- CMakeModules/FindLZ4.cmake | 41 ++++++ main.cpp | 5 + wallpaperengine/image.cpp | 14 +- wallpaperengine/irr/CImageLoaderTEX.cpp | 178 ++++++++++++++++++++++++ wallpaperengine/irr/CImageLoaderTEX.h | 51 +++++++ wallpaperengine/project.cpp | 3 +- wallpaperengine/texture.cpp | 5 +- 8 files changed, 287 insertions(+), 17 deletions(-) create mode 100644 CMakeModules/FindLZ4.cmake create mode 100644 wallpaperengine/irr/CImageLoaderTEX.cpp create mode 100644 wallpaperengine/irr/CImageLoaderTEX.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 2398726..9879ec4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -11,9 +11,10 @@ find_package(OpenGL REQUIRED) find_package(GLUT REQUIRED) find_package(ZLIB REQUIRED) find_package(Irrlicht REQUIRED) +find_package(LZ4 REQUIRED) -include_directories(${X11_INCLUDE_DIR} ${IRRLICHT_INCLUDE_DIR} .) +include_directories(${X11_INCLUDE_DIR} ${IRRLICHT_INCLUDE_DIR} ${LZ4_INCLUDE_DIR} .) -add_executable(wallengine main.cpp wallpaperengine/shaders/compiler.h wallpaperengine/shaders/compiler.cpp wallpaperengine/project.cpp wallpaperengine/project.h wallpaperengine/scene.cpp wallpaperengine/scene.h wallpaperengine/object.cpp wallpaperengine/object.h wallpaperengine/camera.cpp wallpaperengine/camera.h wallpaperengine/core.cpp wallpaperengine/core.h wallpaperengine/image.cpp wallpaperengine/image.h wallpaperengine/object3d.cpp wallpaperengine/object3d.h wallpaperengine/effect.cpp wallpaperengine/effect.h wallpaperengine/fs/fileResolver.cpp wallpaperengine/fs/fileResolver.h wallpaperengine/irrlicht.cpp wallpaperengine/irrlicht.h wallpaperengine/config.cpp wallpaperengine/config.h wallpaperengine/video/renderer.cpp wallpaperengine/video/renderer.h wallpaperengine/video/node.cpp wallpaperengine/video/node.h wallpaperengine/video/material.cpp wallpaperengine/video/material.h wallpaperengine/texture.cpp wallpaperengine/texture.h) +add_executable(wallengine main.cpp wallpaperengine/shaders/compiler.h wallpaperengine/shaders/compiler.cpp wallpaperengine/project.cpp wallpaperengine/project.h wallpaperengine/scene.cpp wallpaperengine/scene.h wallpaperengine/object.cpp wallpaperengine/object.h wallpaperengine/camera.cpp wallpaperengine/camera.h wallpaperengine/core.cpp wallpaperengine/core.h wallpaperengine/image.cpp wallpaperengine/image.h wallpaperengine/object3d.cpp wallpaperengine/object3d.h wallpaperengine/effect.cpp wallpaperengine/effect.h wallpaperengine/fs/fileResolver.cpp wallpaperengine/fs/fileResolver.h wallpaperengine/irrlicht.cpp wallpaperengine/irrlicht.h wallpaperengine/config.cpp wallpaperengine/config.h wallpaperengine/video/renderer.cpp wallpaperengine/video/renderer.h wallpaperengine/video/node.cpp wallpaperengine/video/node.h wallpaperengine/video/material.cpp wallpaperengine/video/material.h wallpaperengine/texture.cpp wallpaperengine/texture.h wallpaperengine/irr/CImageLoaderTEX.h wallpaperengine/irr/CImageLoaderTEX.cpp) -target_link_libraries(wallengine ${X11_LIBRARIES} ${X11_Xxf86vm_LIB} ${OPENGL_LIBRARIES} ${GLUT_LIBRARIES} ${ZLIB_LIBRARIES} ${IRRLICHT_LIBRARY}) \ No newline at end of file +target_link_libraries(wallengine ${X11_LIBRARIES} ${X11_Xxf86vm_LIB} ${OPENGL_LIBRARIES} ${GLUT_LIBRARIES} ${ZLIB_LIBRARIES} ${IRRLICHT_LIBRARY} ${LZ4_LIBRARY}) \ No newline at end of file diff --git a/CMakeModules/FindLZ4.cmake b/CMakeModules/FindLZ4.cmake new file mode 100644 index 0000000..04c1d31 --- /dev/null +++ b/CMakeModules/FindLZ4.cmake @@ -0,0 +1,41 @@ +# Finds liblz4. +# +# This module defines: +# LZ4_FOUND +# LZ4_INCLUDE_DIR +# LZ4_LIBRARY +# +# From https://github.com/facebook/hhvm/blob/master/CMake/FindLZ4.cmake +# + +find_path(LZ4_INCLUDE_DIR NAMES lz4.h) +find_library(LZ4_LIBRARY NAMES lz4) + +# We require LZ4_compress_default() which was added in v1.7.0 +if (LZ4_LIBRARY) + include(CheckCSourceRuns) + set(CMAKE_REQUIRED_INCLUDES ${LZ4_INCLUDE_DIR}) + set(CMAKE_REQUIRED_LIBRARIES ${LZ4_LIBRARY}) + check_c_source_runs(" +#include +int main() { + int good = (LZ4_VERSION_MAJOR > 1) || + ((LZ4_VERSION_MAJOR == 1) && (LZ4_VERSION_MINOR >= 7)); +return !good; +}" LZ4_GOOD_VERSION) + set(CMAKE_REQUIRED_INCLUDES) + set(CMAKE_REQUIRED_LIBRARIES) +endif() + +include(FindPackageHandleStandardArgs) +FIND_PACKAGE_HANDLE_STANDARD_ARGS( + LZ4 DEFAULT_MSG + LZ4_LIBRARY LZ4_INCLUDE_DIR LZ4_GOOD_VERSION) + +if (NOT LZ4_FOUND) + message(STATUS "Using third-party bundled LZ4") +else() + message(STATUS "Found LZ4: ${LZ4_LIBRARY}") +endif (NOT LZ4_FOUND) + +mark_as_advanced(LZ4_INCLUDE_DIR LZ4_LIBRARY) diff --git a/main.cpp b/main.cpp index 54f16b8..fc451c5 100644 --- a/main.cpp +++ b/main.cpp @@ -8,6 +8,7 @@ #include "wallpaperengine/shaders/compiler.h" #include "wallpaperengine/project.h" #include "wallpaperengine/irrlicht.h" +#include "wallpaperengine/irr/CImageLoaderTEX.h" int WinID = 0; irr::SIrrlichtCreationParameters _irr_params; @@ -125,6 +126,10 @@ int main (int argc, char* argv[]) // set our working directory wp::fs::resolver.changeWorkingDirectory (_wp_engine_folder); + + // register custom loader + wp::irrlicht::driver->addExternalImageLoader (new irr::video::CImageLoaderTex ()); + wp::project* wp_project = new wp::project (); if (wp_project->getScene ()->isOrthogonal() == true) diff --git a/wallpaperengine/image.cpp b/wallpaperengine/image.cpp index b39b5a2..1b1c850 100644 --- a/wallpaperengine/image.cpp +++ b/wallpaperengine/image.cpp @@ -65,19 +65,11 @@ namespace wp for (; texturesCur != texturesEnd; texturesCur ++) { // TODO: SUPPORT PROPER WALLPAPERENGINE FORMATS - irr::io::path texturePath = this->m_resolver.resolveOnWorkingDirectory ((*texturesCur)); + std::string name = (*texturesCur); + name += ".tex"; + irr::io::path texturePath = this->m_resolver.resolveOnWorkingDirectory (name); std::string basename = (*texturesCur); - // TRY NORMAL EXTENSIONS FOR NOW... - if (texturePath == "") - { - texturePath = this->m_resolver.resolveOnWorkingDirectory (basename + ".png"); - } - if (texturePath == "") - { - texturePath = this->m_resolver.resolveOnWorkingDirectory (basename + ".jpg"); - } - this->m_textures.push_back (new wp::texture (texturePath)); } } diff --git a/wallpaperengine/irr/CImageLoaderTEX.cpp b/wallpaperengine/irr/CImageLoaderTEX.cpp new file mode 100644 index 0000000..259b1dd --- /dev/null +++ b/wallpaperengine/irr/CImageLoaderTEX.cpp @@ -0,0 +1,178 @@ +// Copyright (C) 2002-2012 Nikolaus Gebhardt +// This file is part of the "Irrlicht Engine". +// For conditions of distribution and use, see copyright notice in irrlicht.h + +#include "CImageLoaderTEX.h" + +#include +#include +#include +#include + +namespace irr { + namespace video { + + //! returns true if the file maybe is able to be loaded by this class + //! based on the file extension (e.g. ".tga") + bool CImageLoaderTex::isALoadableFileExtension (const io::path &filename) const + { + return core::hasFileExtension (filename, "tex"); + } + + + //! returns true if the file maybe is able to be loaded by this class + bool CImageLoaderTex::isALoadableFileFormat (io::IReadFile *file) const + { + return false; + } + + + // load in the image data + IImage *CImageLoaderTex::loadImage (io::IReadFile *input) const + { + if (!input) + return 0; + + video::IImage *image = 0; + + char buffer [1024]; + + if (input->read (buffer, 9) != 9) + { + wp::irrlicht::device->getLogger ()->log ("LOAD TEX: cannot read header\n", input->getFileName ().c_str (), irr::ELL_ERROR); + return 0; + } + + if (memcmp (buffer, "TEXV0005", 9) != 0) + { + wp::irrlicht::device->getLogger ()->log ("LOAD TEX: not really a tex\n", input->getFileName ().c_str (), irr::ELL_ERROR); + return 0; + } + + if (input->read (buffer, 9) != 9) + { + wp::irrlicht::device->getLogger ()->log ("LOAD TEX: cannot read second header\n", input->getFileName ().c_str (), irr::ELL_ERROR); + return 0; + } + + if (memcmp (buffer, "TEXI0001", 9) != 0) + { + wp::irrlicht::device->getLogger ()->log ("LOAD TEX: not really a tex\n", input->getFileName ().c_str (), irr::ELL_ERROR); + return 0; + } + + u32 width; + u32 height; + u32 texture_width; + u32 texture_height; + u32 format; + + input->read (&format, 4); + input->seek (4, true); // ignore bytes + input->read (&texture_width, 4); + input->read (&texture_height, 4); + input->read (&width, 4); + input->read (&height, 4); + input->seek (4, true); // ignore bytes + input->read (buffer, 9); + + if (memcmp (buffer, "TEXB0003", 9) == 0) + { + wp::irrlicht::device->getLogger ()->log ("LOAD TEX: TEXB0003 container not supported yet\n", input->getFileName ().c_str (), irr::ELL_ERROR); + return 0; + } + else if (memcmp (buffer, "TEXB0002", 9) == 0) + { + input->seek (4, true); + } + else + { + wp::irrlicht::device->getLogger ()->log ("LOAD TEX: Unknown container type\n", input->getFileName ().c_str (), irr::ELL_ERROR); + return 0; + } + + if (format != TextureFormat::ARGB8888) + { + wp::irrlicht::device->getLogger ()->log ("LOAD TEX: Only ARGB8888 supported\n", input->getFileName ().c_str (), irr::ELL_ERROR); + return 0; + } + + u32 mipmap_count = 0; + + input->read (&mipmap_count, 4); + + u32 mipmap_width = 0; + u32 mipmap_height = 0; + u32 mipmap_compression = 0; + u32 mipmap_uncompressed_size = 0; + u32 mipmap_compressed_size = 0; + + input->read (&mipmap_width, 4); + input->read (&mipmap_height, 4); + input->read (&mipmap_compression, 4); + input->read (&mipmap_uncompressed_size, 4); + input->read (&mipmap_compressed_size, 4); + + char *decompressedBuffer = new char [mipmap_uncompressed_size]; + + if (mipmap_compression == 1) + { + char *compressedBuffer = new char [mipmap_compressed_size]; + + input->read (compressedBuffer, mipmap_compressed_size); + + int result = LZ4_decompress_safe (compressedBuffer, decompressedBuffer, mipmap_compressed_size, mipmap_uncompressed_size); + + if (!result) + { + delete [] decompressedBuffer; + delete [] compressedBuffer; + wp::irrlicht::device->getLogger ()->log ("LOAD TEX: cannot decompress texture data\n", input->getFileName ().c_str (), irr::ELL_ERROR); + return 0; + } + + delete [] compressedBuffer; + } + else + { + input->read (decompressedBuffer, mipmap_uncompressed_size); + } + + image = wp::irrlicht::driver->createImage (ECF_A8R8G8B8, irr::core::dimension2d (texture_width, texture_height)); + + if (!image) + { + delete [] decompressedBuffer; + delete image; + wp::irrlicht::device->getLogger ()->log ("LOAD TEX: cannot create destination image\n", input->getFileName ().c_str (), irr::ELL_ERROR); + return 0; + } + + u32 bytesPerPixel = image->getBytesPerPixel (); + char *imagedata = (char *) image->lock (); + + for (u32 y = 0; y < height; y++) + { + u32 baseDestination = y * image->getPitch (); + u32 baseOrigin = y * (texture_width * 4); + + for (u32 x = 0; x < width; x++) + { + imagedata[baseDestination + (x * bytesPerPixel) + 0] = decompressedBuffer[baseOrigin + ((texture_width - x) * 4) + 0]; + imagedata[baseDestination + (x * bytesPerPixel) + 1] = decompressedBuffer[baseOrigin + ((texture_width - x) * 4) + 1]; + imagedata[baseDestination + (x * bytesPerPixel) + 2] = decompressedBuffer[baseOrigin + ((texture_width - x) * 4) + 2]; + imagedata[baseDestination + (x * bytesPerPixel) + 3] = decompressedBuffer[baseOrigin + ((texture_width - x) * 4) + 3]; + } + } + + image->unlock (); + + delete [] decompressedBuffer; + + return image; + } + + + }// end namespace irr +}//end namespace video + diff --git a/wallpaperengine/irr/CImageLoaderTEX.h b/wallpaperengine/irr/CImageLoaderTEX.h new file mode 100644 index 0000000..dde6f33 --- /dev/null +++ b/wallpaperengine/irr/CImageLoaderTEX.h @@ -0,0 +1,51 @@ +// Copyright (C) 2002-2012 Nikolaus Gebhardt +// This file is part of the "Irrlicht Engine". +// For conditions of distribution and use, see copyright notice in irrlicht.h + +// this file was created by rt (www.tomkorp.com), based on ttk's png-reader +// i wanted to be able to read in PNG images with irrlicht :) +// why? lossless compression with 8-bit alpha channel! + +#ifndef __C_IMAGE_LOADER_TEX_H_INCLUDED__ +#define __C_IMAGE_LOADER_PNG_H_INCLUDED__ + +#include + +namespace irr +{ +namespace video +{ + +//! Surface Loader for PNG files +class CImageLoaderTex : public IImageLoader +{ +public: + + //! returns true if the file maybe is able to be loaded by this class + //! based on the file extension (e.g. ".png") + virtual bool isALoadableFileExtension(const io::path& filename) const; + + //! returns true if the file maybe is able to be loaded by this class + virtual bool isALoadableFileFormat(io::IReadFile* file) const; + + //! creates a surface from the file + virtual IImage* loadImage(io::IReadFile* input) const; + +private: + enum TextureFormat + { + ARGB8888, + RA88, + A8, + DXT5, + DXT3, + DXT1 + }; +}; + + +} // end namespace video +} // end namespace irr + +#endif + diff --git a/wallpaperengine/project.cpp b/wallpaperengine/project.cpp index fe9b938..e3ccc68 100644 --- a/wallpaperengine/project.cpp +++ b/wallpaperengine/project.cpp @@ -1,6 +1,7 @@ #include #include #include +#include #include "fs/fileResolver.h" @@ -41,7 +42,7 @@ namespace wp if (this->m_type != "scene") { - throw "Only scene wallpapers supported for now"; + throw std::runtime_error ("Only scene wallpapers are supported"); } } diff --git a/wallpaperengine/texture.cpp b/wallpaperengine/texture.cpp index cb67dad..5ab6c2f 100644 --- a/wallpaperengine/texture.cpp +++ b/wallpaperengine/texture.cpp @@ -1,15 +1,16 @@ #include +#include +#include + #include "irrlicht.h" namespace wp { - texture::texture (irr::io::path file) { this->m_texture = wp::irrlicht::driver->getTexture (file); } - irr::video::ITexture* texture::getIrrTexture () { return this->m_texture;