]> O.S.I.I.S - jp/vkvg.git/commitdiff
solid fill & stroke
authorJean-Philippe Bruyère <jp_bruyere@hotmail.com>
Wed, 15 Jul 2020 14:41:03 +0000 (16:41 +0200)
committerj-p <jp_bruyere@hotmail.com>
Wed, 22 Jul 2020 15:14:28 +0000 (17:14 +0200)
12 files changed:
shaders/vkvg.frag [new file with mode: 0644]
shaders/vkvg_main.frag
shaders/vkvg_main.vert
shaders/vkvg_text.frag [new file with mode: 0644]
shaders/vkvg_text.vert [new file with mode: 0644]
src/vkvg_context.c
src/vkvg_context_internal.c
src/vkvg_context_internal.h
src/vkvg_device.c
src/vkvg_device_internal.c
src/vkvg_device_internal.h
src/vkvg_fonts.c

diff --git a/shaders/vkvg.frag b/shaders/vkvg.frag
new file mode 100644 (file)
index 0000000..9a28203
--- /dev/null
@@ -0,0 +1,95 @@
+/*
+ * Copyright (c) 2018 Jean-Philippe Bruyère <jp_bruyere@hotmail.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
+ * Software, and to permit persons to whom the Software is furnished to do so, subject
+ * to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+#version 450
+
+#extension GL_ARB_separate_shader_objects      : enable
+#extension GL_ARB_shading_language_420pack     : enable
+
+layout (set=0, binding = 0) uniform sampler2DArray fontMap;
+layout (set=1, binding = 0) uniform sampler2D          source;
+layout (set=2, binding = 0) uniform _uboGrad {
+       vec4    cp[3];
+       vec4    colors[16];
+       vec4    stops[16];
+       uint    count;
+}uboGrad;
+
+layout (location = 0) in vec3  inFontUV;               //if it is a text drawing, inFontUV.z hold fontMap layer
+layout (location = 1) in vec4  inSrc;                  //source bounds or color depending on pattern type
+layout (location = 2) in flat int inPatType;   //pattern type
+layout (location = 3) in mat3x2 inMat;
+
+layout (location = 0) out vec4 outFragColor;
+
+layout (constant_id = 0) const int NUM_SAMPLES = 8;
+
+
+#define SOLID                  0
+#define SURFACE                        1
+#define LINEAR                 2
+#define RADIAL                 3
+#define MESH                   4
+#define RASTER_SOURCE  5
+
+void main()
+{
+       vec4 c = vec4(0);
+       switch(inPatType){
+       case SOLID:
+               c = inSrc;
+               break;
+       case SURFACE:
+               vec2 p = (gl_FragCoord.xy - inSrc.xy);
+               vec2 uv = vec2(
+                       inMat[0][0] * p.x + inMat[1][0] * p.y + inMat[2][0],
+                       inMat[0][1] * p.x + inMat[1][1] * p.y + inMat[2][1]
+               );
+               c = texture (source, uv / inSrc.zw);
+               break;
+       case LINEAR:
+               //credit to Nikita Rokotyan for linear grad
+               float  alpha = atan( -uboGrad.cp[1].y + uboGrad.cp[0].y, uboGrad.cp[1].x - uboGrad.cp[0].x );
+               float  gradientStartPosRotatedX = uboGrad.cp[0].x*cos(alpha) - uboGrad.cp[0].y*sin(alpha);
+               float  gradientEndPosRotatedX   = uboGrad.cp[1].x*cos(alpha) - uboGrad.cp[1].y*sin(alpha);
+               float  d = gradientEndPosRotatedX - gradientStartPosRotatedX;
+
+               float y = gl_FragCoord.y;//inSrc.y - gl_FragCoord.y;
+               float x = gl_FragCoord.x;
+               float xLocRotated = x*cos( alpha ) - y*sin( alpha );
+
+               c = mix(uboGrad.colors[0], uboGrad.colors[1], smoothstep( gradientStartPosRotatedX + uboGrad.stops[0].r*d, gradientStartPosRotatedX + uboGrad.stops[1].r*d, xLocRotated ) );
+               for ( int i=1; i<uboGrad.count-1; ++i )
+                       c = mix(c, uboGrad.colors[i+1], smoothstep( gradientStartPosRotatedX + uboGrad.stops[i].r*d, gradientStartPosRotatedX + uboGrad.stops[i+1].r*d, xLocRotated ) );
+               break;
+       case RADIAL:
+               break;
+       }
+
+       if (inFontUV.z >= 0.0)
+               c *= texture(fontMap, inFontUV);
+
+       outFragColor = c;
+}
+
+void op_CLEAR () {
+       outFragColor = vec4 (0);
+}
index 6649582097ac5f6a1cca22627218d81bf11ce603..c0766600a4213122030a36b5e1cd0604e2e71ee8 100644 (file)
 #extension GL_ARB_separate_shader_objects      : enable
 #extension GL_ARB_shading_language_420pack     : enable
 
-layout (set=0, binding = 0) uniform sampler2DArray fontMap;
-layout (set=1, binding = 0) uniform sampler2D source;
-layout (set=2, binding = 0) uniform _uboGrad {
+layout (set=0, binding = 0) uniform sampler2D source;
+layout (set=1, binding = 0) uniform _uboGrad {
        vec4    cp[3];
        vec4    colors[16];
        vec4    stops[16];
        uint    count;
 }uboGrad;
 
-layout (location = 0) in vec3  inFontUV;               //if it is a text drawing, inFontUV.z hold fontMap layer
-layout (location = 1) in vec4  inSrc;                  //source bounds or color
-layout (location = 2) in flat int inPatType;
-layout (location = 3) in mat3x2 inMat;
+layout (location = 0) in vec4  inSrc;                  //source bounds or color
+layout (location = 1) in flat int inPatType;
+layout (location = 2) in mat3x2 inMat;
 
 layout (location = 0) out vec4 outFragColor;
 
@@ -83,9 +81,6 @@ void main()
                break;
        }
 
-       if (inFontUV.z >= 0.0)
-               c *= texture(fontMap, inFontUV).r;
-
        outFragColor = c;
 }
 
index 28267134e359b588059b22263257e4fa5870e807..7bd6cf29a91c175793e23e7310c393eb9cbb1f80 100644 (file)
 #extension GL_ARB_shading_language_420pack : enable
 
 layout (location = 0) in vec2  inPos;
-layout (location = 1) in vec3  inUV;
+layout (location = 1) in vec4  inColor;
 
-layout (location = 0) out vec3 outUV;
-layout (location = 1) out vec4 outSrc;
-layout (location = 2) out flat int outPatType;
-layout (location = 3) out mat3x2 outMat;
+layout (location = 0) out vec4 outSrc;
+layout (location = 1) out flat int outPatType;
+layout (location = 2) out mat3x2 outMat;
 
 out gl_PerVertex
 {
@@ -56,17 +55,14 @@ layout(push_constant) uniform PushConsts {
 void main()
 {
        outPatType      = pc.srcType;
-       outSrc          = pc.source;
+       outSrc          = pc.srcType == SOLID ? inColor : pc.source;
        outMat          = pc.matInv;
 
        if (pc.fullScreenQuad != 0) {
                gl_Position = vec4(vec2((gl_VertexIndex << 1) & 2, gl_VertexIndex & 2) * 2.0f - 1.0f, 0.0f, 1.0f);
-               outUV = vec3(0,0,-1);
                return;
        }
 
-       outUV = inUV;
-
        vec2 p = vec2(
                pc.mat[0][0] * inPos.x + pc.mat[1][0] * inPos.y + pc.mat[2][0],
                pc.mat[0][1] * inPos.x + pc.mat[1][1] * inPos.y + pc.mat[2][1]
diff --git a/shaders/vkvg_text.frag b/shaders/vkvg_text.frag
new file mode 100644 (file)
index 0000000..9a28203
--- /dev/null
@@ -0,0 +1,95 @@
+/*
+ * Copyright (c) 2018 Jean-Philippe Bruyère <jp_bruyere@hotmail.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
+ * Software, and to permit persons to whom the Software is furnished to do so, subject
+ * to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+#version 450
+
+#extension GL_ARB_separate_shader_objects      : enable
+#extension GL_ARB_shading_language_420pack     : enable
+
+layout (set=0, binding = 0) uniform sampler2DArray fontMap;
+layout (set=1, binding = 0) uniform sampler2D          source;
+layout (set=2, binding = 0) uniform _uboGrad {
+       vec4    cp[3];
+       vec4    colors[16];
+       vec4    stops[16];
+       uint    count;
+}uboGrad;
+
+layout (location = 0) in vec3  inFontUV;               //if it is a text drawing, inFontUV.z hold fontMap layer
+layout (location = 1) in vec4  inSrc;                  //source bounds or color depending on pattern type
+layout (location = 2) in flat int inPatType;   //pattern type
+layout (location = 3) in mat3x2 inMat;
+
+layout (location = 0) out vec4 outFragColor;
+
+layout (constant_id = 0) const int NUM_SAMPLES = 8;
+
+
+#define SOLID                  0
+#define SURFACE                        1
+#define LINEAR                 2
+#define RADIAL                 3
+#define MESH                   4
+#define RASTER_SOURCE  5
+
+void main()
+{
+       vec4 c = vec4(0);
+       switch(inPatType){
+       case SOLID:
+               c = inSrc;
+               break;
+       case SURFACE:
+               vec2 p = (gl_FragCoord.xy - inSrc.xy);
+               vec2 uv = vec2(
+                       inMat[0][0] * p.x + inMat[1][0] * p.y + inMat[2][0],
+                       inMat[0][1] * p.x + inMat[1][1] * p.y + inMat[2][1]
+               );
+               c = texture (source, uv / inSrc.zw);
+               break;
+       case LINEAR:
+               //credit to Nikita Rokotyan for linear grad
+               float  alpha = atan( -uboGrad.cp[1].y + uboGrad.cp[0].y, uboGrad.cp[1].x - uboGrad.cp[0].x );
+               float  gradientStartPosRotatedX = uboGrad.cp[0].x*cos(alpha) - uboGrad.cp[0].y*sin(alpha);
+               float  gradientEndPosRotatedX   = uboGrad.cp[1].x*cos(alpha) - uboGrad.cp[1].y*sin(alpha);
+               float  d = gradientEndPosRotatedX - gradientStartPosRotatedX;
+
+               float y = gl_FragCoord.y;//inSrc.y - gl_FragCoord.y;
+               float x = gl_FragCoord.x;
+               float xLocRotated = x*cos( alpha ) - y*sin( alpha );
+
+               c = mix(uboGrad.colors[0], uboGrad.colors[1], smoothstep( gradientStartPosRotatedX + uboGrad.stops[0].r*d, gradientStartPosRotatedX + uboGrad.stops[1].r*d, xLocRotated ) );
+               for ( int i=1; i<uboGrad.count-1; ++i )
+                       c = mix(c, uboGrad.colors[i+1], smoothstep( gradientStartPosRotatedX + uboGrad.stops[i].r*d, gradientStartPosRotatedX + uboGrad.stops[i+1].r*d, xLocRotated ) );
+               break;
+       case RADIAL:
+               break;
+       }
+
+       if (inFontUV.z >= 0.0)
+               c *= texture(fontMap, inFontUV);
+
+       outFragColor = c;
+}
+
+void op_CLEAR () {
+       outFragColor = vec4 (0);
+}
diff --git a/shaders/vkvg_text.vert b/shaders/vkvg_text.vert
new file mode 100644 (file)
index 0000000..2826713
--- /dev/null
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2018 Jean-Philippe Bruyère <jp_bruyere@hotmail.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
+ * Software, and to permit persons to whom the Software is furnished to do so, subject
+ * to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+#version 450
+
+#extension GL_ARB_separate_shader_objects : enable
+#extension GL_ARB_shading_language_420pack : enable
+
+layout (location = 0) in vec2  inPos;
+layout (location = 1) in vec3  inUV;
+
+layout (location = 0) out vec3 outUV;
+layout (location = 1) out vec4 outSrc;
+layout (location = 2) out flat int outPatType;
+layout (location = 3) out mat3x2 outMat;
+
+out gl_PerVertex
+{
+       vec4 gl_Position;
+};
+
+layout(push_constant) uniform PushConsts {
+       vec4 source;
+       vec2 size;
+       int  srcType;
+       int  fullScreenQuad;
+       mat3x2 mat;
+       mat3x2 matInv;
+} pc;
+
+#define SOLID                  0
+#define SURFACE                        1
+#define LINEAR                 2
+#define RADIAL                 3
+#define MESH                   4
+#define RASTER_SOURCE  5
+
+void main()
+{
+       outPatType      = pc.srcType;
+       outSrc          = pc.source;
+       outMat          = pc.matInv;
+
+       if (pc.fullScreenQuad != 0) {
+               gl_Position = vec4(vec2((gl_VertexIndex << 1) & 2, gl_VertexIndex & 2) * 2.0f - 1.0f, 0.0f, 1.0f);
+               outUV = vec3(0,0,-1);
+               return;
+       }
+
+       outUV = inUV;
+
+       vec2 p = vec2(
+               pc.mat[0][0] * inPos.x + pc.mat[1][0] * inPos.y + pc.mat[2][0],
+               pc.mat[0][1] * inPos.x + pc.mat[1][1] * inPos.y + pc.mat[2][1]
+       );
+
+       gl_Position = vec4(p * vec2(2) / pc.size - vec2(1), 0.0, 1.0);
+}
index d696dc39c21f70e8ec9e112ceaa0ca7cd5600f93..bae562b06723d053f64a0d3c197dbff33e3ace27 100644 (file)
@@ -145,7 +145,7 @@ VkvgContext vkvg_create(VkvgSurface surf)
        _create_cmd_buff        (ctx);
        _createDescriptorPool   (ctx);
        _init_descriptor_sets   (ctx);
-       _update_descriptor_set  (ctx, ctx->pSurf->dev->fontCache->texture, ctx->dsFont);
+       //_update_descriptor_set  (ctx, ctx->pSurf->dev->fontCache->texture, ctx->dsFont);
        _update_descriptor_set  (ctx, surf->dev->emptyImg, ctx->dsSrc);
        _update_gradient_desc_set(ctx);
 
@@ -166,7 +166,7 @@ VkvgContext vkvg_create(VkvgSurface surf)
 
        vkh_device_set_object_name((VkhDevice)dev, VK_OBJECT_TYPE_DESCRIPTOR_POOL, (uint64_t)ctx->descriptorPool, "CTX Descriptor Pool");
        vkh_device_set_object_name((VkhDevice)dev, VK_OBJECT_TYPE_DESCRIPTOR_SET, (uint64_t)ctx->dsSrc, "CTX DescSet SOURCE");
-       vkh_device_set_object_name((VkhDevice)dev, VK_OBJECT_TYPE_DESCRIPTOR_SET, (uint64_t)ctx->dsFont, "CTX DescSet FONT");
+//     vkh_device_set_object_name((VkhDevice)dev, VK_OBJECT_TYPE_DESCRIPTOR_SET, (uint64_t)ctx->dsFont, "CTX DescSet FONT");
        vkh_device_set_object_name((VkhDevice)dev, VK_OBJECT_TYPE_DESCRIPTOR_SET, (uint64_t)ctx->dsGrad, "CTX DescSet GRADIENT");
 
        vkh_device_set_object_name((VkhDevice)dev, VK_OBJECT_TYPE_BUFFER, (uint64_t)ctx->indices.buffer, "CTX Index Buff");
@@ -231,8 +231,8 @@ void vkvg_destroy (VkvgContext ctx)
        vkFreeCommandBuffers(dev, ctx->cmdPool, 2, ctx->cmdBuffers);
        vkDestroyCommandPool(dev, ctx->cmdPool, NULL);
 
-       VkDescriptorSet dss[] = {ctx->dsFont, ctx->dsSrc, ctx->dsGrad};
-       vkFreeDescriptorSets    (dev, ctx->descriptorPool, 3, dss);
+       VkDescriptorSet dss[] = {ctx->dsSrc, ctx->dsGrad};
+       vkFreeDescriptorSets    (dev, ctx->descriptorPool, 2, dss);
 
        vkDestroyDescriptorPool (dev, ctx->descriptorPool,NULL);
 
@@ -520,7 +520,7 @@ void vkvg_rel_curve_to (VkvgContext ctx, float x1, float y1, float x2, float y2,
 }
 void vkvg_fill_rectangle (VkvgContext ctx, float x, float y, float w, float h){
        _vao_add_rectangle (ctx,x,y,w,h);
-       _record_draw_cmd(ctx);
+       //_record_draw_cmd(ctx);
 }
 
 void vkvg_rectangle (VkvgContext ctx, float x, float y, float w, float h){
@@ -842,7 +842,7 @@ void vkvg_stroke_preserve (VkvgContext ctx)
                else
                        ptrPath++;
        }
-       _record_draw_cmd(ctx);
+       //_record_draw_cmd(ctx);
 }
 void vkvg_paint (VkvgContext ctx){
        _check_cmd_buff_state (ctx);
@@ -853,7 +853,8 @@ void vkvg_set_source_rgb (VkvgContext ctx, float r, float g, float b) {
 }
 void vkvg_set_source_rgba (VkvgContext ctx, float r, float g, float b, float a)
 {
-       _update_cur_pattern (ctx, vkvg_pattern_create_rgba (r,g,b,a));
+       ctx->curColor = CreateRgbaf(r,g,b,a);
+       //_update_cur_pattern (ctx, vkvg_pattern_create_rgba (r,g,b,a));
 }
 void vkvg_set_source_surface(VkvgContext ctx, VkvgSurface surf, float x, float y){
        _update_cur_pattern (ctx, vkvg_pattern_create_for_surface(surf));
index 29434a754e1b5347b545e6dca6d4bbb66560073f..e3f462481f9040eef5adb2ca14fcf72c24c63114 100644 (file)
@@ -277,7 +277,7 @@ void _add_vertexf (VkvgContext ctx, float x, float y){
        Vertex* pVert = &ctx->vertexCache[ctx->vertCount];
        pVert->pos.x = x;
        pVert->pos.y = y;
-       pVert->uv = (vec3){0,0,-1};
+       pVert->color = ctx->curColor;
        ctx->vertCount++;
 
        _check_vertex_cache_size(ctx);
@@ -317,10 +317,10 @@ void _add_triangle_indices(VkvgContext ctx, VKVG_IBO_INDEX_TYPE i0, VKVG_IBO_IND
 void _vao_add_rectangle (VkvgContext ctx, float x, float y, float width, float height){
        Vertex v[4] =
        {
-               {{x,y},             {0,0,-1}},
-               {{x,y+height},      {0,0,-1}},
-               {{x+width,y},       {0,0,-1}},
-               {{x+width,y+height},{0,0,-1}}
+               {{x,y},             ctx->curColor},
+               {{x,y+height},      ctx->curColor},
+               {{x+width,y},       ctx->curColor},
+               {{x+width,y+height},ctx->curColor}
        };
        VKVG_IBO_INDEX_TYPE firstIdx = (VKVG_IBO_INDEX_TYPE)(ctx->vertCount - ctx->curVertOffset);
        Vertex* pVert = &ctx->vertexCache[ctx->vertCount];
@@ -468,10 +468,10 @@ void _record_draw_cmd (VkvgContext ctx){
        ctx->curVertOffset = ctx->vertCount;
 }
 void _flush_cmd_buff (VkvgContext ctx){
-       if (!ctx->cmdStarted)
+       if (ctx->indCount > ctx->curIndStart)
+               _record_draw_cmd (ctx);
+       else if (!ctx->cmdStarted)
                return;
-
-       _record_draw_cmd        (ctx);
        _end_render_pass        (ctx);
        _flush_vertices_caches  (ctx);
        vkh_cmd_end             (ctx->cmd);
@@ -523,9 +523,9 @@ void _start_cmd_for_render_pass (VkvgContext ctx) {
 
        CmdSetScissor(ctx->cmd, 0, 1, &ctx->bounds);
 
-       VkDescriptorSet dss[] = {ctx->dsFont,ctx->dsSrc,ctx->dsGrad};
+       VkDescriptorSet dss[] = {ctx->dsSrc,ctx->dsGrad};
        CmdBindDescriptorSets(ctx->cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, ctx->pSurf->dev->pipelineLayout,
-                                                       0, 3, dss, 0, NULL);
+                                                       0, 2, dss, 0, NULL);
 
        VkDeviceSize offsets[1] = { 0 };
        CmdBindVertexBuffers(ctx->cmd, 0, 1, &ctx->vertices.buffer, offsets);
@@ -730,8 +730,9 @@ void _init_descriptor_sets (VkvgContext ctx){
        VkDescriptorSetAllocateInfo descriptorSetAllocateInfo = { .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,
                                                                                                                          .descriptorPool = ctx->descriptorPool,
                                                                                                                          .descriptorSetCount = 1,
-                                                                                                                         .pSetLayouts = &dev->dslFont };
-       VK_CHECK_RESULT(vkAllocateDescriptorSets(dev->vkDev, &descriptorSetAllocateInfo, &ctx->dsFont));
+                                                                                                                         //.pSetLayouts = &dev->dslFont
+                                                                                                                       };
+       //VK_CHECK_RESULT(vkAllocateDescriptorSets(dev->vkDev, &descriptorSetAllocateInfo, &ctx->dsFont));
        descriptorSetAllocateInfo.pSetLayouts = &dev->dslSrc;
        VK_CHECK_RESULT(vkAllocateDescriptorSets(dev->vkDev, &descriptorSetAllocateInfo, &ctx->dsSrc));
        descriptorSetAllocateInfo.pSetLayouts = &dev->dslGrad;
@@ -739,7 +740,7 @@ void _init_descriptor_sets (VkvgContext ctx){
 }
 //populate vertice buff for stroke
 float _build_vb_step (vkvg_context* ctx, float hw, vec2 pL, vec2 p0, vec2 pR, bool isCurve){
-       Vertex v = {{0},{0,0,-1}};
+       Vertex v = {{0},ctx->curColor};
 
        //if two of the three points are equal, normal is null
        vec2 v0n = vec2_line_norm(pL, p0);
@@ -1078,7 +1079,7 @@ void _poly_fill (VkvgContext ctx){
 
        CmdBindPipeline (ctx->cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, ctx->pSurf->dev->pipelinePolyFill);
 
-       Vertex v = {{0},{0,0,-1}};
+       Vertex v = {{0},ctx->curColor};
        uint32_t ptrPath = 0;
        uint32_t firstPtIdx = 0;
 
@@ -1114,8 +1115,7 @@ void _poly_fill (VkvgContext ctx){
 }
 //create fill from current path with ear clipping technic
 void _fill_ec (VkvgContext ctx){
-       Vertex v = {0};
-       v.uv.z = -1;
+       Vertex v = {{0},ctx->curColor};
 
        uint32_t ptrPath = 0;
        uint32_t firstPtIdx = 0;
@@ -1192,7 +1192,7 @@ void _fill_ec (VkvgContext ctx){
                        ptrPath++;
                free (ecps);
        }
-       _record_draw_cmd(ctx);
+       //_record_draw_cmd(ctx);
 }
 
 static const uint32_t one = 1;
index 6751090ff9ae919c4f212cb99cd47de6be269dde..4851375832206fa035311da20a9090137c25fb07 100644 (file)
 #define VKVG_ARRAY_THRESHOLD           8
 #define VKVG_IBO_INDEX_TYPE         uint16_t
 
+#define CreateRgba(r, g, b, a) ((a << 24) | (r << 16) | (g << 8) | b)
+#ifdef VKVG_PREMULT_ALPHA
+       #define CreateRgbaf(r, g, b, a) (((int)(a * 255.0f) << 24) | ((int)(b * a * 255.0f) << 16) | ((int)(g * a * 255.0f) << 8) | (int)(r * a * 255.0f))
+#else
+       #define CreateRgbaf(r, g, b, a) (((int)(a * 255.0f) << 24) | ((int)(b * 255.0f) << 16) | ((int)(g * 255.0f) << 8) | (int)(r * 255.0f))
+#endif
+
 typedef struct{
        vec2 pos;
-       vec3 uv;
+       uint32_t color;
 }Vertex;
 
 typedef struct {
@@ -86,12 +93,14 @@ typedef struct _vkvg_context_t {
        bool                cmdStarted; //prevent flushing empty renderpass
        bool                pushCstDirty;//prevent pushing to gpu if not requested
        VkDescriptorPool        descriptorPool;//one pool per thread
-       VkDescriptorSet     dsFont;     //fonts glyphs texture atlas descriptor (local for thread safety)
+       //VkDescriptorSet     dsFont;     //fonts glyphs texture atlas descriptor (local for thread safety)
        VkDescriptorSet     dsSrc;      //source ds
        VkDescriptorSet     dsGrad;     //gradient uniform buffer
 
        VkRect2D            bounds;
 
+       uint32_t            curColor;
+
        float xMin;
        float xMax;
        float yMin;
index e680890af407907de37400b57b6387ffd0542332..7a062b64752807eeb06eec8b86feeffc7aeea162 100644 (file)
@@ -121,7 +121,7 @@ VkvgDevice vkvg_device_create_multisample(VkInstance inst, VkPhysicalDevice phy,
        vkh_device_set_object_name((VkhDevice)dev, VK_OBJECT_TYPE_RENDER_PASS, (uint64_t)dev->renderPass_ClearAll, "RP clear all");
 
        vkh_device_set_object_name((VkhDevice)dev, VK_OBJECT_TYPE_DESCRIPTOR_SET_LAYOUT, (uint64_t)dev->dslSrc, "DSLayout SOURCE");
-       vkh_device_set_object_name((VkhDevice)dev, VK_OBJECT_TYPE_DESCRIPTOR_SET_LAYOUT, (uint64_t)dev->dslFont, "DSLayout FONT");
+       //vkh_device_set_object_name((VkhDevice)dev, VK_OBJECT_TYPE_DESCRIPTOR_SET_LAYOUT, (uint64_t)dev->dslFont, "DSLayout FONT");
        vkh_device_set_object_name((VkhDevice)dev, VK_OBJECT_TYPE_DESCRIPTOR_SET_LAYOUT, (uint64_t)dev->dslGrad, "DSLayout GRADIENT");
        vkh_device_set_object_name((VkhDevice)dev, VK_OBJECT_TYPE_PIPELINE_LAYOUT, (uint64_t)dev->pipelineLayout, "PLLayout dev");
 
@@ -150,7 +150,7 @@ void vkvg_device_destroy (VkvgDevice dev)
        vkh_image_destroy               (dev->emptyImg);
 
        vkDestroyDescriptorSetLayout    (dev->vkDev, dev->dslGrad,NULL);
-       vkDestroyDescriptorSetLayout    (dev->vkDev, dev->dslFont,NULL);
+       //vkDestroyDescriptorSetLayout    (dev->vkDev, dev->dslFont,NULL);
        vkDestroyDescriptorSetLayout    (dev->vkDev, dev->dslSrc, NULL);
 
        vkDestroyPipeline               (dev->vkDev, dev->pipelinePolyFill, NULL);
index 25d3ccf29f01d1f59f2a2bd5a02371c6e454b53e..f01bf191ade1949be47a2b0cbac412aae7ac669d 100644 (file)
@@ -242,8 +242,8 @@ void _setupPipelines(VkvgDevice dev)
                                .inputRate = VK_VERTEX_INPUT_RATE_VERTEX };
 
        VkVertexInputAttributeDescription vertexInputAttributs[2] = {
-               {0, 0, VK_FORMAT_R32G32_SFLOAT,         0},
-               {1, 0, VK_FORMAT_R32G32B32_SFLOAT,      sizeof(vec2)}
+               {0, 0, VK_FORMAT_R32G32_SFLOAT, 0},
+               {1, 0, VK_FORMAT_R8G8B8A8_UNORM, sizeof(vec2)}
        };
 
        VkPipelineVertexInputStateCreateInfo vertexInputState = { .sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,
@@ -261,8 +261,8 @@ void _setupPipelines(VkvgDevice dev)
                                                                                        .codeSize = vkvg_main_vert_spv_len };
        VK_CHECK_RESULT(vkCreateShaderModule(dev->vkDev, &createInfo, NULL, &modVert));
 #ifdef VKVG_LCD_FONT_FILTER
-       createInfo.pCode = (uint32_t*)vkvg_main_lcd_frag_spv;
-       createInfo.codeSize = vkvg_main_lcd_frag_spv_len;
+       createInfo.pCode = (uint32_t*)vkvg_main_frag_spv;
+       createInfo.codeSize = vkvg_main_frag_spv_len;
 #else
        createInfo.pCode = (uint32_t*)vkvg_main_frag_spv;
        createInfo.codeSize = vkvg_main_frag_spv_len;
@@ -356,7 +356,7 @@ void _createDescriptorSetLayout (VkvgDevice dev) {
        VkDescriptorSetLayoutCreateInfo dsLayoutCreateInfo = { .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,
                                                                                                                  .bindingCount = 1,
                                                                                                                  .pBindings = &dsLayoutBinding };
-       VK_CHECK_RESULT(vkCreateDescriptorSetLayout(dev->vkDev, &dsLayoutCreateInfo, NULL, &dev->dslFont));
+       //VK_CHECK_RESULT(vkCreateDescriptorSetLayout(dev->vkDev, &dsLayoutCreateInfo, NULL, &dev->dslFont));
        VK_CHECK_RESULT(vkCreateDescriptorSetLayout(dev->vkDev, &dsLayoutCreateInfo, NULL, &dev->dslSrc));
        dsLayoutBinding.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
        VK_CHECK_RESULT(vkCreateDescriptorSetLayout(dev->vkDev, &dsLayoutCreateInfo, NULL, &dev->dslGrad));
@@ -365,12 +365,12 @@ void _createDescriptorSetLayout (VkvgDevice dev) {
                {VK_SHADER_STAGE_VERTEX_BIT,0,sizeof(push_constants)},
                //{VK_SHADER_STAGE_FRAGMENT_BIT,0,sizeof(push_constants)}
        };
-       VkDescriptorSetLayout dsls[] = {dev->dslFont,dev->dslSrc,dev->dslGrad};
+       VkDescriptorSetLayout dsls[] = {dev->dslSrc,dev->dslGrad};
 
        VkPipelineLayoutCreateInfo pipelineLayoutCreateInfo = { .sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
                                                                                                                        .pushConstantRangeCount = 1,
                                                                                                                        .pPushConstantRanges = (VkPushConstantRange*)&pushConstantRange,
-                                                                                                                       .setLayoutCount = 3,
+                                                                                                                       .setLayoutCount = 2,
                                                                                                                        .pSetLayouts = dsls };
        VK_CHECK_RESULT(vkCreatePipelineLayout(dev->vkDev, &pipelineLayoutCreateInfo, NULL, &dev->pipelineLayout));
 }
index a6b1b3a4ac0cec97a54c660847091caba96d8fd1..8c39e0d049b84c6fff10fcae6a49f32c43e3e133 100644 (file)
@@ -81,7 +81,7 @@ typedef struct _vkvg_device_t{
 #endif
        VkPipelineCache                 pipelineCache;          /**< speed up startup by caching configured pipelines on disk */
        VkPipelineLayout                pipelineLayout;         /**< layout common to all pipelines */
