diff --git a/CMakeLists.txt b/CMakeLists.txt index a571ed5..893d023 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -32,6 +32,7 @@ option(OPT_EXTENSIONS "Build extension libraries." ON) option(OPT_TESTS "Build test apps" ON) option(OPT_DEMOS "Build example demos" ON) option(OPT_UNITTEST "Build unit tests" OFF) +option(OPT_SANITIZE "Build with Sanitizer on DEBUG mode" OFF) if (NOT CMAKE_BUILD_TYPE) set(CMAKE_BUILD_TYPE Debug CACHE STRING "Build type" FORCE) diff --git a/build/configs.cmake b/build/configs.cmake index a9aea9a..a335efb 100644 --- a/build/configs.cmake +++ b/build/configs.cmake @@ -9,8 +9,13 @@ if (WIN32) set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} /W3 /WX /Ot /GF /Gm- /GR- /Gy /GL /Zc:wchar_t-") set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /W3 /WX /Ot /GF /Gm- /GR- /Gy /GL /Zc:wchar_t-") elseif (UNIX AND NOT APPLE) - set(CMAKE_C_FLAGS_DEBUG "-D_DEBUG -O0 -Wall -g -Wno-unused-result") - set(CMAKE_CXX_FLAGS_DEBUG "-D_DEBUG -O0 -Wall -g -std=c++11 -fno-rtti -fno-exceptions -Wno-unused-result -Wno-register -Wno-attributes") + if (OPT_SANITIZE) + set(SANITIZE "-fsanitize=address -fsanitize=leak -fsanitize=undefined") + else() + set(SANITIZE "") + endif() + set(CMAKE_C_FLAGS_DEBUG "-D_DEBUG -O0 -Wall -g -Wno-unused-result ${SANITIZE}") + set(CMAKE_CXX_FLAGS_DEBUG "-D_DEBUG -O0 -Wall -g -std=c++11 -fno-rtti -fno-exceptions -Wno-unused-result -Wno-register -Wno-attributes ${SANITIZE}") set(CMAKE_C_FLAGS_RELEASE "-DNDEBUG -O3 -Wall -Wno-unused-result") set(CMAKE_CXX_FLAGS_RELEASE "-DNDEBUG -O3 -Wall -std=c++11 -fno-rtti -fno-exceptions -Wno-unused-result -Wno-register -Wno-attributes") elseif (APPLE) diff --git a/ext/ext.cmake b/ext/ext.cmake index 3d6ad0a..8007cbb 100644 --- a/ext/ext.cmake +++ b/ext/ext.cmake @@ -3,5 +3,5 @@ # Copyright (C) 2024 Zhang Ji Peng # Contact: onecoolx@gmail.com -include (${CMAKE_CURRENT_LIST_DIR}/image_loader/image.cmake) +include (${CMAKE_CURRENT_LIST_DIR}/image_coders/image.cmake) diff --git a/ext/image_coders/apple/apple.cmake b/ext/image_coders/apple/apple.cmake new file mode 100644 index 0000000..185aa5a --- /dev/null +++ b/ext/image_coders/apple/apple.cmake @@ -0,0 +1,24 @@ +# Picasso - a vector graphics library +# +# Copyright (C) 2024 Zhang Ji Peng +# Contact: onecoolx@gmail.com + +set(PXIMAGE_DIR ${PROJECT_ROOT}/ext/image_coders/apple) + +set(PXIMAGE_SOURCES + ${PXIMAGE_DIR}/../psx_image_io.h + ${PXIMAGE_DIR}/../psx_image_io.c + ${PXIMAGE_DIR}/images_module.m +) + +set(LIBX_CGIMAGE psxm_image_cg) + +add_definitions(-DEXPORT) +add_library(${LIBX_CGIMAGE} ${PXIMAGE_SOURCES}) +#target_link_libraries(${LIBX_CGIMAGE} PRIVATE jpeg) +install(TARGETS ${LIBX_CGIMAGE} LIBRARY DESTINATION lib/modules ARCHIVE DESTINATION lib/modules) + +set_target_properties(${LIBX_CGIMAGE} + PROPERTIES + LIBRARY_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/modules" +) diff --git a/ext/image_coders/apple/images_module.m b/ext/image_coders/apple/images_module.m new file mode 100644 index 0000000..82e5fd6 --- /dev/null +++ b/ext/image_coders/apple/images_module.m @@ -0,0 +1,346 @@ +/* Picasso - a vector graphics library + * + * Copyright (C) 2016 Zhang Ji Peng + * Contact: onecoolx@gmail.com + */ + +#include +#include +#include +#include + +#include "picasso_image.h" +#include "picasso_image_plugin.h" + +#include "psx_image_io.h" +#include "psx_color_convert.h" + +#include + +#if TARGET_OS_IPHONE +#include +#include +#elif TARGET_OS_MAC +#include +#endif + +struct cg_image_ctx { + CGImageSourceRef source; + + // write + image_writer_fn writer; + void* writer_param; +}; + +#if 0 +// Represents raw, premultiplied, RGBA image data with tightly packed rows +// (width * 4 bytes). +struct PlatformCGImage +{ + uint32_t width = 0; + uint32_t height = 0; + bool opaque = false; + std::unique_ptr pixels; +}; + +bool cg_image_decode(const uint8_t* encodedBytes, + size_t encodedSizeInBytes, + PlatformCGImage* platformImage) +{ + AutoCF data = + CFDataCreate(kCFAllocatorDefault, encodedBytes, encodedSizeInBytes); + if (!data) + { + return false; + } + + AutoCF source = CGImageSourceCreateWithData(data, nullptr); + if (!source) + { + return false; + } + + AutoCF image = CGImageSourceCreateImageAtIndex(source, 0, nullptr); + if (!image) + { + return false; + } + + bool isOpaque = false; + switch (CGImageGetAlphaInfo(image.get())) + { + case kCGImageAlphaNone: + case kCGImageAlphaNoneSkipFirst: + case kCGImageAlphaNoneSkipLast: + isOpaque = true; + break; + default: + break; + } + + const size_t width = CGImageGetWidth(image); + const size_t height = CGImageGetHeight(image); + const size_t rowBytes = width * 4; // 4 bytes per pixel + const size_t size = rowBytes * height; + + const size_t bitsPerComponent = 8; + CGBitmapInfo cgInfo = kCGBitmapByteOrder32Big; // rgba + if (isOpaque) + { + cgInfo |= kCGImageAlphaNoneSkipLast; + } + else + { + cgInfo |= kCGImageAlphaPremultipliedLast; + } + + std::unique_ptr pixels(new uint8_t[size]); + + AutoCF cs = CGColorSpaceCreateDeviceRGB(); + AutoCF cg = CGBitmapContextCreate( + pixels.get(), width, height, bitsPerComponent, rowBytes, cs, cgInfo); + if (!cg) + { + return false; + } + + CGContextSetBlendMode(cg, kCGBlendModeCopy); + CGContextDrawImage(cg, CGRectMake(0, 0, width, height), image); + + platformImage->width = rive::castTo(width); + platformImage->height = rive::castTo(height); + platformImage->opaque = isOpaque; + platformImage->pixels = std::move(pixels); + + return true; +} + +std::unique_ptr Bitmap::decode(const uint8_t bytes[], size_t byteCount) +{ + PlatformCGImage image; + if (!cg_image_decode(bytes, byteCount, &image)) + { + return nullptr; + } + + // CG only supports premultiplied alpha. Unmultiply now. + size_t imageNumPixels = image.height * image.width; + size_t imageSizeInBytes = imageNumPixels * 4; + // Process 2 pixels at once, deal with odd number of pixels + if (imageNumPixels & 1) + { + imageSizeInBytes -= 4; + } + size_t i; + for (i = 0; i < imageSizeInBytes; i += 8) + { + // Load 2 pixels into 64 bits + auto twoPixels = rive::simd::load(&image.pixels[i]); + auto a0 = twoPixels[3]; + auto a1 = twoPixels[7]; + // Avoid computation if both pixels are either fully transparent or + // opaque pixels + if ((a0 > 0 && a0 < 255) || (a1 > 0 && a1 < 255)) + { + // Avoid potential division by zero + a0 = std::max(a0, 1); + a1 = std::max(a1, 1); + // Cast to 16 bits to avoid overflow + rive::uint16x8 rgbaWidex2 = rive::simd::cast(twoPixels); + // Unpremult: multiply by RGB by "255.0 / alpha" + rgbaWidex2 *= rive::uint16x8{255, 255, 255, 1, 255, 255, 255, 1}; + rgbaWidex2 /= rive::uint16x8{a0, a0, a0, 1, a1, a1, a1, 1}; + // Cast back to 8 bits and store + twoPixels = rive::simd::cast(rgbaWidex2); + rive::simd::store(&image.pixels[i], twoPixels); + } + } + // Process last odd pixel if needed + if (imageNumPixels & 1) + { + // Load 1 pixel into 32 bits + auto rgba = rive::simd::load(&image.pixels[i]); + // Avoid computation for fully transparent or opaque pixels + if (rgba.a > 0 && rgba.a < 255) + { + // Cast to 16 bits to avoid overflow + rive::uint16x4 rgbaWide = rive::simd::cast(rgba); + // Unpremult: multiply by RGB by "255.0 / alpha" + rgbaWide *= rive::uint16x4{255, 255, 255, 1}; + rgbaWide /= rive::uint16x4{rgba.a, rgba.a, rgba.a, 1}; + // Cast back to 8 bits and store + rgba = rive::simd::cast(rgbaWide); + rive::simd::store(&image.pixels[i], rgba); + } + } + + return std::make_unique( + image.width, image.height, PixelFormat::RGBA, std::move(image.pixels)); +} + +#endif + +static int read_image_info(const ps_byte* data, size_t len, psx_image_header* header) +{ + CFDataRef cg_data = CFDataCreate(kCFAllocatorDefault, data, len); + if (!cg_data) { + return -1; + } + + struct cg_image_ctx* ctx = (struct cg_image_ctx*)calloc(1, sizeof(struct cg_image_ctx)); + if (!ctx) { + CFRelease(cg_data); + return -1; // out of memory + } + + ctx->source = CGImageSourceCreateWithData(cg_data, NULL); + + CGImageRef image = CGImageSourceCreateImageAtIndex(ctx->source, 0, NULL); + if (!image) { + CFRelease(ctx->source); + CFRelease(cg_data); + return -1; // out of memory + } + + int bpp = 4; // 4 bytes per pixel + size_t width = CGImageGetWidth(image); + size_t height = CGImageGetHeight(image); + size_t rowbytes = width * bpp; + + header->priv = ctx; + header->width = width; + header->height = height; + header->pitch = rowbytes; + header->depth = 32; + header->bpp = bpp; + header->format = 0; + header->alpha = 1; + header->frames = (int)CGImageSourceGetCount(ctx->source); + + CGImageRelease(image); + CFRelease(cg_data); + return 0; +} + +static int release_read_image_info(psx_image_header* header) +{ + struct cg_image_ctx* ctx = (struct cg_image_ctx*)header->priv; + CFRelease(ctx->source); + free(ctx); + return 0; +} + +static int decode_image_data(psx_image_header* header, const psx_image* image, psx_image_frame* frame, int idx, ps_byte* buffer, size_t buffer_len) +{ + struct cg_image_ctx* ctx = (struct cg_image_ctx*)header->priv; + + int width = header->width; + int height = header->height; + + size_t bitsPerComponent = 8; + CGBitmapInfo cgInfo = kCGBitmapByteOrder32Big | kCGImageAlphaNoneSkipLast; + + CGColorSpaceRef cs = CGColorSpaceCreateDeviceRGB(); + CGContextRef cg = CGBitmapContextCreate(buffer, width, height, bitsPerComponent, header->rowbytes, cs, cgInfo); + if (!cg) { + CGColorSpaceRelease(cs); + return -1; + } + + CGImageRef image = CGImageSourceCreateImageAtIndex(ctx->source, idx, NULL); + + CGContextSetBlendMode(cg, kCGBlendModeCopy); + CGContextDrawImage(cg, CGRectMake(0, 0, width, height), image); + + CGImageRelease(image); + CGContextRelease(cg) + CGColorSpaceRelease(cs); + return 0; +} + + + + + +static int write_image_info(const psx_image* image, image_writer_fn func, void* param, float quality, psx_image_header* header) +{ +} + +static int release_write_image_info(psx_image_header* header) +{ +} + +static int encode_image_data(psx_image_header* header, const psx_image* image, psx_image_frame* frame, + int idx, const ps_byte* buffer, size_t buffer_len, int* ret) +{ +} + +static psx_image_operator * cg_coder = NULL; +static module_handle lib_image = INVALID_HANDLE; + +typedef int (*register_func)(const char*, const ps_byte*, size_t, size_t, psx_priority_level, psx_image_operator*); +typedef int (*unregister_func)(psx_image_operator*); + +void psx_image_module_init(void) +{ + register_func func = NULL; + + lib_image = _module_load("libpsx_image.so"); + if (lib_image == INVALID_HANDLE) + return; + + func = _module_get_symbol(lib_image, "psx_image_register_operator"); + if (!func) + return; + + cg_coder = (psx_image_operator*)calloc(1, sizeof(psx_image_operator)); + if (!jpg_coder) + return; + + cg_coder->read_header_info = read_image_info; + cg_coder->decode_image_data = decode_image_data; + cg_coder->release_read_header_info = release_read_image_info; + + cg_coder->write_header_info = write_image_info; + cg_coder->encode_image_data = encode_image_data; + cg_coder->release_write_header_info = release_write_image_info; + + func("jpg", (ps_byte*)"\xFF\xD8\xFF", 0, 3, PRIORITY_DEFAULT, cg_coder); + func("jpeg", (ps_byte*)"\xFF\xD8\xFF", 0, 3, PRIORITY_DEFAULT, cg_coder); + //func("jpeg2k", (ps_byte*)"\xFF\xD8\xFF", 0, 3, PRIORITY_DEFAULT, cg_coder); + //func("tiff", (ps_byte*)"\xFF\xD8\xFF", 0, 3, PRIORITY_DEFAULT, cg_coder); + //func("pict", (ps_byte*)"\xFF\xD8\xFF", 0, 3, PRIORITY_DEFAULT, cg_coder); + //func("qtif", (ps_byte*)"\xFF\xD8\xFF", 0, 3, PRIORITY_DEFAULT, cg_coder); + func("png", (ps_byte*)"\x89\x50\x4E\x47\x0D\x0A\x1A\x0A", 0, 8, PRIORITY_DEFAULT, cg_coder); + func("gif", (ps_byte*)"GIF", 0, 3, PRIORITY_DEFAULT, cg_coder); +} + +void psx_image_module_shutdown(void) +{ + unregister_func func = NULL; + + func = _module_get_symbol(lib_image, "psx_image_unregister_operator"); + if (func) { + if (cg_coder) { + func(cg_coder); //jpg + func(cg_coder); //jpeg + func(cg_coder); //png + func(cg_coder); //gif + free(cg_coder); + } + } + + if (lib_image != INVALID_HANDLE) + _module_unload(lib_image); +} + +const char* psx_image_module_get_string(int idx) +{ + switch (idx) { + case MODULE_NAME: + return "apple"; + default: + return "unknown"; + } +} + diff --git a/ext/image_loader/gif/gif.cmake b/ext/image_coders/gif/gif.cmake similarity index 91% rename from ext/image_loader/gif/gif.cmake rename to ext/image_coders/gif/gif.cmake index d6e85d6..d9fc13f 100644 --- a/ext/image_loader/gif/gif.cmake +++ b/ext/image_coders/gif/gif.cmake @@ -3,7 +3,7 @@ # Copyright (C) 2024 Zhang Ji Peng # Contact: onecoolx@gmail.com -set(PXGIF_DIR ${PROJECT_ROOT}/ext/image_loader/gif) +set(PXGIF_DIR ${PROJECT_ROOT}/ext/image_coders/gif) set(PXGIF_SOURCES ${PXGIF_DIR}/../psx_image_io.h diff --git a/ext/image_loader/gif/gif_module.c b/ext/image_coders/gif/gif_module.c similarity index 99% rename from ext/image_loader/gif/gif_module.c rename to ext/image_coders/gif/gif_module.c index 277f5ed..24ce547 100644 --- a/ext/image_loader/gif/gif_module.c +++ b/ext/image_coders/gif/gif_module.c @@ -581,7 +581,7 @@ static int release_write_gif_info(psx_image_header* header) return 0; } -psx_image_operator * gif_coder = NULL; +static psx_image_operator * gif_coder = NULL; static module_handle lib_image = INVALID_HANDLE; typedef int (*register_func)(const char*, const ps_byte*, size_t, size_t, psx_priority_level, psx_image_operator*); diff --git a/ext/image_loader/image.cmake b/ext/image_coders/image.cmake similarity index 96% rename from ext/image_loader/image.cmake rename to ext/image_coders/image.cmake index bb4e53e..874befa 100644 --- a/ext/image_loader/image.cmake +++ b/ext/image_coders/image.cmake @@ -3,7 +3,7 @@ # Copyright (C) 2024 Zhang Ji Peng # Contact: onecoolx@gmail.com -set(PXIMG_DIR ${PROJECT_ROOT}/ext/image_loader) +set(PXIMG_DIR ${PROJECT_ROOT}/ext/image_coders) set(PXIMG_SOURCES ${PXIMG_DIR}/psx_list.h diff --git a/ext/image_loader/jpeg/jpeg.cmake b/ext/image_coders/jpeg/jpeg.cmake similarity index 91% rename from ext/image_loader/jpeg/jpeg.cmake rename to ext/image_coders/jpeg/jpeg.cmake index b7cec2e..249ca36 100644 --- a/ext/image_loader/jpeg/jpeg.cmake +++ b/ext/image_coders/jpeg/jpeg.cmake @@ -3,7 +3,7 @@ # Copyright (C) 2024 Zhang Ji Peng # Contact: onecoolx@gmail.com -set(PXJPEG_DIR ${PROJECT_ROOT}/ext/image_loader/jpeg) +set(PXJPEG_DIR ${PROJECT_ROOT}/ext/image_coders/jpeg) set(PXJPEG_SOURCES ${PXJPEG_DIR}/../psx_image_io.h diff --git a/ext/image_loader/jpeg/jpeg_module.c b/ext/image_coders/jpeg/jpeg_module.c similarity index 99% rename from ext/image_loader/jpeg/jpeg_module.c rename to ext/image_coders/jpeg/jpeg_module.c index c3a265d..b07ff41 100644 --- a/ext/image_loader/jpeg/jpeg_module.c +++ b/ext/image_coders/jpeg/jpeg_module.c @@ -27,7 +27,7 @@ struct jpeg_error_pub { struct jpeg_write_pub { struct jpeg_destination_mgr dst; - unsigned char buffer[256]; + uint8_t buffer[256]; image_writer_fn writer; void* writer_param; }; @@ -354,7 +354,7 @@ static int release_write_jpg_info(psx_image_header* header) return 0; } -psx_image_operator * jpg_coder = NULL; +static psx_image_operator * jpg_coder = NULL; static module_handle lib_image = INVALID_HANDLE; typedef int (*register_func)(const char*, const ps_byte*, size_t, size_t, psx_priority_level, psx_image_operator*); diff --git a/ext/image_loader/png/png.cmake b/ext/image_coders/png/png.cmake similarity index 91% rename from ext/image_loader/png/png.cmake rename to ext/image_coders/png/png.cmake index 658937f..681b649 100644 --- a/ext/image_loader/png/png.cmake +++ b/ext/image_coders/png/png.cmake @@ -3,7 +3,7 @@ # Copyright (C) 2024 Zhang Ji Peng # Contact: onecoolx@gmail.com -set(PXPNG_DIR ${PROJECT_ROOT}/ext/image_loader/png) +set(PXPNG_DIR ${PROJECT_ROOT}/ext/image_coders/png) set(PXPNG_SOURCES ${PXPNG_DIR}/../psx_image_io.h diff --git a/ext/image_loader/png/png_module.c b/ext/image_coders/png/png_module.c similarity index 99% rename from ext/image_loader/png/png_module.c rename to ext/image_coders/png/png_module.c index b4d0bda..8ba4b03 100644 --- a/ext/image_loader/png/png_module.c +++ b/ext/image_coders/png/png_module.c @@ -353,7 +353,7 @@ static int encode_png_data(psx_image_header* header, const psx_image* image, psx return 0; } -psx_image_operator * png_coder = NULL; +static psx_image_operator * png_coder = NULL; static module_handle lib_image = INVALID_HANDLE; typedef int (*register_func)(const char*, const ps_byte*, size_t, size_t, psx_priority_level, psx_image_operator*); diff --git a/ext/image_loader/psx_color_convert.h b/ext/image_coders/psx_color_convert.h similarity index 100% rename from ext/image_loader/psx_color_convert.h rename to ext/image_coders/psx_color_convert.h diff --git a/ext/image_loader/psx_image.def b/ext/image_coders/psx_image.def similarity index 100% rename from ext/image_loader/psx_image.def rename to ext/image_coders/psx_image.def diff --git a/ext/image_loader/psx_image.rc b/ext/image_coders/psx_image.rc similarity index 100% rename from ext/image_loader/psx_image.rc rename to ext/image_coders/psx_image.rc diff --git a/ext/image_loader/psx_image_io.c b/ext/image_coders/psx_image_io.c similarity index 98% rename from ext/image_loader/psx_image_io.c rename to ext/image_coders/psx_image_io.c index 20c5421..6719e7c 100644 --- a/ext/image_loader/psx_image_io.c +++ b/ext/image_coders/psx_image_io.c @@ -219,6 +219,12 @@ char* _module_get_modules_dir(char* path_buffer, size_t buffer_size) char* path_seek = NULL; size_t length = 0; + + lib_paths = (char*)getenv("PS_IMAGE_MODULES_DIR"); + if (lib_paths) { + return lib_paths; + } + if ((stat("/usr/lib/modules", &info) == 0) && S_ISDIR(info.st_mode)){ if (buffer_size > 24) { strncpy(path_buffer, "/usr/lib/modules/", buffer_size); diff --git a/ext/image_loader/psx_image_io.h b/ext/image_coders/psx_image_io.h similarity index 100% rename from ext/image_loader/psx_image_io.h rename to ext/image_coders/psx_image_io.h diff --git a/ext/image_loader/psx_image_loader.c b/ext/image_coders/psx_image_loader.c similarity index 100% rename from ext/image_loader/psx_image_loader.c rename to ext/image_coders/psx_image_loader.c diff --git a/ext/image_loader/psx_image_loader.h b/ext/image_coders/psx_image_loader.h similarity index 100% rename from ext/image_loader/psx_image_loader.h rename to ext/image_coders/psx_image_loader.h diff --git a/ext/image_loader/psx_image_modules.c b/ext/image_coders/psx_image_modules.c similarity index 99% rename from ext/image_loader/psx_image_modules.c rename to ext/image_coders/psx_image_modules.c index df7a003..50ba6a9 100644 --- a/ext/image_loader/psx_image_modules.c +++ b/ext/image_coders/psx_image_modules.c @@ -70,7 +70,6 @@ int modules_init(struct image_modules_mgr* mgr) return 0; } - void modules_destroy(struct image_modules_mgr* mgr) { size_t i = 0; diff --git a/ext/image_loader/psx_image_modules.h b/ext/image_coders/psx_image_modules.h similarity index 100% rename from ext/image_loader/psx_image_modules.h rename to ext/image_coders/psx_image_modules.h diff --git a/ext/image_loader/psx_list.h b/ext/image_coders/psx_list.h similarity index 100% rename from ext/image_loader/psx_list.h rename to ext/image_coders/psx_list.h diff --git a/ext/image_loader/resource.h b/ext/image_coders/resource.h similarity index 100% rename from ext/image_loader/resource.h rename to ext/image_coders/resource.h diff --git a/ext/image_loader/webp/webp.cmake b/ext/image_coders/webp/webp.cmake similarity index 91% rename from ext/image_loader/webp/webp.cmake rename to ext/image_coders/webp/webp.cmake index 0a2a1a5..8f82df1 100644 --- a/ext/image_loader/webp/webp.cmake +++ b/ext/image_coders/webp/webp.cmake @@ -3,7 +3,7 @@ # Copyright (C) 2024 Zhang Ji Peng # Contact: onecoolx@gmail.com -set(PXWEBP_DIR ${PROJECT_ROOT}/ext/image_loader/webp) +set(PXWEBP_DIR ${PROJECT_ROOT}/ext/image_coders/webp) set(PXWEBP_SOURCES ${PXWEBP_DIR}/../psx_image_io.h diff --git a/ext/image_loader/webp/webp_module.c b/ext/image_coders/webp/webp_module.c similarity index 99% rename from ext/image_loader/webp/webp_module.c rename to ext/image_coders/webp/webp_module.c index dc607bb..cd97995 100644 --- a/ext/image_loader/webp/webp_module.c +++ b/ext/image_coders/webp/webp_module.c @@ -324,7 +324,7 @@ static int release_write_webp_info(psx_image_header* header) return 0; } -psx_image_operator * webp_coder = NULL; +static psx_image_operator * webp_coder = NULL; static module_handle lib_image = INVALID_HANDLE; typedef int (*register_func)(const char*, const ps_byte*, size_t, size_t, psx_priority_level, psx_image_operator*); diff --git a/ext/image_loader/apple/apple.cmake b/ext/image_loader/apple/apple.cmake deleted file mode 100644 index e69de29..0000000 diff --git a/src/picasso_font_api.cpp b/src/picasso_font_api.cpp index 8e02b68..3985d25 100644 --- a/src/picasso_font_api.cpp +++ b/src/picasso_font_api.cpp @@ -427,7 +427,7 @@ void PICAPI ps_draw_text(ps_context* ctx, const ps_rect* area, const void* text, // draw the text if (ctx->state->font->desc.charset() == CHARSET_ANSI) { const char* p = (const char*)text; - while (*p && len) { + while (len && *p) { _REGISTER_ char c = *p; const picasso::glyph* glyph = ctx->fonts->current_font()->get_glyph(c); if (glyph) { @@ -446,7 +446,7 @@ void PICAPI ps_draw_text(ps_context* ctx, const ps_rect* area, const void* text, } } else { const ps_uchar16* p = (const ps_uchar16*)text; - while (*p && len) { + while (len && *p) { _REGISTER_ ps_uchar16 c = *p; const picasso::glyph* glyph = ctx->fonts->current_font()->get_glyph(c); if (glyph) { diff --git a/test/alpha_func.c b/test/alpha_func.c index 54eb96b..5be3eac 100644 --- a/test/alpha_func.c +++ b/test/alpha_func.c @@ -85,6 +85,7 @@ void set_pattern_data(unsigned char* data, ps_color_format fmt, int w, int h, in { ps_image* pam = ps_image_create_with_data(data, fmt, w, h, p); pt = ps_pattern_create_image(pam, WRAP_TYPE_REPEAT, WRAP_TYPE_REPEAT, pm); + ps_image_unref(pam); } void timer_action(ps_context* gc) diff --git a/test/bitblt_func.c b/test/bitblt_func.c index f74f929..a3654e0 100644 --- a/test/bitblt_func.c +++ b/test/bitblt_func.c @@ -58,6 +58,7 @@ void set_pattern_data(unsigned char* data, ps_color_format fmt, int w, int h, in { ps_image* pam = ps_image_create_with_data(data, fmt, w, h, p); pt = ps_pattern_create_image(pam, WRAP_TYPE_REPEAT, WRAP_TYPE_REPEAT, pm); + ps_image_unref(pam); } void timer_action(ps_context* gc) diff --git a/test/blur_func.c b/test/blur_func.c index b6fea78..1048c36 100644 --- a/test/blur_func.c +++ b/test/blur_func.c @@ -68,6 +68,7 @@ void set_pattern_data(unsigned char* data, ps_color_format fmt, int w, int h, in { ps_image* pam = ps_image_create_with_data(data, fmt, w, h, p); pt = ps_pattern_create_image(pam, WRAP_TYPE_REPEAT, WRAP_TYPE_REPEAT, pm); + ps_image_unref(pam); } void timer_action(ps_context* gc) diff --git a/test/clip_func.c b/test/clip_func.c index 691d54f..48eea35 100644 --- a/test/clip_func.c +++ b/test/clip_func.c @@ -93,6 +93,7 @@ void set_pattern_data(unsigned char* data, ps_color_format fmt, int w, int h, in { ps_image* pam = ps_image_create_with_data(data, fmt, w, h, p); pt = ps_pattern_create_image(pam, WRAP_TYPE_REPEAT, WRAP_TYPE_REPEAT, pm); + ps_image_unref(pam); } void timer_action(ps_context* gc) diff --git a/test/composite_func.c b/test/composite_func.c index 926b895..2c57ac5 100644 --- a/test/composite_func.c +++ b/test/composite_func.c @@ -57,6 +57,7 @@ void set_pattern_data(unsigned char* data, ps_color_format fmt, int w, int h, in { ps_image* pam = ps_image_create_with_data(data, fmt, w, h, p); pt = ps_pattern_create_image(pam, WRAP_TYPE_REPEAT, WRAP_TYPE_REPEAT, pm); + ps_image_unref(pam); } void timer_action(ps_context* gc) diff --git a/test/gamma_func.c b/test/gamma_func.c index af497e5..c71e002 100644 --- a/test/gamma_func.c +++ b/test/gamma_func.c @@ -99,6 +99,7 @@ void set_pattern_data(unsigned char* data, ps_color_format fmt, int w, int h, in { ps_image* pam = ps_image_create_with_data(data, fmt, w, h, p); pt = ps_pattern_create_image(pam, WRAP_TYPE_REPEAT, WRAP_TYPE_REPEAT, pm); + ps_image_unref(pam); } void timer_action(ps_context* gc) diff --git a/test/gcstate_func.c b/test/gcstate_func.c index c426101..b43df7a 100644 --- a/test/gcstate_func.c +++ b/test/gcstate_func.c @@ -89,6 +89,7 @@ void set_pattern_data(unsigned char* data, ps_color_format fmt, int w, int h, in { ps_image* pam = ps_image_create_with_data(data, fmt, w, h, p); pt = ps_pattern_create_image(pam, WRAP_TYPE_REPEAT, WRAP_TYPE_REPEAT, pm); + ps_image_unref(pam); } void timer_action(ps_context* gc) diff --git a/test/mask_func.c b/test/mask_func.c index 72ba4ed..0d182c9 100644 --- a/test/mask_func.c +++ b/test/mask_func.c @@ -69,6 +69,7 @@ void set_pattern_data(unsigned char* data, ps_color_format fmt, int w, int h, in { ps_image* pam = ps_image_create_with_data(data, fmt, w, h, p); pt = ps_pattern_create_image(pam, WRAP_TYPE_REPEAT, WRAP_TYPE_REPEAT, pm); + ps_image_unref(pam); } void timer_action(ps_context* gc) diff --git a/test/part_func.c b/test/part_func.c index e9532fe..d60dbf2 100644 --- a/test/part_func.c +++ b/test/part_func.c @@ -56,6 +56,7 @@ void set_pattern_data(unsigned char* data, ps_color_format fmt, int w, int h, in { ps_image* pam = ps_image_create_with_data(data, fmt, w, h, p); pt = ps_pattern_create_image(pam, WRAP_TYPE_REPEAT, WRAP_TYPE_REPEAT, pm); + ps_image_unref(pam); } void timer_action(ps_context* gc) diff --git a/test/path_func.c b/test/path_func.c index 826e6c5..d54f6f5 100644 --- a/test/path_func.c +++ b/test/path_func.c @@ -78,6 +78,7 @@ void set_pattern_data(unsigned char* data, ps_color_format fmt, int w, int h, in { ps_image* pam = ps_image_create_with_data(data, fmt, w, h, p); pt = ps_pattern_create_image(pam, WRAP_TYPE_REPEAT, WRAP_TYPE_REPEAT, pm); + ps_image_unref(pam); } void timer_action(ps_context* gc) diff --git a/test/pattern_func.c b/test/pattern_func.c index 6053675..2910b1a 100644 --- a/test/pattern_func.c +++ b/test/pattern_func.c @@ -71,6 +71,7 @@ void set_pattern_data(unsigned char* data, ps_color_format fmt, int w, int h, in pt2 = ps_pattern_create_image(pam, WRAP_TYPE_REPEAT, WRAP_TYPE_REFLECT, pm); pt3 = ps_pattern_create_image(pam, WRAP_TYPE_REFLECT, WRAP_TYPE_REPEAT, pm); pt4 = ps_pattern_create_image(pam, WRAP_TYPE_REFLECT, WRAP_TYPE_REFLECT, pm); + ps_image_unref(pam); } void timer_action(ps_context* gc) diff --git a/test/shadow_func.c b/test/shadow_func.c index bd4d273..154e2d0 100644 --- a/test/shadow_func.c +++ b/test/shadow_func.c @@ -87,6 +87,7 @@ void set_pattern_data(unsigned char* data, ps_color_format fmt, int w, int h, in { ps_image* pam = ps_image_create_with_data(data, fmt, w, h, p); pt = ps_pattern_create_image(pam, WRAP_TYPE_REPEAT, WRAP_TYPE_REPEAT, pm); + ps_image_unref(pam); } void timer_action(ps_context* gc) diff --git a/test/text_func.c b/test/text_func.c index 2e50449..73a0590 100644 --- a/test/text_func.c +++ b/test/text_func.c @@ -165,6 +165,7 @@ void set_pattern_data(unsigned char* data, ps_color_format fmt, int w, int h, in { ps_image* pam = ps_image_create_with_data(data, fmt, w, h, p); pt = ps_pattern_create_image(pam, WRAP_TYPE_REPEAT, WRAP_TYPE_REPEAT, pm); + ps_image_unref(pam); } void timer_action(ps_context* gc) diff --git a/test/thread_func.c b/test/thread_func.c index 6af0ebc..1c63885 100644 --- a/test/thread_func.c +++ b/test/thread_func.c @@ -71,6 +71,7 @@ void set_pattern_data(unsigned char* data, ps_color_format fmt, int w, int h, in { ps_image* pam = ps_image_create_with_data(data, fmt, w, h, p); pt = ps_pattern_create_image(pam, WRAP_TYPE_REPEAT, WRAP_TYPE_REPEAT, pm); + ps_image_unref(pam); //start thread work! diff --git a/test/timeuse.h b/test/timeuse.h index 9ad50a8..368be14 100644 --- a/test/timeuse.h +++ b/test/timeuse.h @@ -50,4 +50,49 @@ static inline double get_clock_used_ms(LARGE_INTEGER t1, LARGE_INTEGER t2) #endif +#if defined(ARM) +static inline uint64_t arm_rdtsc(void) +{ + uint64_t tsc; + asm volatile("mrs %0, cntvct_el0" : "=r"(tsc)); + return tsc; +} + +static inline uint64_t +arm64_cntfrq(void) +{ + uint64_t freq; + asm volatile("mrs %0, cntfrq_el0" : "=r" (freq)); + return freq; +} + +static inline uint64_t +arm64_pmccntr(void) +{ + uint64_t tsc; + asm volatile("mrs %0, pmccntr_el0" : "=r"(tsc)); + return tsc; +} + +static inline uint64_t +rdtsc(void) +{ + return arm64_pmccntr(); +} + +static void enable_pmu_pmccntr(void) +{ + u64 val = 0; + asm volatile("msr pmintenset_el1, %0" : : "r" ((u64)(0 << 31))); + asm volatile("msr pmcntenset_el0, %0" :: "r" ((u64)(1 << 31))); + asm volatile("msr pmuserenr_el0, %0" : : "r"((u64)(1 << 0) | (u64)(1 << 2))); + asm volatile("mrs %0, pmcr_el0" : "=r" (val)); + val |= ((u64)(1 << 0) | (u64)(1 << 2)); + isb(); + asm volatile("msr pmcr_el0, %0" : : "r" (val)); +} +#endif + + + #endif