From: Jean-Philippe Bruyère Date: Mon, 9 Aug 2021 08:54:11 +0000 (+0200) Subject: vkvg_surface_write_to_memory, #vkvg_export and #vkvg_inline modifs X-Git-Tag: v0.2.0~59^2~6 X-Git-Url: https://git.osiis.dedyn.io/?a=commitdiff_plain;h=6fc942db46aa97ac0dea8801f5e588093d7fa03c;p=jp%2Fvkvg.git vkvg_surface_write_to_memory, #vkvg_export and #vkvg_inline modifs --- diff --git a/include/vkvg.h b/include/vkvg.h index 217bf1a..a97f2d1 100644 --- a/include/vkvg.h +++ b/include/vkvg.h @@ -67,13 +67,14 @@ extern "C" { #include #ifndef vkvg_public -# if defined (_MSC_VER) && !defined (VKVG_STATIC_BUILD) -# define vkvg_public __declspec(dllimport) -# else -# define vkvg_public -# endif + #if (defined(_WIN32) || defined(_WIN64)) && !defined (VKVG_STATIC_BUILD) + #define vkvg_public __declspec(dllimport) + #else + #define vkvg_public __attribute__((visibility("default"))) + #endif #endif + #define VKVG_LOG_ERR 0x10 #define VKVG_LOG_DEBUG 0x20 #define VKVG_LOG_INFO 0x40 @@ -678,6 +679,13 @@ uint32_t vkvg_surface_get_height (VkvgSurface surf); */ vkvg_public void vkvg_surface_write_to_png (VkvgSurface surf, const char* path); +/** + * @brief Save surface to memory + * @param The surface to save + * @param A valid pointer on cpu memory large enough to contain surface pixels (stride * height) + */ +vkvg_public +void vkvg_surface_write_to_memory (VkvgSurface surf, unsigned char* const bitmap); /** * @brief Explicitly resolve a multisampled surface. * diff --git a/src/cross_mutex.c b/src/cross_mutex.c index 7a33c87..2066f28 100644 --- a/src/cross_mutex.c +++ b/src/cross_mutex.c @@ -24,48 +24,49 @@ int MUTEX_INIT(MUTEX *mutex) { #ifdef _WIN32 - *mutex = CreateMutex(0, FALSE, 0);; - return (*mutex==0); + *mutex = CreateMutex(0, FALSE, 0);; + return (*mutex==0); #elif __APPLE__ #elif __unix__ - return pthread_mutex_init (mutex, NULL); + return pthread_mutex_init (mutex, NULL); #else - return -1; + return -1; #endif } int MUTEX_LOCK(MUTEX *mutex) { #ifdef _WIN32 - return (WaitForSingleObject(*mutex, INFINITE)==WAIT_FAILED?1:0); + return (WaitForSingleObject(*mutex, INFINITE)==WAIT_FAILED?1:0); #elif __APPLE__ #elif __unix__ - return pthread_mutex_lock( mutex ); + return pthread_mutex_lock( mutex ); #else - return -1; + return -1; #endif } int MUTEX_UNLOCK(MUTEX *mutex) { #ifdef _WIN32 - return (ReleaseMutex(*mutex)==0); + return (ReleaseMutex(*mutex)==0); #elif __APPLE__ #elif __unix__ - return pthread_mutex_unlock( mutex ); + return pthread_mutex_unlock( mutex ); #else - return -1; + return -1; #endif } int MUTEX_DESTROY(MUTEX *mutex) { #ifdef _WIN32 - return (CloseHandle(*mutex)==0); + return (CloseHandle(*mutex)==0); #elif __APPLE__ #elif __unix__ - return pthread_mutex_destroy(mutex); + return pthread_mutex_destroy(mutex); #else - return -1; + return -1; #endif } + diff --git a/src/cross_mutex.h b/src/cross_mutex.h index 11635a7..dd86634 100644 --- a/src/cross_mutex.h +++ b/src/cross_mutex.h @@ -24,15 +24,15 @@ //cross platform mutex #ifdef _WIN32 -#include "windows.h" -#include "process.h" -#define MUTEX HANDLE + #include "windows.h" + #include "process.h" + #define MUTEX HANDLE #elif __APPLE__ -#include "pthread.h" -#define MUTEX pthread_mutex_t + #include "pthread.h" + #define MUTEX pthread_mutex_t #elif __unix__ -#include "pthread.h" -#define MUTEX pthread_mutex_t + #include "pthread.h" + #define MUTEX pthread_mutex_t #endif int MUTEX_INIT(MUTEX *mutex); diff --git a/src/cross_os.c b/src/cross_os.c index 1db376c..7385eee 100644 --- a/src/cross_os.c +++ b/src/cross_os.c @@ -28,21 +28,20 @@ int directoryExists (const char* path) { #if defined(_WIN32) || defined(_WIN64) - return getenv("HOME") != NULL; #elif __APPLE__ #elif __unix__ - struct stat st = {0}; - return stat(path, &st)+1; + struct stat st = {0}; + return stat(path, &st)+1; #else - return -1; + return -1; #endif } const char* getUserDir () { #if defined(_WIN32) || defined(_WIN64) - return getenv("HOME"); + return getenv("HOME"); #elif __APPLE__ #elif __unix__ - struct passwd *pw = getpwuid(getuid()); - return pw->pw_dir; + struct passwd *pw = getpwuid(getuid()); + return pw->pw_dir; #endif } diff --git a/src/cross_os.h b/src/cross_os.h index 916aa12..864d8f9 100644 --- a/src/cross_os.h +++ b/src/cross_os.h @@ -28,9 +28,11 @@ #define _CRT_SECURE_NO_WARNINGS #include "windows.h" #define isnanf _isnanf + #define vkvg_inline __forceinline #elif __APPLE__ #include #define isnanf isnan + #define vkvg_inline #elif __unix__ #include #include @@ -38,6 +40,7 @@ #ifndef isnanf #define isnanf __isnanf #endif + #define vkvg_inline static inline __attribute((always_inline)) #endif const char* getUserDir (); diff --git a/src/vkvg_buff.c b/src/vkvg_buff.c index 7e51696..54b02e0 100644 --- a/src/vkvg_buff.c +++ b/src/vkvg_buff.c @@ -24,16 +24,16 @@ #include "vkvg_device_internal.h" void vkvg_buffer_create(VkvgDevice pDev, VkBufferUsageFlags usage, VmaMemoryUsage memoryPropertyFlags, VkDeviceSize size, vkvg_buff *buff){ - buff->pDev = pDev; - VkBufferCreateInfo bufCreateInfo = { - .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, - .usage = usage, .size = size, .sharingMode = VK_SHARING_MODE_EXCLUSIVE}; - VmaAllocationCreateInfo allocInfo = { .usage = memoryPropertyFlags, .flags = VMA_ALLOCATION_CREATE_MAPPED_BIT }; + buff->pDev = pDev; + VkBufferCreateInfo bufCreateInfo = { + .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, + .usage = usage, .size = size, .sharingMode = VK_SHARING_MODE_EXCLUSIVE}; + VmaAllocationCreateInfo allocInfo = { .usage = memoryPropertyFlags, .flags = VMA_ALLOCATION_CREATE_MAPPED_BIT }; - VK_CHECK_RESULT(vmaCreateBuffer (pDev->allocator, &bufCreateInfo, &allocInfo, &buff->buffer, &buff->alloc, &buff->allocInfo)); + VK_CHECK_RESULT(vmaCreateBuffer (pDev->allocator, &bufCreateInfo, &allocInfo, &buff->buffer, &buff->alloc, &buff->allocInfo)); } void vkvg_buffer_destroy(vkvg_buff *buff){ - vmaDestroyBuffer (buff->pDev->allocator, buff->buffer, buff->alloc); + vmaDestroyBuffer (buff->pDev->allocator, buff->buffer, buff->alloc); } diff --git a/src/vkvg_internal.h b/src/vkvg_internal.h index a7402bd..f49e389 100644 --- a/src/vkvg_internal.h +++ b/src/vkvg_internal.h @@ -58,6 +58,7 @@ #define ROUND_DOWN(v,p) (floorf(v * p) / p) #define EQUF(a, b) (fabsf(a-b)<=FLT_EPSILON) + #include "cross_os.h" #include "vectors.h" #include "cross_mutex.h" diff --git a/src/vkvg_pattern.c b/src/vkvg_pattern.c index 92634e4..76dc30e 100644 --- a/src/vkvg_pattern.c +++ b/src/vkvg_pattern.c @@ -79,10 +79,8 @@ uint32_t vkvg_pattern_get_reference_count (VkvgPattern pat) { return pat->references; } void vkvg_pattern_add_color_stop (VkvgPattern pat, float offset, float r, float g, float b, float a) { - if (pat->type == VKVG_PATTERN_TYPE_SURFACE || pat->type == VKVG_PATTERN_TYPE_SOLID){ - + if (pat->type == VKVG_PATTERN_TYPE_SURFACE || pat->type == VKVG_PATTERN_TYPE_SOLID) return; - } vkvg_gradient_t* grad = (vkvg_gradient_t*)pat->data; vkvg_color_t c = {r,g,b,a}; diff --git a/src/vkvg_surface.c b/src/vkvg_surface.c index 19bbaa4..802f75e 100644 --- a/src/vkvg_surface.c +++ b/src/vkvg_surface.c @@ -278,3 +278,44 @@ void vkvg_surface_write_to_png (VkvgSurface surf, const char* path){ vkh_image_unmap (stagImg); vkh_image_destroy (stagImg); } + +void vkvg_surface_write_to_memory (VkvgSurface surf, unsigned char* const bitmap){ + uint32_t stride = surf->width * 4; + VkImageSubresourceLayers imgSubResLayers = {VK_IMAGE_ASPECT_COLOR_BIT,0,0,1}; + VkvgDevice dev = surf->dev; + + //RGBA to blit to, surf img is bgra + VkhImage stagImg= vkh_image_create ((VkhDevice)surf->dev,VK_FORMAT_R8G8B8A8_UNORM,surf->width,surf->height,VK_IMAGE_TILING_LINEAR, + VMA_MEMORY_USAGE_GPU_TO_CPU, + VK_IMAGE_USAGE_TRANSFER_SRC_BIT|VK_IMAGE_USAGE_TRANSFER_DST_BIT); + + VkCommandBuffer cmd = dev->cmd; + _wait_and_reset_device_fence (dev); + + vkh_cmd_begin (cmd, VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT); + vkh_image_set_layout (cmd, stagImg, VK_IMAGE_ASPECT_COLOR_BIT, + VK_IMAGE_LAYOUT_GENERAL, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, + VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT); + vkh_image_set_layout (cmd, surf->img, VK_IMAGE_ASPECT_COLOR_BIT, + VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, + VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT); + + VkImageBlit blit = { + .srcSubresource = imgSubResLayers, + .srcOffsets[1] = {(int32_t)surf->width, (int32_t)surf->height, 1}, + .dstSubresource = imgSubResLayers, + .dstOffsets[1] = {(int32_t)surf->width, (int32_t)surf->height, 1}, + }; + vkCmdBlitImage (cmd, + vkh_image_get_vkimage (surf->img), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, + vkh_image_get_vkimage (stagImg), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &blit, VK_FILTER_NEAREST); + + vkh_cmd_end (cmd); + _submit_cmd (dev, &cmd, dev->fence); + vkWaitForFences (dev->vkDev, 1, &dev->fence, VK_TRUE, UINT64_MAX); + + void* img = vkh_image_map (stagImg); + memcpy(bitmap, img, surf->height * stride); + vkh_image_unmap (stagImg); + vkh_image_destroy (stagImg); +}