-       VkDescriptorSetLayout   dslFont;                /**< font cache descriptors layout */
+       //VkDescriptorSetLayout dslFont;                /**< font cache descriptors layout */
        VkDescriptorSetLayout   dslSrc;                 /**< context source surface descriptors layout */
        VkDescriptorSetLayout   dslGrad;                /**< context gradient descriptors layout */
 
index 7e87fc3b157ea733fed906521ca761f0870e3033..794eca63db91d43ed527a8bb4d78b1844a71eba0 100644 (file)
 static int defaultFontCharSize = 12<<6;
 
 void _init_fonts_cache (VkvgDevice dev){
-    _font_cache_t* cache = (_font_cache_t*)calloc(1, sizeof(_font_cache_t));
+       _font_cache_t* cache = (_font_cache_t*)calloc(1, sizeof(_font_cache_t));
 
-    cache->config = FcInitLoadConfigAndFonts();
-    if (!cache->config) {
-        fprintf(stderr, "Font config initialisation failed, consider using 'FONTCONFIG_PATH' and 'FONTCONFIG_FILE' environmane\
-                       variables to point to 'fonts.conf' needed for FontConfig startup");
-        assert(cache->config);
-    }
+       cache->config = FcInitLoadConfigAndFonts();
+       if (!cache->config) {
+               fprintf(stderr, "Font config initialisation failed, consider using 'FONTCONFIG_PATH' and 'FONTCONFIG_FILE' environmane\
+                                          variables to point to 'fonts.conf' needed for FontConfig startup");
+               assert(cache->config);
+       }
 
-    FT_CHECK_RESULT(FT_Init_FreeType(&cache->library));
+       FT_CHECK_RESULT(FT_Init_FreeType(&cache->library));
 
 
 #ifdef VKVG_LCD_FONT_FILTER
-    FT_CHECK_RESULT(FT_Library_SetLcdFilter (cache->library, FT_LCD_FILTER_LIGHT));
-    cache->texFormat = FB_COLOR_FORMAT;
-    cache->texPixelSize = 4;
+       FT_CHECK_RESULT(FT_Library_SetLcdFilter (cache->library, FT_LCD_FILTER_LIGHT));
+       cache->texFormat = FB_COLOR_FORMAT;
+       cache->texPixelSize = 4;
 #else
-    cache->texFormat = VK_FORMAT_R8_UNORM;
-    cache->texPixelSize = 1;
+       cache->texFormat = VK_FORMAT_R8_UNORM;
+       cache->texPixelSize = 1;
 #endif
 
-    cache->texLength = FONT_CACHE_INIT_LAYERS;
-    cache->texture = vkh_tex2d_array_create ((VkhDevice)dev, cache->texFormat, FONT_PAGE_SIZE, FONT_PAGE_SIZE,
-                            cache->texLength ,VMA_MEMORY_USAGE_GPU_ONLY,
-                            VK_IMAGE_USAGE_SAMPLED_BIT|VK_IMAGE_USAGE_TRANSFER_DST_BIT|VK_IMAGE_USAGE_TRANSFER_SRC_BIT);
-    vkh_image_create_descriptor (cache->texture, VK_IMAGE_VIEW_TYPE_2D_ARRAY, VK_IMAGE_ASPECT_COLOR_BIT,
-                                 VK_FILTER_NEAREST, VK_FILTER_NEAREST, VK_SAMPLER_MIPMAP_MODE_NEAREST, VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER);
+       cache->texLength = FONT_CACHE_INIT_LAYERS;
+       cache->texture = vkh_tex2d_array_create ((VkhDevice)dev, cache->texFormat, FONT_PAGE_SIZE, FONT_PAGE_SIZE,
+                                                       cache->texLength ,VMA_MEMORY_USAGE_GPU_ONLY,
+                                                       VK_IMAGE_USAGE_SAMPLED_BIT|VK_IMAGE_USAGE_TRANSFER_DST_BIT|VK_IMAGE_USAGE_TRANSFER_SRC_BIT);
+       vkh_image_create_descriptor (cache->texture, VK_IMAGE_VIEW_TYPE_2D_ARRAY, VK_IMAGE_ASPECT_COLOR_BIT,
+                                                                VK_FILTER_NEAREST, VK_FILTER_NEAREST, VK_SAMPLER_MIPMAP_MODE_NEAREST, VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER);
 
-    cache->uploadFence = vkh_fence_create((VkhDevice)dev);
+       cache->uploadFence = vkh_fence_create((VkhDevice)dev);
 
-    uint32_t buffLength = FONT_PAGE_SIZE*FONT_PAGE_SIZE*cache->texPixelSize;
+       uint32_t buffLength = FONT_PAGE_SIZE*FONT_PAGE_SIZE*cache->texPixelSize;
 
-    vkvg_buffer_create (dev,
-        VK_BUFFER_USAGE_TRANSFER_SRC_BIT,
-        VMA_MEMORY_USAGE_CPU_TO_GPU,
-        buffLength, &cache->buff);
+       vkvg_buffer_create (dev,
+               VK_BUFFER_USAGE_TRANSFER_SRC_BIT,
+               VMA_MEMORY_USAGE_CPU_TO_GPU,
+               buffLength, &cache->buff);
 
-    cache->cmd = vkh_cmd_buff_create((VkhDevice)dev,dev->cmdPool,VK_COMMAND_BUFFER_LEVEL_PRIMARY);
+       cache->cmd = vkh_cmd_buff_create((VkhDevice)dev,dev->cmdPool,VK_COMMAND_BUFFER_LEVEL_PRIMARY);
 
-    //Set texture cache initial layout to shaderReadOnly to prevent error msg if cache is not fill
-    VkImageSubresourceRange subres      = {VK_IMAGE_ASPECT_COLOR_BIT,0,1,0,cache->texLength};
-    vkh_cmd_begin (cache->cmd,VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT);
-    vkh_image_set_layout_subres(cache->cmd, cache->texture, subres,
-                                VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
-                                VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT);
-    VK_CHECK_RESULT(vkEndCommandBuffer(cache->cmd));
-    _submit_cmd (dev, &cache->cmd, cache->uploadFence);
+       //Set texture cache initial layout to shaderReadOnly to prevent error msg if cache is not fill
+       VkImageSubresourceRange subres      = {VK_IMAGE_ASPECT_COLOR_BIT,0,1,0,cache->texLength};
+       vkh_cmd_begin (cache->cmd,VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT);
+       vkh_image_set_layout_subres(cache->cmd, cache->texture, subres,
+                                                               VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
+                                                               VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT);
+       VK_CHECK_RESULT(vkEndCommandBuffer(cache->cmd));
+       _submit_cmd (dev, &cache->cmd, cache->uploadFence);
 
-    cache->hostBuff = (uint8_t*)malloc(buffLength);
-    cache->pensY = (int*)calloc(cache->texLength, sizeof(int));
+       cache->hostBuff = (uint8_t*)malloc(buffLength);
+       cache->pensY = (int*)calloc(cache->texLength, sizeof(int));
 
-    dev->fontCache = cache;
+       dev->fontCache = cache;
 }
 ///increase layer count of 2d texture array used as font cache.
 void _increase_font_tex_array (VkvgDevice dev){
-    _font_cache_t* cache = dev->fontCache;
+       _font_cache_t* cache = dev->fontCache;
 
-    vkWaitForFences     (dev->vkDev, 1, &cache->uploadFence, VK_TRUE, UINT64_MAX);
-    vkResetCommandBuffer(cache->cmd, 0);
-    vkResetFences       (dev->vkDev, 1, &cache->uploadFence);
+       vkWaitForFences     (dev->vkDev, 1, &cache->uploadFence, VK_TRUE, UINT64_MAX);
+       vkResetCommandBuffer(cache->cmd, 0);
+       vkResetFences       (dev->vkDev, 1, &cache->uploadFence);
 
-    uint8_t newSize = cache->texLength + FONT_CACHE_INIT_LAYERS;
-    VkhImage newImg = vkh_tex2d_array_create ((VkhDevice)dev, cache->texFormat, FONT_PAGE_SIZE, FONT_PAGE_SIZE,
-                                              newSize ,VMA_MEMORY_USAGE_GPU_ONLY,
-                                              VK_IMAGE_USAGE_SAMPLED_BIT|VK_IMAGE_USAGE_TRANSFER_DST_BIT|VK_IMAGE_USAGE_TRANSFER_SRC_BIT);
-    vkh_image_create_descriptor (newImg, VK_IMAGE_VIEW_TYPE_2D_ARRAY, VK_IMAGE_ASPECT_COLOR_BIT,
-                               VK_FILTER_NEAREST, VK_FILTER_NEAREST, VK_SAMPLER_MIPMAP_MODE_NEAREST,VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER);
+       uint8_t newSize = cache->texLength + FONT_CACHE_INIT_LAYERS;
+       VkhImage newImg = vkh_tex2d_array_create ((VkhDevice)dev, cache->texFormat, FONT_PAGE_SIZE, FONT_PAGE_SIZE,
+                                                                                         newSize ,VMA_MEMORY_USAGE_GPU_ONLY,
+                                                                                         VK_IMAGE_USAGE_SAMPLED_BIT|VK_IMAGE_USAGE_TRANSFER_DST_BIT|VK_IMAGE_USAGE_TRANSFER_SRC_BIT);
+       vkh_image_create_descriptor (newImg, VK_IMAGE_VIEW_TYPE_2D_ARRAY, VK_IMAGE_ASPECT_COLOR_BIT,
+                                                          VK_FILTER_NEAREST, VK_FILTER_NEAREST, VK_SAMPLER_MIPMAP_MODE_NEAREST,VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER);
 
-    VkImageSubresourceRange subresNew   = {VK_IMAGE_ASPECT_COLOR_BIT,0,1,0,newSize};
-    VkImageSubresourceRange subres      = {VK_IMAGE_ASPECT_COLOR_BIT,0,1,0,cache->texLength};
+       VkImageSubresourceRange subresNew   = {VK_IMAGE_ASPECT_COLOR_BIT,0,1,0,newSize};
+       VkImageSubresourceRange subres      = {VK_IMAGE_ASPECT_COLOR_BIT,0,1,0,cache->texLength};
 
-    vkh_cmd_begin (cache->cmd,VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT);
+       vkh_cmd_begin (cache->cmd,VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT);
 
-    vkh_image_set_layout_subres(cache->cmd, newImg, subresNew,
-                                VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
-                                VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT);
-    vkh_image_set_layout_subres(cache->cmd, cache->texture, subres,
-                                VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
-                                VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT);
+       vkh_image_set_layout_subres(cache->cmd, newImg, subresNew,
+                                                               VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
+                                                               VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT);
+       vkh_image_set_layout_subres(cache->cmd, cache->texture, subres,
+                                                               VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
+                                                               VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT);
 
-    VkImageCopy cregion = { .srcSubresource = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, cache->texLength},
-                            .dstSubresource = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, cache->texLength},
-                            .extent = {FONT_PAGE_SIZE,FONT_PAGE_SIZE,1}};
+       VkImageCopy cregion = { .srcSubresource = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, cache->texLength},
+                                                       .dstSubresource = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, cache->texLength},
+                                                       .extent = {FONT_PAGE_SIZE,FONT_PAGE_SIZE,1}};
 
