#include <stdbool.h>
#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
*/
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.
*
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
}
+
//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);
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
}
#define _CRT_SECURE_NO_WARNINGS
#include "windows.h"
#define isnanf _isnanf
+ #define vkvg_inline __forceinline
#elif __APPLE__
#include <math.h>
#define isnanf isnan
+ #define vkvg_inline
#elif __unix__
#include <unistd.h>
#include <sys/types.h>
#ifndef isnanf
#define isnanf __isnanf
#endif
+ #define vkvg_inline static inline __attribute((always_inline))
#endif
const char* getUserDir ();
#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);
}
#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"
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};
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);
+}