mirror of https://github.com/PCSX2/pcsx2.git
Common: Add Image and Easing classes
This commit is contained in:
parent
33f1e51ebc
commit
9cce6945e6
|
@ -19,6 +19,7 @@ target_sources(common PRIVATE
|
||||||
Exceptions.cpp
|
Exceptions.cpp
|
||||||
FastJmp.cpp
|
FastJmp.cpp
|
||||||
FileSystem.cpp
|
FileSystem.cpp
|
||||||
|
Image.cpp
|
||||||
Misc.cpp
|
Misc.cpp
|
||||||
MD5Digest.cpp
|
MD5Digest.cpp
|
||||||
PrecompiledHeader.cpp
|
PrecompiledHeader.cpp
|
||||||
|
@ -60,6 +61,7 @@ target_sources(common PRIVATE
|
||||||
boost_spsc_queue.hpp
|
boost_spsc_queue.hpp
|
||||||
Console.h
|
Console.h
|
||||||
CrashHandler.h
|
CrashHandler.h
|
||||||
|
Easing.h
|
||||||
EnumOps.h
|
EnumOps.h
|
||||||
EventSource.h
|
EventSource.h
|
||||||
Exceptions.h
|
Exceptions.h
|
||||||
|
@ -67,6 +69,7 @@ target_sources(common PRIVATE
|
||||||
FileSystem.h
|
FileSystem.h
|
||||||
General.h
|
General.h
|
||||||
HashCombine.h
|
HashCombine.h
|
||||||
|
Image.h
|
||||||
LRUCache.h
|
LRUCache.h
|
||||||
MemcpyFast.h
|
MemcpyFast.h
|
||||||
MemsetFast.inl
|
MemsetFast.inl
|
||||||
|
@ -264,6 +267,8 @@ endif()
|
||||||
|
|
||||||
target_link_libraries(common PRIVATE
|
target_link_libraries(common PRIVATE
|
||||||
${LIBC_LIBRARIES}
|
${LIBC_LIBRARIES}
|
||||||
|
PNG::PNG
|
||||||
|
jpgd
|
||||||
)
|
)
|
||||||
|
|
||||||
target_link_libraries(common PUBLIC
|
target_link_libraries(common PUBLIC
|
||||||
|
|
|
@ -0,0 +1,258 @@
|
||||||
|
#pragma once
|
||||||
|
#include "Pcsx2Defs.h"
|
||||||
|
#include <cmath>
|
||||||
|
|
||||||
|
// From https://github.com/nicolausYes/easing-functions/blob/master/src/easing.cpp
|
||||||
|
|
||||||
|
namespace Easing {
|
||||||
|
static constexpr float pi = 3.1415926545f;
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
__ri static T InSine(T t)
|
||||||
|
{
|
||||||
|
return std::sin(1.5707963f * t);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
__ri static T OutSine(T t)
|
||||||
|
{
|
||||||
|
return 1 + std::sin(1.5707963f * (--t));
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
__ri static T InOutSine(T t)
|
||||||
|
{
|
||||||
|
return 0.5f * (1 + std::sin(3.1415926f * (t - 0.5f)));
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
__ri static T InQuad(T t)
|
||||||
|
{
|
||||||
|
return t * t;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
__ri static T OutQuad(T t)
|
||||||
|
{
|
||||||
|
return t * (2 - t);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
__ri static T InOutQuad(T t)
|
||||||
|
{
|
||||||
|
return t < 0.5f ? 2 * t * t : t * (4 - 2 * t) - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
__ri static T InCubic(T t)
|
||||||
|
{
|
||||||
|
return t * t * t;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
__ri static T OutCubic(T t)
|
||||||
|
{
|
||||||
|
return 1 + (--t) * t * t;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
__ri static T InOutCubic(T t)
|
||||||
|
{
|
||||||
|
return t < 0.5f ? 4 * t * t * t : 1 + (--t) * (2 * (--t)) * (2 * t);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
__ri static T InQuart(T t)
|
||||||
|
{
|
||||||
|
t *= t;
|
||||||
|
return t * t;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
__ri static T OutQuart(T t)
|
||||||
|
{
|
||||||
|
t = (--t) * t;
|
||||||
|
return 1 - t * t;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
__ri static T InOutQuart(T t)
|
||||||
|
{
|
||||||
|
if (t < 0.5)
|
||||||
|
{
|
||||||
|
t *= t;
|
||||||
|
return 8 * t * t;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
t = (--t) * t;
|
||||||
|
return 1 - 8 * t * t;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
__ri static T InQuint(T t)
|
||||||
|
{
|
||||||
|
T t2 = t * t;
|
||||||
|
return t * t2 * t2;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
__ri static T OutQuint(T t)
|
||||||
|
{
|
||||||
|
T t2 = (--t) * t;
|
||||||
|
return 1 + t * t2 * t2;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
__ri static T InOutQuint(T t)
|
||||||
|
{
|
||||||
|
T t2;
|
||||||
|
if (t < 0.5)
|
||||||
|
{
|
||||||
|
t2 = t * t;
|
||||||
|
return 16 * t * t2 * t2;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
t2 = (--t) * t;
|
||||||
|
return 1 + 16 * t * t2 * t2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
__ri static T InExpo(T t)
|
||||||
|
{
|
||||||
|
return (std::pow(2, 8 * t) - 1) / 255;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
__ri static T OutExpo(T t)
|
||||||
|
{
|
||||||
|
return 1 - std::pow(2, -8 * t);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
__ri static T InOutExpo(T t)
|
||||||
|
{
|
||||||
|
if (t < 0.5f)
|
||||||
|
{
|
||||||
|
return (std::pow(2, 16 * t) - 1) / 510;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return 1 - 0.5f * std::pow(2, -16 * (t - 0.5f));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
__ri static T InCirc(T t)
|
||||||
|
{
|
||||||
|
return 1 - std::sqrt(1 - t);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
__ri static T OutCirc(T t)
|
||||||
|
{
|
||||||
|
return std::sqrt(t);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
__ri static T InOutCirc(T t)
|
||||||
|
{
|
||||||
|
if (t < 0.5f)
|
||||||
|
{
|
||||||
|
return (1 - std::sqrt(1 - 2 * t)) * 0.5f;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return (1 + std::sqrt(2 * t - 1)) * 0.5f;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
__ri static T InBack(T t)
|
||||||
|
{
|
||||||
|
return t * t * (2.70158f * t - 1.70158f);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
static T OutBack(T t)
|
||||||
|
{
|
||||||
|
t -= 1;
|
||||||
|
return 1 + t * t * (2.70158f * t + 1.70158f);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
__ri static T InOutBack(T t)
|
||||||
|
{
|
||||||
|
if (t < 0.5f)
|
||||||
|
{
|
||||||
|
return t * t * (7 * t - 2.5f) * 2;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return 1 + (--t) * t * 2 * (7 * t + 2.5f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
__ri static T InElastic(T t)
|
||||||
|
{
|
||||||
|
T t2 = t * t;
|
||||||
|
return t2 * t2 * std::sin(t * pi * 4.5f);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
__ri static T OutElastic(T t)
|
||||||
|
{
|
||||||
|
T t2 = (t - 1) * (t - 1);
|
||||||
|
return 1 - t2 * t2 * std::cos(t * pi * 4.5f);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
__ri static T InOutElastic(T t)
|
||||||
|
{
|
||||||
|
T t2;
|
||||||
|
if (t < 0.45f)
|
||||||
|
{
|
||||||
|
t2 = t * t;
|
||||||
|
return 8 * t2 * t2 * std::sin(t * pi * 9);
|
||||||
|
}
|
||||||
|
else if (t < 0.55f)
|
||||||
|
{
|
||||||
|
return 0.5f + 0.75f * std::sin(t * pi * 4);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
t2 = (t - 1) * (t - 1);
|
||||||
|
return 1 - 8 * t2 * t2 * std::sin(t * pi * 9);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
__ri static T InBounce(T t)
|
||||||
|
{
|
||||||
|
return std::pow(2, 6 * (t - 1)) * std::abs(sin(t * pi * 3.5f));
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
__ri static T OutBounce(T t)
|
||||||
|
{
|
||||||
|
return 1 - std::pow(2, -6 * t) * std::abs(std::cos(t * pi * 3.5f));
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
__ri static T InOutBounce(T t)
|
||||||
|
{
|
||||||
|
if (t < 0.5f)
|
||||||
|
{
|
||||||
|
return 8 * std::pow(2, 8 * (t - 1)) * std::abs(std::sin(t * pi * 7));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return 1 - 8 * std::pow(2, -8 * t) * std::abs(std::sin(t * pi * 7));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Easing
|
|
@ -0,0 +1,545 @@
|
||||||
|
/* PCSX2 - PS2 Emulator for PCs
|
||||||
|
* Copyright (C) 2002-2022 PCSX2 Dev Team
|
||||||
|
*
|
||||||
|
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
|
||||||
|
* of the GNU Lesser General Public License as published by the Free Software Found-
|
||||||
|
* ation, either version 3 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
||||||
|
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||||
|
* PURPOSE. See the GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License along with PCSX2.
|
||||||
|
* If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "PrecompiledHeader.h"
|
||||||
|
#include "Image.h"
|
||||||
|
#include "FileSystem.h"
|
||||||
|
#include "Console.h"
|
||||||
|
#include "Path.h"
|
||||||
|
#include "ScopedGuard.h"
|
||||||
|
#include "StringUtil.h"
|
||||||
|
|
||||||
|
#include "jpgd.h"
|
||||||
|
#include "jpge.h"
|
||||||
|
#include <png.h>
|
||||||
|
|
||||||
|
using namespace Common;
|
||||||
|
|
||||||
|
static bool PNGBufferLoader(RGBA8Image* image, const void* buffer, size_t buffer_size);
|
||||||
|
static bool PNGBufferSaver(const RGBA8Image& image, std::vector<u8>* buffer, int quality);
|
||||||
|
static bool PNGFileLoader(RGBA8Image* image, const char* filename, std::FILE* fp);
|
||||||
|
static bool PNGFileSaver(const RGBA8Image& image, const char* filename, std::FILE* fp, int quality);
|
||||||
|
|
||||||
|
static bool JPEGBufferLoader(RGBA8Image* image, const void* buffer, size_t buffer_size);
|
||||||
|
static bool JPEGBufferSaver(const RGBA8Image& image, std::vector<u8>* buffer, int quality);
|
||||||
|
static bool JPEGFileLoader(RGBA8Image* image, const char* filename, std::FILE* fp);
|
||||||
|
static bool JPEGFileSaver(const RGBA8Image& image, const char* filename, std::FILE* fp, int quality);
|
||||||
|
|
||||||
|
struct FormatHandler
|
||||||
|
{
|
||||||
|
const char* extension;
|
||||||
|
bool (*buffer_loader)(RGBA8Image*, const void*, size_t);
|
||||||
|
bool (*buffer_saver)(const RGBA8Image&, std::vector<u8>*, int);
|
||||||
|
bool (*file_loader)(RGBA8Image*, const char*, std::FILE*);
|
||||||
|
bool (*file_saver)(const RGBA8Image&, const char*, std::FILE*, int);
|
||||||
|
};
|
||||||
|
|
||||||
|
static constexpr FormatHandler s_format_handlers[] = {
|
||||||
|
{"png", PNGBufferLoader, PNGBufferSaver, PNGFileLoader, PNGFileSaver},
|
||||||
|
{"jpg", JPEGBufferLoader, JPEGBufferSaver, JPEGFileLoader, JPEGFileSaver},
|
||||||
|
{"jpeg", JPEGBufferLoader, JPEGBufferSaver, JPEGFileLoader, JPEGFileSaver},
|
||||||
|
};
|
||||||
|
|
||||||
|
static const FormatHandler* GetFormatHandler(const std::string_view& extension)
|
||||||
|
{
|
||||||
|
for (const FormatHandler& handler : s_format_handlers)
|
||||||
|
{
|
||||||
|
if (StringUtil::compareNoCase(extension, handler.extension))
|
||||||
|
return &handler;
|
||||||
|
}
|
||||||
|
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
RGBA8Image::RGBA8Image() = default;
|
||||||
|
|
||||||
|
RGBA8Image::RGBA8Image(const RGBA8Image& copy)
|
||||||
|
: Image(copy)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
RGBA8Image::RGBA8Image(u32 width, u32 height, const u32* pixels)
|
||||||
|
: Image(width, height, pixels)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
RGBA8Image::RGBA8Image(RGBA8Image&& move)
|
||||||
|
: Image(move)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
RGBA8Image& RGBA8Image::operator=(const RGBA8Image& copy)
|
||||||
|
{
|
||||||
|
Image<u32>::operator=(copy);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
RGBA8Image& RGBA8Image::operator=(RGBA8Image&& move)
|
||||||
|
{
|
||||||
|
Image<u32>::operator=(move);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool RGBA8Image::LoadFromFile(const char* filename)
|
||||||
|
{
|
||||||
|
auto fp = FileSystem::OpenManagedCFile(filename, "rb");
|
||||||
|
if (!fp)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return LoadFromFile(filename, fp.get());
|
||||||
|
}
|
||||||
|
|
||||||
|
bool RGBA8Image::SaveToFile(const char* filename, int quality) const
|
||||||
|
{
|
||||||
|
auto fp = FileSystem::OpenManagedCFile(filename, "wb");
|
||||||
|
if (!fp)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (SaveToFile(filename, fp.get(), quality))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
// save failed
|
||||||
|
fp.reset();
|
||||||
|
FileSystem::DeleteFilePath(filename);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool RGBA8Image::LoadFromFile(const char* filename, std::FILE* fp)
|
||||||
|
{
|
||||||
|
const std::string_view extension(Path::GetExtension(filename));
|
||||||
|
const FormatHandler* handler = GetFormatHandler(extension);
|
||||||
|
if (!handler || !handler->file_loader)
|
||||||
|
{
|
||||||
|
Console.Error("(RGBA8Image::LoadFromFile) Unknown extension '%.*s'",
|
||||||
|
static_cast<int>(extension.size()), extension.data());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return handler->file_loader(this, filename, fp);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool RGBA8Image::LoadFromBuffer(const char* filename, const void* buffer, size_t buffer_size)
|
||||||
|
{
|
||||||
|
const std::string_view extension(Path::GetExtension(filename));
|
||||||
|
const FormatHandler* handler = GetFormatHandler(extension);
|
||||||
|
if (!handler || !handler->buffer_loader)
|
||||||
|
{
|
||||||
|
Console.Error("(RGBA8Image::LoadFromBuffer) Unknown extension '%.*s'",
|
||||||
|
static_cast<int>(extension.size()), extension.data());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return handler->buffer_loader(this, buffer, buffer_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool RGBA8Image::SaveToFile(const char* filename, std::FILE* fp, int quality) const
|
||||||
|
{
|
||||||
|
const std::string_view extension(Path::GetExtension(filename));
|
||||||
|
const FormatHandler* handler = GetFormatHandler(extension);
|
||||||
|
if (!handler || !handler->file_saver)
|
||||||
|
{
|
||||||
|
Console.Error("(RGBA8Image::SaveToFile) Unknown extension '%.*s'",
|
||||||
|
static_cast<int>(extension.size()), extension.data());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!handler->file_saver(*this, filename, fp, quality))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return (std::fflush(fp) == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::optional<std::vector<u8>> RGBA8Image::SaveToBuffer(const char* filename, int quality) const
|
||||||
|
{
|
||||||
|
std::optional<std::vector<u8>> ret;
|
||||||
|
|
||||||
|
const std::string_view extension(Path::GetExtension(filename));
|
||||||
|
const FormatHandler* handler = GetFormatHandler(extension);
|
||||||
|
if (!handler || !handler->file_saver)
|
||||||
|
{
|
||||||
|
Console.Error("(RGBA8Image::SaveToBuffer) Unknown extension '%.*s'",
|
||||||
|
static_cast<int>(extension.size()), extension.data());
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = std::vector<u8>();
|
||||||
|
if (!handler->buffer_saver(*this, &ret.value(), quality))
|
||||||
|
ret.reset();
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool PNGCommonLoader(RGBA8Image* image, png_structp png_ptr, png_infop info_ptr,
|
||||||
|
std::vector<u32>& new_data, std::vector<png_bytep>& row_pointers)
|
||||||
|
{
|
||||||
|
png_read_info(png_ptr, info_ptr);
|
||||||
|
|
||||||
|
const u32 width = png_get_image_width(png_ptr, info_ptr);
|
||||||
|
const u32 height = png_get_image_height(png_ptr, info_ptr);
|
||||||
|
const png_byte color_type = png_get_color_type(png_ptr, info_ptr);
|
||||||
|
const png_byte bit_depth = png_get_bit_depth(png_ptr, info_ptr);
|
||||||
|
|
||||||
|
// Read any color_type into 8bit depth, RGBA format.
|
||||||
|
// See http://www.libpng.org/pub/png/libpng-manual.txt
|
||||||
|
|
||||||
|
if (bit_depth == 16)
|
||||||
|
png_set_strip_16(png_ptr);
|
||||||
|
|
||||||
|
if (color_type == PNG_COLOR_TYPE_PALETTE)
|
||||||
|
png_set_palette_to_rgb(png_ptr);
|
||||||
|
|
||||||
|
// PNG_COLOR_TYPE_GRAY_ALPHA is always 8 or 16bit depth.
|
||||||
|
if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8)
|
||||||
|
png_set_expand_gray_1_2_4_to_8(png_ptr);
|
||||||
|
|
||||||
|
if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS))
|
||||||
|
png_set_tRNS_to_alpha(png_ptr);
|
||||||
|
|
||||||
|
// These color_type don't have an alpha channel then fill it with 0xff.
|
||||||
|
if (color_type == PNG_COLOR_TYPE_RGB ||
|
||||||
|
color_type == PNG_COLOR_TYPE_GRAY ||
|
||||||
|
color_type == PNG_COLOR_TYPE_PALETTE)
|
||||||
|
png_set_filler(png_ptr, 0xFF, PNG_FILLER_AFTER);
|
||||||
|
|
||||||
|
if (color_type == PNG_COLOR_TYPE_GRAY ||
|
||||||
|
color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
|
||||||
|
png_set_gray_to_rgb(png_ptr);
|
||||||
|
|
||||||
|
png_read_update_info(png_ptr, info_ptr);
|
||||||
|
|
||||||
|
new_data.resize(width * height);
|
||||||
|
row_pointers.reserve(height);
|
||||||
|
for (u32 y = 0; y < height; y++)
|
||||||
|
row_pointers.push_back(reinterpret_cast<png_bytep>(new_data.data() + y * width));
|
||||||
|
|
||||||
|
png_read_image(png_ptr, row_pointers.data());
|
||||||
|
image->SetPixels(width, height, std::move(new_data));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool PNGFileLoader(RGBA8Image* image, const char* filename, std::FILE* fp)
|
||||||
|
{
|
||||||
|
png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, nullptr, nullptr, nullptr);
|
||||||
|
if (!png_ptr)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
png_infop info_ptr = png_create_info_struct(png_ptr);
|
||||||
|
if (!info_ptr)
|
||||||
|
{
|
||||||
|
png_destroy_read_struct(&png_ptr, nullptr, nullptr);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
ScopedGuard cleanup([&png_ptr, &info_ptr]() {
|
||||||
|
png_destroy_read_struct(&png_ptr, &info_ptr, nullptr);
|
||||||
|
});
|
||||||
|
|
||||||
|
std::vector<u32> new_data;
|
||||||
|
std::vector<png_bytep> row_pointers;
|
||||||
|
|
||||||
|
if (setjmp(png_jmpbuf(png_ptr)))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
png_init_io(png_ptr, fp);
|
||||||
|
return PNGCommonLoader(image, png_ptr, info_ptr, new_data, row_pointers);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool PNGBufferLoader(RGBA8Image* image, const void* buffer, size_t buffer_size)
|
||||||
|
{
|
||||||
|
png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, nullptr, nullptr, nullptr);
|
||||||
|
if (!png_ptr)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
png_infop info_ptr = png_create_info_struct(png_ptr);
|
||||||
|
if (!info_ptr)
|
||||||
|
{
|
||||||
|
png_destroy_read_struct(&png_ptr, nullptr, nullptr);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
ScopedGuard cleanup([&png_ptr, &info_ptr]() {
|
||||||
|
png_destroy_read_struct(&png_ptr, &info_ptr, nullptr);
|
||||||
|
});
|
||||||
|
|
||||||
|
std::vector<u32> new_data;
|
||||||
|
std::vector<png_bytep> row_pointers;
|
||||||
|
|
||||||
|
if (setjmp(png_jmpbuf(png_ptr)))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
struct IOData
|
||||||
|
{
|
||||||
|
const u8* buffer;
|
||||||
|
size_t buffer_size;
|
||||||
|
size_t buffer_pos;
|
||||||
|
};
|
||||||
|
IOData data = {static_cast<const u8*>(buffer), buffer_size, 0};
|
||||||
|
|
||||||
|
png_set_read_fn(png_ptr, &data, [](png_structp png_ptr, png_bytep data_ptr, png_size_t size) {
|
||||||
|
IOData* data = static_cast<IOData*>(png_get_io_ptr(png_ptr));
|
||||||
|
const size_t read_size = std::min<size_t>(data->buffer_size - data->buffer_pos, size);
|
||||||
|
if (read_size > 0)
|
||||||
|
{
|
||||||
|
std::memcpy(data_ptr, data->buffer + data->buffer_pos, read_size);
|
||||||
|
data->buffer_pos += read_size;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return PNGCommonLoader(image, png_ptr, info_ptr, new_data, row_pointers);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void PNGSaveCommon(const RGBA8Image& image, png_structp png_ptr, png_infop info_ptr, int quality)
|
||||||
|
{
|
||||||
|
png_set_compression_level(png_ptr, std::clamp(quality / 10, 0, 9));
|
||||||
|
png_set_IHDR(png_ptr, info_ptr, image.GetWidth(), image.GetHeight(), 8, PNG_COLOR_TYPE_RGBA,
|
||||||
|
PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
|
||||||
|
png_write_info(png_ptr, info_ptr);
|
||||||
|
|
||||||
|
for (u32 y = 0; y < image.GetHeight(); ++y)
|
||||||
|
png_write_row(png_ptr, (png_bytep)image.GetRowPixels(y));
|
||||||
|
|
||||||
|
png_write_end(png_ptr, nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool PNGFileSaver(const RGBA8Image& image, const char* filename, std::FILE* fp, int quality)
|
||||||
|
{
|
||||||
|
png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, nullptr, nullptr, nullptr);
|
||||||
|
png_infop info_ptr = nullptr;
|
||||||
|
if (!png_ptr)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
ScopedGuard cleanup([&png_ptr, &info_ptr]() {
|
||||||
|
if (png_ptr)
|
||||||
|
png_destroy_write_struct(&png_ptr, info_ptr ? &info_ptr : nullptr);
|
||||||
|
});
|
||||||
|
|
||||||
|
info_ptr = png_create_info_struct(png_ptr);
|
||||||
|
if (!info_ptr)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (setjmp(png_jmpbuf(png_ptr)))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
png_set_write_fn(
|
||||||
|
png_ptr, fp, [](png_structp png_ptr, png_bytep data_ptr, png_size_t size) {
|
||||||
|
if (std::fwrite(data_ptr, size, 1, static_cast<std::FILE*>(png_get_io_ptr(png_ptr))) != 1)
|
||||||
|
png_error(png_ptr, "file write error"); }, [](png_structp png_ptr) {});
|
||||||
|
|
||||||
|
PNGSaveCommon(image, png_ptr, info_ptr, quality);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool PNGBufferSaver(const RGBA8Image& image, std::vector<u8>* buffer, int quality)
|
||||||
|
{
|
||||||
|
png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, nullptr, nullptr, nullptr);
|
||||||
|
png_infop info_ptr = nullptr;
|
||||||
|
if (!png_ptr)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
ScopedGuard cleanup([&png_ptr, &info_ptr]() {
|
||||||
|
if (png_ptr)
|
||||||
|
png_destroy_write_struct(&png_ptr, info_ptr ? &info_ptr : nullptr);
|
||||||
|
});
|
||||||
|
|
||||||
|
info_ptr = png_create_info_struct(png_ptr);
|
||||||
|
if (!info_ptr)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
buffer->reserve(image.GetWidth() * image.GetHeight() * 2);
|
||||||
|
|
||||||
|
if (setjmp(png_jmpbuf(png_ptr)))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
png_set_write_fn(
|
||||||
|
png_ptr, buffer, [](png_structp png_ptr, png_bytep data_ptr, png_size_t size) {
|
||||||
|
std::vector<u8>* buffer = static_cast<std::vector<u8>*>(png_get_io_ptr(png_ptr));
|
||||||
|
const size_t old_pos = buffer->size();
|
||||||
|
buffer->resize(old_pos + size);
|
||||||
|
std::memcpy(buffer->data() + old_pos, data_ptr, size); }, [](png_structp png_ptr) {});
|
||||||
|
|
||||||
|
PNGSaveCommon(image, png_ptr, info_ptr, quality);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool JPEGBufferLoader(RGBA8Image* image, const void* buffer, size_t buffer_size)
|
||||||
|
{
|
||||||
|
int width, height, file_comps;
|
||||||
|
u8* data = jpgd::decompress_jpeg_image_from_memory(static_cast<const u8*>(buffer), static_cast<int>(buffer_size),
|
||||||
|
&width, &height, &file_comps, 4, 0);
|
||||||
|
if (!data)
|
||||||
|
{
|
||||||
|
Console.Error("jpgd::decompress_jpeg_image_from_memory() failed");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
image->SetPixels(static_cast<u32>(width), static_cast<u32>(height), reinterpret_cast<const u32*>(data));
|
||||||
|
std::free(data);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool JPEGFileLoader(RGBA8Image* image, const char* filename, std::FILE* fp)
|
||||||
|
{
|
||||||
|
class FileStream : public jpgd::jpeg_decoder_stream
|
||||||
|
{
|
||||||
|
std::FILE* m_fp;
|
||||||
|
bool m_error_flag = false;
|
||||||
|
bool m_eof_flag = false;
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit FileStream(std::FILE* fp_)
|
||||||
|
: m_fp(fp_)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
int read(jpgd::uint8* pBuf, int max_bytes_to_read, bool* pEOF_flag) override
|
||||||
|
{
|
||||||
|
if (m_eof_flag)
|
||||||
|
{
|
||||||
|
*pEOF_flag = true;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_error_flag)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
int bytes_read = static_cast<int>(std::fread(pBuf, 1, max_bytes_to_read, m_fp));
|
||||||
|
if (bytes_read < max_bytes_to_read)
|
||||||
|
{
|
||||||
|
if (std::ferror(m_fp))
|
||||||
|
{
|
||||||
|
m_error_flag = true;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_eof_flag = true;
|
||||||
|
*pEOF_flag = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return bytes_read;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
FileStream stream(fp);
|
||||||
|
int width, height, file_comps;
|
||||||
|
u8* data = jpgd::decompress_jpeg_image_from_stream(&stream, &width, &height, &file_comps, 4, 0);
|
||||||
|
if (!data)
|
||||||
|
{
|
||||||
|
Console.Error("jpgd::decompress_jpeg_image_from_stream() failed");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
image->SetPixels(static_cast<u32>(width), static_cast<u32>(height), reinterpret_cast<const u32*>(data));
|
||||||
|
std::free(data);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool JPEGCommonSaver(const RGBA8Image& image, jpge::output_stream& stream, int quality)
|
||||||
|
{
|
||||||
|
jpge::params params;
|
||||||
|
params.m_quality = quality;
|
||||||
|
|
||||||
|
jpge::jpeg_encoder dst_image;
|
||||||
|
if (!dst_image.init(&stream, image.GetWidth(), image.GetHeight(), 3, params))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// for RGBA->RGB
|
||||||
|
std::vector<u8> row;
|
||||||
|
row.resize(image.GetWidth() * 3);
|
||||||
|
|
||||||
|
for (uint pass_index = 0; pass_index < dst_image.get_total_passes(); pass_index++)
|
||||||
|
{
|
||||||
|
for (u32 i = 0; i < image.GetHeight(); i++)
|
||||||
|
{
|
||||||
|
const u8* row_in = reinterpret_cast<const u8*>(image.GetRowPixels(i));
|
||||||
|
u8* row_out = row.data();
|
||||||
|
for (u32 j = 0; j < image.GetWidth(); j++)
|
||||||
|
{
|
||||||
|
*(row_out++) = *(row_in++);
|
||||||
|
*(row_out++) = *(row_in++);
|
||||||
|
*(row_out++) = *(row_in++);
|
||||||
|
row_in++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!dst_image.process_scanline(row.data()))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!dst_image.process_scanline(NULL))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
dst_image.deinit();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool JPEGBufferSaver(const RGBA8Image& image, std::vector<u8>* buffer, int quality)
|
||||||
|
{
|
||||||
|
class BufferStream : public jpge::output_stream
|
||||||
|
{
|
||||||
|
std::vector<u8>* buffer;
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit BufferStream(std::vector<u8>* buffer_)
|
||||||
|
: buffer(buffer_)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
bool put_buf(const void* Pbuf, int len) override
|
||||||
|
{
|
||||||
|
const size_t old_size = buffer->size();
|
||||||
|
buffer->resize(buffer->size() + static_cast<size_t>(len));
|
||||||
|
std::memcpy(buffer->data() + old_size, Pbuf, static_cast<size_t>(len));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// give enough space to avoid reallocs
|
||||||
|
buffer->reserve(image.GetWidth() * image.GetHeight() * 2);
|
||||||
|
|
||||||
|
BufferStream stream(buffer);
|
||||||
|
return JPEGCommonSaver(image, stream, quality);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool JPEGFileSaver(const RGBA8Image& image, const char* filename, std::FILE* fp, int quality)
|
||||||
|
{
|
||||||
|
class FileStream : public jpge::output_stream
|
||||||
|
{
|
||||||
|
std::FILE* m_fp;
|
||||||
|
bool m_error_flag = false;
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit FileStream(std::FILE* fp_)
|
||||||
|
: m_fp(fp_)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
bool put_buf(const void* Pbuf, int len) override
|
||||||
|
{
|
||||||
|
if (m_error_flag)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (std::fwrite(Pbuf, len, 1, m_fp) != 1)
|
||||||
|
{
|
||||||
|
m_error_flag = true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
FileStream stream(fp);
|
||||||
|
return JPEGCommonSaver(image, stream, quality);
|
||||||
|
}
|
|
@ -0,0 +1,144 @@
|
||||||
|
/* PCSX2 - PS2 Emulator for PCs
|
||||||
|
* Copyright (C) 2002-2022 PCSX2 Dev Team
|
||||||
|
*
|
||||||
|
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
|
||||||
|
* of the GNU Lesser General Public License as published by the Free Software Found-
|
||||||
|
* ation, either version 3 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
||||||
|
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||||
|
* PURPOSE. See the GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License along with PCSX2.
|
||||||
|
* If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
#include "Pcsx2Defs.h"
|
||||||
|
#include <algorithm>
|
||||||
|
#include <cstdio>
|
||||||
|
#include <cstring>
|
||||||
|
#include <optional>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
namespace Common
|
||||||
|
{
|
||||||
|
template <typename PixelType>
|
||||||
|
class Image
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Image() = default;
|
||||||
|
Image(u32 width, u32 height, const PixelType* pixels) { SetPixels(width, height, pixels); }
|
||||||
|
Image(const Image& copy)
|
||||||
|
{
|
||||||
|
m_width = copy.m_width;
|
||||||
|
m_height = copy.m_height;
|
||||||
|
m_pixels = copy.m_pixels;
|
||||||
|
}
|
||||||
|
Image(Image&& move)
|
||||||
|
{
|
||||||
|
m_width = move.m_width;
|
||||||
|
m_height = move.m_height;
|
||||||
|
m_pixels = std::move(move.m_pixels);
|
||||||
|
move.m_width = 0;
|
||||||
|
move.m_height = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
Image& operator=(const Image& copy)
|
||||||
|
{
|
||||||
|
m_width = copy.m_width;
|
||||||
|
m_height = copy.m_height;
|
||||||
|
m_pixels = copy.m_pixels;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
Image& operator=(Image&& move)
|
||||||
|
{
|
||||||
|
m_width = move.m_width;
|
||||||
|
m_height = move.m_height;
|
||||||
|
m_pixels = std::move(move.m_pixels);
|
||||||
|
move.m_width = 0;
|
||||||
|
move.m_height = 0;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
__fi bool IsValid() const { return (m_width > 0 && m_height > 0); }
|
||||||
|
__fi u32 GetWidth() const { return m_width; }
|
||||||
|
__fi u32 GetHeight() const { return m_height; }
|
||||||
|
__fi u32 GetByteStride() const { return (sizeof(PixelType) * m_width); }
|
||||||
|
__fi const PixelType* GetPixels() const { return m_pixels.data(); }
|
||||||
|
__fi PixelType* GetPixels() { return m_pixels.data(); }
|
||||||
|
__fi const PixelType* GetRowPixels(u32 y) const { return &m_pixels[y * m_width]; }
|
||||||
|
__fi PixelType* GetRowPixels(u32 y) { return &m_pixels[y * m_width]; }
|
||||||
|
__fi void SetPixel(u32 x, u32 y, PixelType pixel) { m_pixels[y * m_width + x] = pixel; }
|
||||||
|
__fi PixelType GetPixel(u32 x, u32 y) const { return m_pixels[y * m_width + x]; }
|
||||||
|
|
||||||
|
void Clear(PixelType fill_value = static_cast<PixelType>(0))
|
||||||
|
{
|
||||||
|
std::fill(m_pixels.begin(), m_pixels.end(), fill_value);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Invalidate()
|
||||||
|
{
|
||||||
|
m_width = 0;
|
||||||
|
m_height = 0;
|
||||||
|
m_pixels.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetSize(u32 new_width, u32 new_height, PixelType fill_value = static_cast<PixelType>(0))
|
||||||
|
{
|
||||||
|
m_width = new_width;
|
||||||
|
m_height = new_height;
|
||||||
|
m_pixels.resize(new_width * new_height);
|
||||||
|
Clear(fill_value);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetPixels(u32 width, u32 height, const PixelType* pixels)
|
||||||
|
{
|
||||||
|
m_width = width;
|
||||||
|
m_height = height;
|
||||||
|
m_pixels.resize(width * height);
|
||||||
|
std::memcpy(m_pixels.data(), pixels, width * height * sizeof(PixelType));
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetPixels(u32 width, u32 height, std::vector<PixelType> pixels)
|
||||||
|
{
|
||||||
|
m_width = width;
|
||||||
|
m_height = height;
|
||||||
|
m_pixels = std::move(pixels);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<PixelType> TakePixels()
|
||||||
|
{
|
||||||
|
m_width = 0;
|
||||||
|
m_height = 0;
|
||||||
|
return std::move(m_pixels);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
u32 m_width = 0;
|
||||||
|
u32 m_height = 0;
|
||||||
|
std::vector<PixelType> m_pixels;
|
||||||
|
};
|
||||||
|
|
||||||
|
class RGBA8Image : public Image<u32>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
static constexpr int DEFAULT_SAVE_QUALITY = 85;
|
||||||
|
|
||||||
|
RGBA8Image();
|
||||||
|
RGBA8Image(u32 width, u32 height, const u32* pixels);
|
||||||
|
RGBA8Image(const RGBA8Image& copy);
|
||||||
|
RGBA8Image(RGBA8Image&& move);
|
||||||
|
|
||||||
|
RGBA8Image& operator=(const RGBA8Image& copy);
|
||||||
|
RGBA8Image& operator=(RGBA8Image&& move);
|
||||||
|
|
||||||
|
bool LoadFromFile(const char* filename);
|
||||||
|
bool LoadFromFile(const char* filename, std::FILE* fp);
|
||||||
|
bool LoadFromBuffer(const char* filename, const void* buffer, size_t buffer_size);
|
||||||
|
|
||||||
|
bool SaveToFile(const char* filename, int quality = DEFAULT_SAVE_QUALITY) const;
|
||||||
|
bool SaveToFile(const char* filename, std::FILE* fp, int quality = DEFAULT_SAVE_QUALITY) const;
|
||||||
|
std::optional<std::vector<u8>> SaveToBuffer(const char* filename, int quality = DEFAULT_SAVE_QUALITY) const;
|
||||||
|
};
|
||||||
|
} // namespace Common
|
|
@ -33,6 +33,8 @@
|
||||||
<ItemDefinitionGroup>
|
<ItemDefinitionGroup>
|
||||||
<ClCompile>
|
<ClCompile>
|
||||||
<AdditionalIncludeDirectories>$(SolutionDir)3rdparty\d3d12memalloc\include;$(SolutionDir)3rdparty\glad\include;$(SolutionDir)3rdparty\glslang\glslang;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
<AdditionalIncludeDirectories>$(SolutionDir)3rdparty\d3d12memalloc\include;$(SolutionDir)3rdparty\glad\include;$(SolutionDir)3rdparty\glslang\glslang;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||||
|
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(SolutionDir)3rdparty\libpng</AdditionalIncludeDirectories>
|
||||||
|
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(SolutionDir)3rdparty\jpgd</AdditionalIncludeDirectories>
|
||||||
<ExceptionHandling>Async</ExceptionHandling>
|
<ExceptionHandling>Async</ExceptionHandling>
|
||||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||||
<ForcedIncludeFiles>PrecompiledHeader.h</ForcedIncludeFiles>
|
<ForcedIncludeFiles>PrecompiledHeader.h</ForcedIncludeFiles>
|
||||||
|
@ -64,6 +66,7 @@
|
||||||
<ClCompile Include="GL\ShaderCache.cpp" />
|
<ClCompile Include="GL\ShaderCache.cpp" />
|
||||||
<ClCompile Include="GL\StreamBuffer.cpp" />
|
<ClCompile Include="GL\StreamBuffer.cpp" />
|
||||||
<ClCompile Include="FileSystem.cpp" />
|
<ClCompile Include="FileSystem.cpp" />
|
||||||
|
<ClCompile Include="Image.cpp" />
|
||||||
<ClCompile Include="MD5Digest.cpp" />
|
<ClCompile Include="MD5Digest.cpp" />
|
||||||
<ClCompile Include="ProgressCallback.cpp" />
|
<ClCompile Include="ProgressCallback.cpp" />
|
||||||
<ClCompile Include="StackWalker.cpp" />
|
<ClCompile Include="StackWalker.cpp" />
|
||||||
|
@ -126,6 +129,7 @@
|
||||||
<ClInclude Include="D3D12\StreamBuffer.h" />
|
<ClInclude Include="D3D12\StreamBuffer.h" />
|
||||||
<ClInclude Include="D3D12\Texture.h" />
|
<ClInclude Include="D3D12\Texture.h" />
|
||||||
<ClInclude Include="D3D12\Util.h" />
|
<ClInclude Include="D3D12\Util.h" />
|
||||||
|
<ClInclude Include="Easing.h" />
|
||||||
<ClInclude Include="boost_spsc_queue.hpp" />
|
<ClInclude Include="boost_spsc_queue.hpp" />
|
||||||
<ClInclude Include="FastJmp.h" />
|
<ClInclude Include="FastJmp.h" />
|
||||||
<ClInclude Include="GL\Context.h" />
|
<ClInclude Include="GL\Context.h" />
|
||||||
|
@ -135,6 +139,7 @@
|
||||||
<ClInclude Include="GL\StreamBuffer.h" />
|
<ClInclude Include="GL\StreamBuffer.h" />
|
||||||
<ClInclude Include="FileSystem.h" />
|
<ClInclude Include="FileSystem.h" />
|
||||||
<ClInclude Include="HashCombine.h" />
|
<ClInclude Include="HashCombine.h" />
|
||||||
|
<ClInclude Include="Image.h" />
|
||||||
<ClInclude Include="LRUCache.h" />
|
<ClInclude Include="LRUCache.h" />
|
||||||
<ClInclude Include="MD5Digest.h" />
|
<ClInclude Include="MD5Digest.h" />
|
||||||
<ClInclude Include="ProgressCallback.h" />
|
<ClInclude Include="ProgressCallback.h" />
|
||||||
|
@ -204,6 +209,9 @@
|
||||||
<ProjectReference Include="..\3rdparty\glslang\glslang.vcxproj">
|
<ProjectReference Include="..\3rdparty\glslang\glslang.vcxproj">
|
||||||
<Project>{ef6834a9-11f3-4331-bc34-21b325abb180}</Project>
|
<Project>{ef6834a9-11f3-4331-bc34-21b325abb180}</Project>
|
||||||
</ProjectReference>
|
</ProjectReference>
|
||||||
|
<ProjectReference Include="..\3rdparty\jpgd\jpgd.vcxproj">
|
||||||
|
<Project>{ed2f21fd-0a36-4a8f-9b90-e7d92a2acb63}</Project>
|
||||||
|
</ProjectReference>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||||
<ImportGroup Label="ExtensionTargets">
|
<ImportGroup Label="ExtensionTargets">
|
||||||
|
|
|
@ -184,6 +184,9 @@
|
||||||
<ClCompile Include="CrashHandler.cpp">
|
<ClCompile Include="CrashHandler.cpp">
|
||||||
<Filter>Source Files</Filter>
|
<Filter>Source Files</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="Image.cpp">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClInclude Include="AlignedMalloc.h">
|
<ClInclude Include="AlignedMalloc.h">
|
||||||
|
@ -432,6 +435,12 @@
|
||||||
<ClInclude Include="LRUCache.h">
|
<ClInclude Include="LRUCache.h">
|
||||||
<Filter>Header Files</Filter>
|
<Filter>Header Files</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
<ClInclude Include="Image.h">
|
||||||
|
<Filter>Header Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="Easing.h">
|
||||||
|
<Filter>Header Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Filter Include="Source Files">
|
<Filter Include="Source Files">
|
||||||
|
|
Loading…
Reference in New Issue