-    vkCmdCopyImage (cache->cmd, vkh_image_get_vkimage (cache->texture), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
-                                vkh_image_get_vkimage (newImg), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &cregion);
+       vkCmdCopyImage (cache->cmd, vkh_image_get_vkimage (cache->texture), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
+                                                               vkh_image_get_vkimage (newImg), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &cregion);
 
-    vkh_image_set_layout_subres(cache->cmd, newImg, subresNew,
-                                VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
-                                VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT);
+       vkh_image_set_layout_subres(cache->cmd, newImg, subresNew,
+                                                               VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
+                                                               VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT);
 
-    VK_CHECK_RESULT(vkEndCommandBuffer(cache->cmd));
+       VK_CHECK_RESULT(vkEndCommandBuffer(cache->cmd));
 
-    _submit_cmd         (dev, &cache->cmd, cache->uploadFence);
-    vkWaitForFences     (dev->vkDev, 1, &cache->uploadFence, VK_TRUE, UINT64_MAX);
+       _submit_cmd         (dev, &cache->cmd, cache->uploadFence);
+       vkWaitForFences     (dev->vkDev, 1, &cache->uploadFence, VK_TRUE, UINT64_MAX);
 
-    _flush_all_contexes (dev);
+       _flush_all_contexes (dev);
 
-    cache->pensY = (int*)realloc(cache->pensY, newSize * sizeof(int));
-    memset (cache->pensY + cache->texLength * sizeof(int),0,FONT_CACHE_INIT_LAYERS*sizeof(int));
+       cache->pensY = (int*)realloc(cache->pensY, newSize * sizeof(int));
+       memset (cache->pensY + cache->texLength * sizeof(int),0,FONT_CACHE_INIT_LAYERS*sizeof(int));
 
-    vkh_image_destroy   (cache->texture);
-    cache->texLength   = newSize;
-    cache->texture     = newImg;
+       vkh_image_destroy   (cache->texture);
+       cache->texLength   = newSize;
+       cache->texture     = newImg;
 
-    VkvgContext next = dev->lastCtx;
-    while (next != NULL){
-        _update_descriptor_set (next, next->source, next->dsSrc);
-        next = next->pPrev;
-    }
+       /*VkvgContext next = dev->lastCtx;
+       while (next != NULL){
+               _update_descriptor_set (next, next->source, next->dsSrc);
+               next = next->pPrev;
+       }*/
 }
 ///Start a new line in font cache, increase texture layer count if needed.
 void _init_next_line_in_tex_cache (VkvgDevice dev, _vkvg_font_t* f){
-    _font_cache_t* cache = dev->fontCache;
-    int i;
-    for (i = 0; i < cache->texLength; ++i) {
-        if (cache->pensY[i] + f->curLine.height >= FONT_PAGE_SIZE)
-            continue;
-        f->curLine.pageIdx = (unsigned char)i;
-        f->curLine.penX = 0;
-        f->curLine.penY = cache->pensY[i];
-        cache->pensY[i] += f->curLine.height;
-        return;
-    }
-    _flush_chars_to_tex         (dev, f);
-    _increase_font_tex_array    (dev);
-    _init_next_line_in_tex_cache(dev, f);
+       _font_cache_t* cache = dev->fontCache;
+       int i;
+       for (i = 0; i < cache->texLength; ++i) {
+               if (cache->pensY[i] + f->curLine.height >= FONT_PAGE_SIZE)
+                       continue;
+               f->curLine.pageIdx = (unsigned char)i;
+               f->curLine.penX = 0;
+               f->curLine.penY = cache->pensY[i];
+               cache->pensY[i] += f->curLine.height;
+               return;
+       }
+       _flush_chars_to_tex         (dev, f);
+       _increase_font_tex_array    (dev);
+       _init_next_line_in_tex_cache(dev, f);
 }
 void _destroy_font_cache (VkvgDevice dev){
-    _font_cache_t* cache = (_font_cache_t*)dev->fontCache;
+       _font_cache_t* cache = (_font_cache_t*)dev->fontCache;
 
-    //FcFini();
+       //FcFini();
 
-    free (cache->hostBuff);
+       free (cache->hostBuff);
 
-    for (int i = 0; i < cache->fontsCount; ++i) {
-        _vkvg_font_t f = cache->fonts[i];
+       for (int i = 0; i < cache->fontsCount; ++i) {
+               _vkvg_font_t f = cache->fonts[i];
 
-        for (int g = 0; g < f.face->num_glyphs; ++g) {
-            if (f.charLookup[g]!=NULL)
-                free(f.charLookup[g]);
-        }
+               for (int g = 0; g < f.face->num_glyphs; ++g) {
+                       if (f.charLookup[g]!=NULL)
+                               free(f.charLookup[g]);
+               }
 
-        FT_Done_Face (f.face);
-        hb_font_destroy (f.hb_font);
+               FT_Done_Face (f.face);
+               hb_font_destroy (f.hb_font);
 
-        free(f.charLookup);
-        free(f.fontFile);
-    }
+               free(f.charLookup);
+               free(f.fontFile);
+       }
 
-    free(cache->fonts);
-    free(cache->pensY);
+       free(cache->fonts);
+       free(cache->pensY);
 
 
-    vkvg_buffer_destroy (&cache->buff);
-    vkh_image_destroy   (cache->texture);
-    //vkFreeCommandBuffers(dev->vkDev,dev->cmdPool, 1, &cache->cmd);
-    vkDestroyFence      (dev->vkDev,cache->uploadFence,NULL);
+       vkvg_buffer_destroy (&cache->buff);
+       vkh_image_destroy   (cache->texture);
+       //vkFreeCommandBuffers(dev->vkDev,dev->cmdPool, 1, &cache->cmd);
+       vkDestroyFence      (dev->vkDev,cache->uploadFence,NULL);
 
-    free (dev->fontCache);
+       free (dev->fontCache);
 
 }
 
 #ifdef DEBUG
 //helper function
 void _dump_glyphs (FT_Face face){
-    FT_GlyphSlot    slot;
-    char gname[256];
+       FT_GlyphSlot    slot;
+       char gname[256];
 
-    for (int i = 0; i < face->num_glyphs; ++i) {
-        FT_CHECK_RESULT(FT_Load_Glyph(face,i,FT_LOAD_RENDER));
-        slot = face->glyph;
+       for (int i = 0; i < face->num_glyphs; ++i) {
+               FT_CHECK_RESULT(FT_Load_Glyph(face,i,FT_LOAD_RENDER));
+               slot = face->glyph;
 
-        FT_Get_Glyph_Name(face,i,gname,256);
+               FT_Get_Glyph_Name(face,i,gname,256);
 
 
-        printf("glyph: %s (%d,%d;%d), max advance:%ld\n", gname,
-               slot->bitmap.width, slot->bitmap.rows, slot->bitmap.pitch,
-               face->size->metrics.max_advance/64);
-    }
+               printf("glyph: %s (%d,%d;%d), max advance:%ld\n", gname,
+                          slot->bitmap.width, slot->bitmap.rows, slot->bitmap.pitch,
+                          face->size->metrics.max_advance/64);
+       }
 }
 #endif
 //flush font stagging buffer to cache texture array
 void _flush_chars_to_tex (VkvgDevice dev, _vkvg_font_t* f) {
-    _font_cache_t* cache = dev->fontCache;
-    if (cache->stagingX == 0)
-        return;
+       _font_cache_t* cache = dev->fontCache;
+       if (cache->stagingX == 0)
+               return;
 
-    vkWaitForFences     (dev->vkDev,1,&cache->uploadFence,VK_TRUE,UINT64_MAX);
-    vkResetCommandBuffer(cache->cmd,0);
-    vkResetFences       (dev->vkDev,1,&cache->uploadFence);
+       vkWaitForFences     (dev->vkDev,1,&cache->uploadFence,VK_TRUE,UINT64_MAX);
+       vkResetCommandBuffer(cache->cmd,0);
+       vkResetFences       (dev->vkDev,1,&cache->uploadFence);
 
-    memcpy(cache->buff.allocInfo.pMappedData, cache->hostBuff, (uint64_t)f->curLine.height * FONT_PAGE_SIZE * cache->texPixelSize);
+       memcpy(cache->buff.allocInfo.pMappedData, cache->hostBuff, (uint64_t)f->curLine.height * FONT_PAGE_SIZE * cache->texPixelSize);
 
-    vkh_cmd_begin (cache->cmd,VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT);
+       vkh_cmd_begin (cache->cmd,VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT);
 
-    VkImageSubresourceRange subres      = {VK_IMAGE_ASPECT_COLOR_BIT,0,1,f->curLine.pageIdx,1};
-    vkh_image_set_layout_subres(cache->cmd, cache->texture, subres,
-                                VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
-                                VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT);
+       VkImageSubresourceRange subres      = {VK_IMAGE_ASPECT_COLOR_BIT,0,1,f->curLine.pageIdx,1};
+       vkh_image_set_layout_subres(cache->cmd, cache->texture, subres,
+                                                               VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
+                                                               VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT);
 
-    VkBufferImageCopy bufferCopyRegion = { .imageSubresource = {VK_IMAGE_ASPECT_COLOR_BIT,0,f->curLine.pageIdx,1},
-                                           .bufferRowLength = FONT_PAGE_SIZE,
-                                           .bufferImageHeight = f->curLine.height,
-                                           .imageOffset = {f->curLine.penX,f->curLine.penY,0},
-                                           .imageExtent = {FONT_PAGE_SIZE-f->curLine.penX,f->curLine.height,1}};
+       VkBufferImageCopy bufferCopyRegion = { .imageSubresource = {VK_IMAGE_ASPECT_COLOR_BIT,0,f->curLine.pageIdx,1},
+                                                                                  .bufferRowLength = FONT_PAGE_SIZE,
+                                                                                  .bufferImageHeight = f->curLine.height,
+                                                                                  .imageOffset = {f->curLine.penX,f->curLine.penY,0},
+                                                                                  .imageExtent = {FONT_PAGE_SIZE-f->curLine.penX,f->curLine.height,1}};
 
-    vkCmdCopyBufferToImage(cache->cmd, cache->buff.buffer,
-                           vkh_image_get_vkimage (cache->texture), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &bufferCopyRegion);
+       vkCmdCopyBufferToImage(cache->cmd, cache->buff.buffer,
+                                                  vkh_image_get_vkimage (cache->texture), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &bufferCopyRegion);
 
-    vkh_image_set_layout_subres(cache->cmd, cache->texture, subres,
-                                VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
-                                VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT);
+       vkh_image_set_layout_subres(cache->cmd, cache->texture, subres,
+                                                               VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
+                                                               VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT);
 
-    VK_CHECK_RESULT(vkEndCommandBuffer(cache->cmd));
+       VK_CHECK_RESULT(vkEndCommandBuffer(cache->cmd));
 
-    _submit_cmd (dev, &cache->cmd, cache->uploadFence);
+       _submit_cmd (dev, &cache->cmd, cache->uploadFence);
 
-    f->curLine.penX += cache->stagingX;
-    cache->stagingX = 0;
-    memset(cache->hostBuff, 0, (uint64_t)FONT_PAGE_SIZE * FONT_PAGE_SIZE * cache->texPixelSize);
+       f->curLine.penX += cache->stagingX;
+       cache->stagingX = 0;
+       memset(cache->hostBuff, 0, (uint64_t)FONT_PAGE_SIZE * FONT_PAGE_SIZE * cache->texPixelSize);
 }
 //create a new char entry and put glyph in stagging buffer, ready for upload.
 _char_ref* _prepare_char (VkvgDevice dev, _vkvg_font_t* f, FT_UInt gindex){
 
 #ifdef VKVG_LCD_FONT_FILTER
-    FT_CHECK_RESULT(FT_Load_Glyph(f->face, gindex, FT_LOAD_TARGET_NORMAL));
-    FT_CHECK_RESULT(FT_Render_Glyph(f->face->glyph, FT_RENDER_MODE_LCD));
+       FT_CHECK_RESULT(FT_Load_Glyph(f->face, gindex, FT_LOAD_TARGET_NORMAL));
+       FT_CHECK_RESULT(FT_Render_Glyph(f->face->glyph, FT_RENDER_MODE_LCD));
 #else
-    FT_CHECK_RESULT(FT_Load_Glyph(f->face, gindex, FT_LOAD_RENDER));
+       FT_CHECK_RESULT(FT_Load_Glyph(f->face, gindex, FT_LOAD_RENDER));
 #endif
 
-    FT_GlyphSlot    slot    = f->face->glyph;
-    FT_Bitmap       bmp     = slot->bitmap;
-    uint8_t*        data    = dev->fontCache->hostBuff;
-    uint32_t        bmpWidth= bmp.width;   //real width in pixel of char bitmap
+       FT_GlyphSlot    slot    = f->face->glyph;
+       FT_Bitmap       bmp     = slot->bitmap;
+       uint8_t*        data    = dev->fontCache->hostBuff;
+       uint32_t        bmpWidth= bmp.width;   //real width in pixel of char bitmap
 
 #ifdef VKVG_LCD_FONT_FILTER
-    bmpWidth /= 3;
+       bmpWidth /= 3;
 #endif
 
 
-    if (dev->fontCache->stagingX + f->curLine.penX + bmpWidth > FONT_PAGE_SIZE){
-        _flush_chars_to_tex (dev, f);
-        _init_next_line_in_tex_cache (dev, f);
-    }
+       if (dev->fontCache->stagingX + f->curLine.penX + bmpWidth > FONT_PAGE_SIZE){
+               _flush_chars_to_tex (dev, f);
+               _init_next_line_in_tex_cache (dev, f);
+       }
 
-    int penX = dev->fontCache->stagingX;
-    for(uint32_t y=0; y<bmp.rows; y++) {
-        for(uint32_t x=0; x<bmpWidth; x++) {
+       int penX = dev->fontCache->stagingX;
+       for(uint32_t y=0; y<bmp.rows; y++) {
+               for(uint32_t x=0; x<bmpWidth; x++) {
 #ifdef VKVG_LCD_FONT_FILTER
-            unsigned char r = bmp.buffer[y * bmp.pitch + x * 3];
-            unsigned char g = bmp.buffer[y * bmp.pitch + x * 3 + 1];
-            unsigned char b = bmp.buffer[y * bmp.pitch + x * 3 + 2];
-
-            data[(penX + x + y * FONT_PAGE_SIZE) * 4] = b;
-            data[(penX + x + y * FONT_PAGE_SIZE) * 4 + 1] = g;
-            data[(penX + x + y * FONT_PAGE_SIZE) * 4 + 2] = r;
-            data[(penX + x + y * FONT_PAGE_SIZE) * 4 + 3] = (r+g+b)/3;
+                       unsigned char r = bmp.buffer[y * bmp.pitch + x * 3];
+                       unsigned char g = bmp.buffer[y * bmp.pitch + x * 3 + 1];
+                       unsigned char b = bmp.buffer[y * bmp.pitch + x * 3 + 2];
+
+                       data[(penX + x + y * FONT_PAGE_SIZE) * 4] = b;
+                       data[(penX + x + y * FONT_PAGE_SIZE) * 4 + 1] = g;
+                       data[(penX + x + y * FONT_PAGE_SIZE) * 4 + 2] = r;
+                       data[(penX + x + y * FONT_PAGE_SIZE) * 4 + 3] = (r+g+b)/3;
 #else
-            data[penX + x + y * FONT_PAGE_SIZE ] = bmp.buffer[x + y * bmp.width];
+                       data[penX + x + y * FONT_PAGE_SIZE ] = bmp.buffer[x + y * bmp.width];
 #endif
-        }
-    }
-
-    _char_ref* cr = (_char_ref*)malloc(sizeof(_char_ref));
-    vec4 uvBounds = {
-        (float)(penX + f->curLine.penX) / (float)FONT_PAGE_SIZE,
-        (float)f->curLine.penY / (float)FONT_PAGE_SIZE,
-        (float)bmpWidth,
-        (float)bmp.rows};
-    cr->bounds = uvBounds;
-    cr->pageIdx = f->curLine.pageIdx;
-    cr->bmpDiff.x = (int16_t)slot->bitmap_left;
-    cr->bmpDiff.y = (int16_t)slot->bitmap_top;
-
-    f->charLookup[gindex] = cr;
-    dev->fontCache->stagingX += bmpWidth;
-    return cr;
+               }
+       }
+
+       _char_ref* cr = (_char_ref*)malloc(sizeof(_char_ref));
+       vec4 uvBounds = {
+               (float)(penX + f->curLine.penX) / (float)FONT_PAGE_SIZE,
+               (float)f->curLine.penY / (float)FONT_PAGE_SIZE,
+               (float)bmpWidth,
+               (float)bmp.rows};
+       cr->bounds = uvBounds;
+       cr->pageIdx = f->curLine.pageIdx;
+       cr->bmpDiff.x = (int16_t)slot->bitmap_left;
+       cr->bmpDiff.y = (int16_t)slot->bitmap_top;
+
+       f->charLookup[gindex] = cr;
+       dev->fontCache->stagingX += bmpWidth;
+       return cr;
 }
 //set current font size for context
 void _set_font_size (VkvgContext ctx, uint32_t size){
-    ctx->selectedFont.charSize = size << 6;
-    ctx->currentFont = NULL;
+       ctx->selectedFont.charSize = size << 6;
+       ctx->currentFont = NULL;
 }
 //select current font for context
 void _select_font_face (VkvgContext ctx, const char* name){
-    _font_cache_t*  cache = (_font_cache_t*)ctx->pSurf->dev->fontCache;
-
-    char* fontFile;
-
-    //make pattern from font name
-    FcPattern* pat = FcNameParse((const FcChar8*)name);
-    FcConfigSubstitute(cache->config, pat, FcMatchPattern);
-    FcDefaultSubstitute(pat);
-    // find the font
-    FcResult result;
-    FcPattern* font = FcFontMatch(cache->config, pat, &result);
-    if (font)
-    {
-        if (FcPatternGetString(font, FC_FILE, 0, (FcChar8 **)&fontFile) == FcResultMatch){
-            memset (ctx->selectedFont.fontFile, 0, FONT_FILE_NAME_MAX_SIZE);
-            memcpy (ctx->selectedFont.fontFile, fontFile, FONT_FILE_NAME_MAX_SIZE);
-        }
-    }
-    FcPatternDestroy(pat);
-    FcPatternDestroy(font);
-
-    ctx->currentFont =  NULL;
+       _font_cache_t*  cache = (_font_cache_t*)ctx->pSurf->dev->fontCache;
+
+       char* fontFile;
+
+       //make pattern from font name
+       FcPattern* pat = FcNameParse((const FcChar8*)name);
+       FcConfigSubstitute(cache->config, pat, FcMatchPattern);
+       FcDefaultSubstitute(pat);
+       // find the font
+       FcResult result;
+       FcPattern* font = FcFontMatch(cache->config, pat, &result);
+       if (font)
+       {
+               if (FcPatternGetString(font, FC_FILE, 0, (FcChar8 **)&fontFile) == FcResultMatch){
+                       memset (ctx->selectedFont.fontFile, 0, FONT_FILE_NAME_MAX_SIZE);
+                       memcpy (ctx->selectedFont.fontFile, fontFile, FONT_FILE_NAME_MAX_SIZE);
+               }
+       }
+       FcPatternDestroy(pat);
+       FcPatternDestroy(font);
+
+       ctx->currentFont =  NULL;
 }
 //try to find font in cache with same font file path and font size as selected in context.
 _vkvg_font_t* _tryFindVkvgFont (VkvgContext ctx){
-    _font_cache_t*  cache = (_font_cache_t*)ctx->pSurf->dev->fontCache;
-    for (int i = 0; i < cache->fontsCount; ++i) {
-        if (strcmp (cache->fonts[i].fontFile, ctx->selectedFont.fontFile)==0 && cache->fonts[i].charSize == ctx->selectedFont.charSize)
-            return &cache->fonts[i];
-    }
-    return NULL;
+       _font_cache_t*  cache = (_font_cache_t*)ctx->pSurf->dev->fontCache;
+       for (int i = 0; i < cache->fontsCount; ++i) {
+               if (strcmp (cache->fonts[i].fontFile, ctx->selectedFont.fontFile)==0 && cache->fonts[i].charSize == ctx->selectedFont.charSize)
+                       return &cache->fonts[i];
+       }
+       return NULL;
 }
 //try to find corresponding font in cache (defined by context selectedFont) and create a new font entry if not found.
 void _update_current_font (VkvgContext ctx) {
-    VkvgDevice dev = ctx->pSurf->dev;
-    if (ctx->currentFont == NULL){
-        if (ctx->selectedFont.fontFile[0] == 0) {
-            ctx->selectedFont.charSize = 10 << 6;
-            _select_font_face (ctx, "sans");
-        }
-        ctx->currentFont = _tryFindVkvgFont (ctx);
-        if (ctx->currentFont == NULL){
-            //create new font in cache
-            _font_cache_t*  cache = dev->fontCache;
-            cache->fontsCount++;
-            if (cache->fontsCount == 1)
-                cache->fonts = (_vkvg_font_t*) malloc (cache->fontsCount * sizeof(_vkvg_font_t));
-            else
-                cache->fonts = (_vkvg_font_t*) realloc (cache->fonts, cache->fontsCount * sizeof(_vkvg_font_t));
-
-            _vkvg_font_t nf = ctx->selectedFont;
-            if (nf.charSize == 0)
-                nf.charSize = defaultFontCharSize;
-
-            nf.fontFile = (char*)calloc(FONT_FILE_NAME_MAX_SIZE,sizeof(char));
-            strcpy (nf.fontFile, ctx->selectedFont.fontFile);
-
-            FT_CHECK_RESULT(FT_New_Face(cache->library, nf.fontFile, 0, &nf.face));
-            FT_CHECK_RESULT(FT_Set_Char_Size(nf.face, 0, nf.charSize, dev->hdpi, dev->vdpi ));
-            nf.hb_font = hb_ft_font_create(nf.face, NULL);
-            nf.charLookup = (_char_ref**)calloc(nf.face->num_glyphs,sizeof(_char_ref*));
-
-            //nf.curLine.height = (nf.face->bbox.xMax - nf.face->bbox.xMin) >> 6;
-            if (FT_IS_SCALABLE(nf.face))
-                nf.curLine.height = FT_MulFix(nf.face->height, nf.face->size->metrics.y_scale) >> 6;// nf.face->size->metrics.height >> 6;
-            else
-                nf.curLine.height = nf.face->height >> 6;
-
-            _init_next_line_in_tex_cache (dev, &nf);
-            cache->fonts[cache->fontsCount-1] = nf;
-            ctx->currentFont = &cache->fonts[cache->fontsCount-1];
-        }
-    }
+       VkvgDevice dev = ctx->pSurf->dev;
+       if (ctx->currentFont == NULL){
+               if (ctx->selectedFont.fontFile[0] == 0) {
+                       ctx->selectedFont.charSize = 10 << 6;
+                       _select_font_face (ctx, "sans");
+               }
+               ctx->currentFont = _tryFindVkvgFont (ctx);
+               if (ctx->currentFont == NULL){
+                       //create new font in cache
+                       _font_cache_t*  cache = dev->fontCache;
+                       cache->fontsCount++;
+                       if (cache->fontsCount == 1)
+                               cache->fonts = (_vkvg_font_t*) malloc (cache->fontsCount * sizeof(_vkvg_font_t));
+                       else
+                               cache->fonts = (_vkvg_font_t*) realloc (cache->fonts, cache->fontsCount * sizeof(_vkvg_font_t));
+
+                       _vkvg_font_t nf = ctx->selectedFont;
+                       if (nf.charSize == 0)
+                               nf.charSize = defaultFontCharSize;
+
+                       nf.fontFile = (char*)calloc(FONT_FILE_NAME_MAX_SIZE,sizeof(char));
+                       strcpy (nf.fontFile, ctx->selectedFont.fontFile);
+
+                       FT_CHECK_RESULT(FT_New_Face(cache->library, nf.fontFile, 0, &nf.face));
+                       FT_CHECK_RESULT(FT_Set_Char_Size(nf.face, 0, nf.charSize, dev->hdpi, dev->vdpi ));
+                       nf.hb_font = hb_ft_font_create(nf.face, NULL);
+                       nf.charLookup = (_char_ref**)calloc(nf.face->num_glyphs,sizeof(_char_ref*));
+
+                       //nf.curLine.height = (nf.face->bbox.xMax - nf.face->bbox.xMin) >> 6;
+                       if (FT_IS_SCALABLE(nf.face))
+                               nf.curLine.height = FT_MulFix(nf.face->height, nf.face->size->metrics.y_scale) >> 6;// nf.face->size->metrics.height >> 6;
+                       else
+                               nf.curLine.height = nf.face->height >> 6;
+
+                       _init_next_line_in_tex_cache (dev, &nf);
+                       cache->fonts[cache->fontsCount-1] = nf;
+                       ctx->currentFont = &cache->fonts[cache->fontsCount-1];
+               }
+       }
 }
 //Get harfBuzz buffer for provided text.
 hb_buffer_t * _get_hb_buffer (_vkvg_font_t* font, const char* text) {
-    hb_buffer_t *buf = hb_buffer_create();
+       hb_buffer_t *buf = hb_buffer_create();
 
-    const char *lng  = "fr";
-    hb_script_t script = HB_SCRIPT_LATIN;
-    script = hb_script_from_string (text, (int)strlen (text));
+       const char *lng  = "fr";
+       hb_script_t script = HB_SCRIPT_LATIN;
+       script = hb_script_from_string (text, (int)strlen (text));
 
-    hb_direction_t dir = hb_script_get_horizontal_direction(script);
-    //dir = HB_DIRECTION_TTB;
-    hb_buffer_set_direction (buf, dir);
-    hb_buffer_set_script    (buf, script);
-    hb_buffer_set_language  (buf, hb_language_from_string (lng, (int)strlen(lng)));
-    hb_buffer_add_utf8      (buf, text, (int)strlen(text), 0, (int)strlen(text));
+       hb_direction_t dir = hb_script_get_horizontal_direction(script);
+       //dir = HB_DIRECTION_TTB;
+       hb_buffer_set_direction (buf, dir);
+       hb_buffer_set_script    (buf, script);
+       hb_buffer_set_language  (buf, hb_language_from_string (lng, (int)strlen(lng)));
+       hb_buffer_add_utf8      (buf, text, (int)strlen(text), 0, (int)strlen(text));
 
-    hb_shape (font->hb_font, buf, NULL, 0);
-    return buf;
+       hb_shape (font->hb_font, buf, NULL, 0);
+       return buf;
 }
 //retrieve global font extends of context's current font as defined by FreeType
 void _font_extents (VkvgContext ctx, vkvg_font_extents_t *extents) {
-    _update_current_font (ctx);
-
-    //TODO: ensure correct metrics are returned (scalled/unscalled, etc..)
-    FT_BBox* bbox = &ctx->currentFont->face->bbox;
-    FT_Size_Metrics* metrics = &ctx->currentFont->face->size->metrics;
-    extents->ascent = (float)(FT_MulFix(ctx->currentFont->face->ascender, metrics->y_scale) >> 6);//metrics->ascender >> 6;
-    extents->descent= (float)(FT_MulFix(ctx->currentFont->face->descender, metrics->y_scale) >> 6);//metrics->descender >> 6;
-    extents->height = (float)(FT_MulFix(ctx->currentFont->face->height, metrics->y_scale) >> 6);//metrics->height >> 6;
-    extents->max_x_advance = (float)(bbox->xMax >> 6);
-    extents->max_y_advance = (float)(bbox->yMax >> 6);
+       _update_current_font (ctx);
+
+       //TODO: ensure correct metrics are returned (scalled/unscalled, etc..)
+       FT_BBox* bbox = &ctx->currentFont->face->bbox;
+       FT_Size_Metrics* metrics = &ctx->currentFont->face->size->metrics;
+       extents->ascent = (float)(FT_MulFix(ctx->currentFont->face->ascender, metrics->y_scale) >> 6);//metrics->ascender >> 6;
+       extents->descent= (float)(FT_MulFix(ctx->currentFont->face->descender, metrics->y_scale) >> 6);//metrics->descender >> 6;
+       extents->height = (float)(FT_MulFix(ctx->currentFont->face->height, metrics->y_scale) >> 6);//metrics->height >> 6;
+       extents->max_x_advance = (float)(bbox->xMax >> 6);
+       extents->max_y_advance = (float)(bbox->yMax >> 6);
 }
 //compute text extends for provided string.
 void _text_extents (VkvgContext ctx, const char* text, vkvg_text_extents_t *extents) {
-    _update_current_font (ctx);
+       _update_current_font (ctx);
 
-    vkvg_text_run_t tr = {0};
-    _create_text_run (ctx, text, &tr);
+       vkvg_text_run_t tr = {0};
+       _create_text_run (ctx, text, &tr);
 
-    *extents = tr.extents;
+       *extents = tr.extents;
 
-    _destroy_text_run (&tr);
+       _destroy_text_run (&tr);
 }
 void _create_text_run (VkvgContext ctx, const char* text, VkvgText textRun) {
 
-    _update_current_font (ctx);
+       _update_current_font (ctx);
 
-    textRun->hbBuf = _get_hb_buffer (ctx->currentFont, text);
-    textRun->font = ctx->currentFont;
-    textRun->dev = ctx->pSurf->dev;
+       textRun->hbBuf = _get_hb_buffer (ctx->currentFont, text);
+       textRun->font = ctx->currentFont;
+       textRun->dev = ctx->pSurf->dev;
 
-    textRun->glyph_pos = hb_buffer_get_glyph_positions   (textRun->hbBuf, &textRun->glyph_count);
+       textRun->glyph_pos = hb_buffer_get_glyph_positions   (textRun->hbBuf, &textRun->glyph_count);
 
-    unsigned int string_width_in_pixels = 0;
-    for (uint32_t i=0; i < textRun->glyph_count; ++i)
-        string_width_in_pixels += textRun->glyph_pos[i].x_advance >> 6;
+       unsigned int string_width_in_pixels = 0;
+       for (uint32_t i=0; i < textRun->glyph_count; ++i)
+               string_width_in_pixels += textRun->glyph_pos[i].x_advance >> 6;
 
-    FT_Size_Metrics* metrics = &ctx->currentFont->face->size->metrics;
-    textRun->extents.x_advance = (float)string_width_in_pixels;
-    textRun->extents.y_advance = (float)(textRun->glyph_pos[textRun->glyph_count-1].y_advance >> 6);
-    textRun->extents.x_bearing = -(float)(textRun->glyph_pos[0].x_offset >> 6);
-    textRun->extents.y_bearing = -(float)(textRun->glyph_pos[0].y_offset >> 6);
+       FT_Size_Metrics* metrics = &ctx->currentFont->face->size->metrics;
+       textRun->extents.x_advance = (float)string_width_in_pixels;
+       textRun->extents.y_advance = (float)(textRun->glyph_pos[textRun->glyph_count-1].y_advance >> 6);
+       textRun->extents.x_bearing = -(float)(textRun->glyph_pos[0].x_offset >> 6);
+       textRun->extents.y_bearing = -(float)(textRun->glyph_pos[0].y_offset >> 6);
 
-    textRun->extents.height = (float)(FT_MulFix(ctx->currentFont->face->height, metrics->y_scale) >> 6);// (metrics->ascender + metrics->descender) >> 6;
-    textRun->extents.width  = textRun->extents.x_advance;
+       textRun->extents.height = (float)(FT_MulFix(ctx->currentFont->face->height, metrics->y_scale) >> 6);// (metrics->ascender + metrics->descender) >> 6;
+       textRun->extents.width  = textRun->extents.x_advance;
 }
 void _destroy_text_run (VkvgText textRun) {
-    hb_buffer_destroy (textRun->hbBuf);
+       hb_buffer_destroy (textRun->hbBuf);
 }
 void _show_text_run (VkvgContext ctx, VkvgText tr) {
-    unsigned int glyph_count;
-    hb_glyph_info_t* glyph_info = hb_buffer_get_glyph_infos (tr->hbBuf, &glyph_count);
+       unsigned int glyph_count;
+       hb_glyph_info_t* glyph_info = hb_buffer_get_glyph_infos (tr->hbBuf, &glyph_count);
 
-    Vertex v = {{0},{0}};
-    vec2 pen = {0,0};
+       Vertex v = {{0},0};
+       vec2 pen = {0,0};
 
-    if (!_current_path_is_empty(ctx))
-        pen = _get_current_position(ctx);
+       if (!_current_path_is_empty(ctx))
+               pen = _get_current_position(ctx);
 
-    for (uint32_t i=0; i < glyph_count; ++i) {
-        _char_ref* cr = tr->font->charLookup[glyph_info[i].codepoint];
+       for (uint32_t i=0; i < glyph_count; ++i) {
+               _char_ref* cr = tr->font->charLookup[glyph_info[i].codepoint];
 
-        if (cr==NULL)
-            cr = _prepare_char(tr->dev, tr->font, glyph_info[i].codepoint);
+               if (cr==NULL)
+                       cr = _prepare_char(tr->dev, tr->font, glyph_info[i].codepoint);
 
-        //continue;
-        if (cr!=NULL){
-            float uvWidth = cr->bounds.width / (float)FONT_PAGE_SIZE;
-            float uvHeight = cr->bounds.height / (float)FONT_PAGE_SIZE;
-            vec2 p0 = {pen.x + cr->bmpDiff.x + (tr->glyph_pos[i].x_offset >> 6),
-                       pen.y - cr->bmpDiff.y + (tr->glyph_pos[i].y_offset >> 6)};
-            v.pos = p0;
+               //continue;
+               if (cr!=NULL){
+                       float uvWidth = cr->bounds.width / (float)FONT_PAGE_SIZE;
+                       float uvHeight = cr->bounds.height / (float)FONT_PAGE_SIZE;
+                       vec2 p0 = {pen.x + cr->bmpDiff.x + (tr->glyph_pos[i].x_offset >> 6),
+                                          pen.y - cr->bmpDiff.y + (tr->glyph_pos[i].y_offset >> 6)};
+                       v.pos = p0;
 
-            VKVG_IBO_INDEX_TYPE firstIdx = (VKVG_IBO_INDEX_TYPE)(ctx->vertCount - ctx->curVertOffset);
+                       VKVG_IBO_INDEX_TYPE firstIdx = (VKVG_IBO_INDEX_TYPE)(ctx->vertCount - ctx->curVertOffset);
 
-            v.uv.x = cr->bounds.x;
-            v.uv.y = cr->bounds.y;
-            v.uv.z = cr->pageIdx;
-            _add_vertex(ctx,v);
+                       /*
+                       v.uv.x = cr->bounds.x;
+                       v.uv.y = cr->bounds.y;
+                       v.uv.z = cr->pageIdx;
+                       _add_vertex(ctx,v);
 
-            v.pos.y += cr->bounds.height;
-            v.uv.y += uvHeight;
-            _add_vertex(ctx,v);
+                       v.pos.y += cr->bounds.height;
+                       v.uv.y += uvHeight;
+                       _add_vertex(ctx,v);
 
-            v.pos.x += cr->bounds.width;
-            v.pos.y = p0.y;
-            v.uv.x += uvWidth;
-            v.uv.y = cr->bounds.y;
-            _add_vertex(ctx,v);
+                       v.pos.x += cr->bounds.width;
+                       v.pos.y = p0.y;
+                       v.uv.x += uvWidth;
+                       v.uv.y = cr->bounds.y;
+                       _add_vertex(ctx,v);
 
-            v.pos.y += cr->bounds.height;
-            v.uv.y += uvHeight;
-            _add_vertex(ctx,v);
+                       v.pos.y += cr->bounds.height;
+                       v.uv.y += uvHeight;
+                       _add_vertex(ctx,v);
+*/
+                       _add_tri_indices_for_rect (ctx, firstIdx);
+               }
 
-            _add_tri_indices_for_rect (ctx, firstIdx);
-        }
+               pen.x += (tr->glyph_pos[i].x_advance >> 6);
+               pen.y -= (tr->glyph_pos[i].y_advance >> 6);
+       }
 
-        pen.x += (tr->glyph_pos[i].x_advance >> 6);
-        pen.y -= (tr->glyph_pos[i].y_advance >> 6);
-    }
+       vkvg_move_to(ctx, pen.x, pen.y);
 
-    vkvg_move_to(ctx, pen.x, pen.y);
-
-    _flush_chars_to_tex(tr->dev, tr->font);
+       _flush_chars_to_tex(tr->dev, tr->font);
 }
 
 #ifdef DEBUG
 void _show_texture (vkvg_context* ctx){
-    Vertex vs[] = {
-        {{0,0},                             {0,0,0}},
-        {{0,FONT_PAGE_SIZE},                {0,1,0}},
-        {{FONT_PAGE_SIZE,0},                {1,0,0}},
-        {{FONT_PAGE_SIZE,FONT_PAGE_SIZE},   {1,1,0}}
-    };
+       Vertex vs[] = {
+               {{0,0},                             {0,0,0}},
+               {{0,FONT_PAGE_SIZE},                {0,1,0}},
+               {{FONT_PAGE_SIZE,0},                {1,0,0}},
+               {{FONT_PAGE_SIZE,FONT_PAGE_SIZE},   {1,1,0}}
+       };
 
-    VKVG_IBO_INDEX_TYPE i = (VKVG_IBO_INDEX_TYPE)ctx->vertCount;
+       VKVG_IBO_INDEX_TYPE i = (VKVG_IBO_INDEX_TYPE)ctx->vertCount;
 
-    _add_vertex(ctx,vs[0]);
-    _add_vertex(ctx,vs[1]);
-    _add_vertex(ctx,vs[2]);
-    _add_vertex(ctx,vs[3]);
+       _add_vertex(ctx,vs[0]);
+       _add_vertex(ctx,vs[1]);
+       _add_vertex(ctx,vs[2]);
+       _add_vertex(ctx,vs[3]);
 
-    _add_tri_indices_for_rect (ctx, i);
+       _add_tri_indices_for_rect (ctx, i);
 }
 #endif
 
 void _show_text (VkvgContext ctx, const char* text){
 
-    vkvg_text_run_t tr = {0};
-    _create_text_run (ctx, text, &tr);
+       vkvg_text_run_t tr = {0};
+       _create_text_run (ctx, text, &tr);
 
-    _show_text_run (ctx, &tr);
+       _show_text_run (ctx, &tr);
 
-    _destroy_text_run (&tr);
+       _destroy_text_run (&tr);
 
-    //_show_texture(ctx); return;
+       //_show_texture(ctx); return;
 }
 
 
 /*void testfonts(){
-    FT_Library      library;
-    FT_Face         face;
-    FT_GlyphSlot    slot;
+       FT_Library      library;
+       FT_Face         face;
+       FT_GlyphSlot    slot;
 
-    assert(!FT_Init_FreeType(&library));
-    assert(!FT_New_Face(library, "/usr/share/fonts/truetype/dejavu/DejaVuSansMono.ttf", 0, &face));
-    assert(!FT_Set_Char_Size(face, 0, ptSize, device_hdpi, device_vdpi ));
+       assert(!FT_Init_FreeType(&library));
+       assert(!FT_New_Face(library, "/usr/share/fonts/truetype/dejavu/DejaVuSansMono.ttf", 0, &face));
+       assert(!FT_Set_Char_Size(face, 0, ptSize, device_hdpi, device_vdpi ));
 
-    //_build_face_tex(face);
+       //_build_face_tex(face);
 
-    hb_font_t *hb_font = hb_ft_font_create(face, NULL);
-    hb_buffer_t *buf = hb_buffer_create();
+       hb_font_t *hb_font = hb_ft_font_create(face, NULL);
+       hb_buffer_t *buf = hb_buffer_create();
 
-    const char *text = "Ленивый рыжий кот";
-    const char *lng  = "en";
-    //"كسول الزنجبيل القط","懶惰的姜貓",
+       const char *text = "Ленивый рыжий кот";
+       const char *lng  = "en";
+       //"كسول الزنجبيل القط","懶惰的姜貓",
 
 
-    hb_buffer_set_direction (buf, HB_DIRECTION_LTR);
-    hb_buffer_set_script    (buf, HB_SCRIPT_LATIN);
-    hb_buffer_set_language  (buf, hb_language_from_string(lng,strlen(lng)));
-    hb_buffer_add_utf8      (buf, text, strlen(text), 0, strlen(text));
+       hb_buffer_set_direction (buf, HB_DIRECTION_LTR);
+       hb_buffer_set_script    (buf, HB_SCRIPT_LATIN);
+       hb_buffer_set_language  (buf, hb_language_from_string(lng,strlen(lng)));
+       hb_buffer_add_utf8      (buf, text, strlen(text), 0, strlen(text));
 
-    hb_unicode_funcs_t * unifc = hb_unicode_funcs_get_default();
-    hb_script_t sc = hb_buffer_get_script(buf);
+       hb_unicode_funcs_t * unifc = hb_unicode_funcs_get_default();
+       hb_script_t sc = hb_buffer_get_script(buf);
 
-    sc = hb_unicode_script(unifc,0x0260);
+       sc = hb_unicode_script(unifc,0x0260);
 
-    FT_CharMap* cm = face->charmap;
+       FT_CharMap* cm = face->charmap;
 
-    //hb_script_to_iso15924_tag()
+       //hb_script_to_iso15924_tag()
 
 
-    FT_Done_Face    ( face );
-    FT_Done_FreeType( library );
+       FT_Done_Face    ( face );
+       FT_Done_FreeType( library );
 }*/