summaryrefslogtreecommitdiffstatsci
diff options
context:
space:
mode:
authorJean-Philippe Bruyère <jp_bruyere@hotmail.com>2026-10-24 09:36:10 +0200
committerJean-Philippe Bruyère <jp_bruyere@hotmail.com>2026-10-24 09:47:23 +0200
commit86ddd9ba28461dad4cec23f01d2a0e5c1f44b0e8 (patch)
tree2b1b608ccec8a7e8d0cc881361037a448f3c662f
parent64bdd9f5b5a9d515de420830de085ff5203b9278 (diff)
save stencil only on reset with saved clips on stackµ
-rw-r--r--gunit_tests/save_restore.cpp157
-rw-r--r--samples/tests/clip.cpp2
-rw-r--r--samples/tests/save_restore.cpp83
-rw-r--r--src/vkvg_context.c146
-rw-r--r--src/vkvg_context_internal.h2
5 files changed, 304 insertions, 86 deletions
diff --git a/gunit_tests/save_restore.cpp b/gunit_tests/save_restore.cpp
index f82a208..39510bd 100644
--- a/gunit_tests/save_restore.cpp
+++ b/gunit_tests/save_restore.cpp
@@ -37,88 +37,189 @@ class SaveRestoreTest : public DrawTestBase {
float x = cos(a) * 256;
float y = sin(a) * 256;
+ vkvg_restore(ctx);
+ EXPECT_EQ(VKVG_STATUS_SUCCESS, vkvg_status(ctx));
+
vkvg_set_line_width(ctx, 2.f);
vkvg_move_to(ctx, 256.f - x, 256.f - y);
vkvg_line_to(ctx, 256.f + x, 256.f + y);
vkvg_set_source_rgba(ctx, 0.f, 1.f, 0.f, 0.6f);
vkvg_stroke(ctx);
- vkvg_restore(ctx);
- EXPECT_EQ(VKVG_STATUS_SUCCESS, vkvg_status(ctx));
-
depth--;
}
};
-TEST_F(SaveRestoreTest, RestoreClip1) {
+TEST_F(SaveRestoreTest, RecursePaint3) {
VkvgContext ctx = vkvg_create(surf);
- vkvg_arc(ctx, 140, 140, 100, 0, 2.f * M_PI);
- vkvg_clip(ctx);
- vkvg_save(ctx);
- vkvg_reset_clip(ctx);
- vkvg_restore(ctx);
- vkvg_set_source_surface(ctx, imgSurf, 0, 0);
- vkvg_paint(ctx);
- EXPECT_EQ(VKVG_STATUS_SUCCESS, vkvg_status(ctx));
+ EXPECT_NO_FATAL_FAILURE(recurse_draw(ctx, 0, 3));
+
vkvg_destroy(ctx);
compareWithRefImage();
}
-TEST_F(SaveRestoreTest, RecursePaint3) {
+TEST_F(SaveRestoreTest, RecursePaint10) {
VkvgContext ctx = vkvg_create(surf);
- EXPECT_NO_FATAL_FAILURE(recurse_draw(ctx, 0, 3));
+ EXPECT_NO_FATAL_FAILURE(recurse_draw(ctx, 0, 10));
vkvg_destroy(ctx);
compareWithRefImage();
}
-
-TEST_F(SaveRestoreTest, RecursePaint6) {
+TEST_F(SaveRestoreTest, RecursePaint20) {
VkvgContext ctx = vkvg_create(surf);
- EXPECT_NO_FATAL_FAILURE(recurse_draw(ctx, 0, 6));
+ EXPECT_NO_FATAL_FAILURE(recurse_draw(ctx, 0, 20));
vkvg_destroy(ctx);
compareWithRefImage();
}
-
-TEST_F(SaveRestoreTest, RecursePaint9) {
+TEST_F(SaveRestoreTest, NZ) {
VkvgContext ctx = vkvg_create(surf);
+ vkvg_set_fill_rule(ctx, VKVG_FILL_RULE_NON_ZERO);
- EXPECT_NO_FATAL_FAILURE(recurse_draw(ctx, 0, 9));
+ vkvg_rectangle(ctx, 50, 50, 200, 200);
+ vkvg_clip(ctx);
+
+ vkvg_set_source_rgb(ctx, 0, 0, 1);
+ vkvg_paint(ctx);
+
+ vkvg_rectangle(ctx, 0, 0, 220, 220);
+ vkvg_set_source_rgb(ctx, 1, 0, 0);
+ vkvg_fill(ctx);
vkvg_destroy(ctx);
compareWithRefImage();
}
-
-TEST_F(SaveRestoreTest, RecursePaint10) {
+TEST_F(SaveRestoreTest, NZ2) {
VkvgContext ctx = vkvg_create(surf);
+ vkvg_set_fill_rule(ctx, VKVG_FILL_RULE_NON_ZERO);
- EXPECT_NO_FATAL_FAILURE(recurse_draw(ctx, 0, 10));
+ vkvg_rectangle(ctx, 50, 50, 200, 200);
+ vkvg_clip(ctx);
+
+ vkvg_set_source_rgb(ctx, 0, 0, 1);
+ vkvg_paint(ctx);
+
+ vkvg_save(ctx);
+
+ vkvg_rectangle(ctx, 75, 75, 150, 150);
+ vkvg_clip(ctx);
+
+ vkvg_set_source_rgb(ctx, 0, 1, 0);
+ vkvg_paint(ctx);
+
+ vkvg_save(ctx);
+
+ vkvg_rectangle(ctx, 100, 100, 100, 100);
+ vkvg_clip(ctx);
+
+ vkvg_set_source_rgb(ctx, 1, 0, 0);
+ vkvg_paint(ctx);
+
+ vkvg_set_line_width(ctx, 40);
+ vkvg_set_source_rgb(ctx, 0, 0, 1);
+ vkvg_move_to(ctx, 0,0);
+ vkvg_line_to(ctx, 512,512);
+ vkvg_stroke_preserve(ctx);
+
+ vkvg_restore(ctx);
+
+ vkvg_set_line_width(ctx, 30);
+ vkvg_set_source_rgb(ctx, 0, 0, 0);
+ vkvg_stroke_preserve(ctx);
+
+ vkvg_restore(ctx);
+
+ vkvg_set_line_width(ctx, 20);
+ vkvg_set_source_rgb(ctx, 1, 0, 0);
+ vkvg_stroke(ctx);
vkvg_destroy(ctx);
compareWithRefImage();
}
-TEST_F(SaveRestoreTest, RecursePaint11) {
+TEST_F(SaveRestoreTest, ResetNZ) {
VkvgContext ctx = vkvg_create(surf);
+ vkvg_set_fill_rule(ctx, VKVG_FILL_RULE_NON_ZERO);
+ vkvg_set_line_width(ctx, 20);
+
+ vkvg_rectangle(ctx, 50, 50, 200, 200);
+ vkvg_clip(ctx);
+
+ vkvg_set_source_rgb(ctx, 0, 0, 1);
+ vkvg_paint(ctx);
+
+ vkvg_save(ctx);
+
+ vkvg_rectangle(ctx, 75, 75, 150, 150);
+ vkvg_clip(ctx);
+
+ vkvg_set_source_rgb(ctx, 0, 1, 0);
+ vkvg_paint(ctx);
+
+ vkvg_reset_clip(ctx);
+
+ vkvg_set_source_rgb(ctx, 1, 1, 0);
+ vkvg_move_to(ctx, 512,0);
+ vkvg_line_to(ctx, 0,512);
+ vkvg_stroke(ctx);
+
+ vkvg_restore(ctx);
- EXPECT_NO_FATAL_FAILURE(recurse_draw(ctx, 0, 11));
+ vkvg_set_source_rgb(ctx, 1, 0, 0);
+ vkvg_move_to(ctx, 0,0);
+ vkvg_line_to(ctx, 512,512);
+ vkvg_stroke(ctx);
vkvg_destroy(ctx);
compareWithRefImage();
}
-TEST_F(SaveRestoreTest, RecursePaint20) {
+TEST_F(SaveRestoreTest, ResetNZ2) {
VkvgContext ctx = vkvg_create(surf);
+ vkvg_set_fill_rule(ctx, VKVG_FILL_RULE_NON_ZERO);
+ vkvg_set_line_width(ctx, 20);
- EXPECT_NO_FATAL_FAILURE(recurse_draw(ctx, 0, 20));
+ vkvg_rectangle(ctx, 50, 50, 200, 200);
+ vkvg_clip(ctx);
+
+ vkvg_set_source_rgb(ctx, 0, 0, 1);
+ vkvg_paint(ctx);
+
+ vkvg_save(ctx);
+
+ vkvg_rectangle(ctx, 75, 75, 150, 150);
+ vkvg_clip(ctx);
+
+ vkvg_set_source_rgb(ctx, 0, 1, 0);
+ vkvg_paint(ctx);
+
+ vkvg_reset_clip(ctx);
+
+ vkvg_set_source_rgb(ctx, 1, 1, 0);
+ vkvg_move_to(ctx, 512,0);
+ vkvg_line_to(ctx, 0,512);
+ vkvg_stroke(ctx);
+
+ vkvg_rectangle(ctx, 85, 20, 30, 260);
+ vkvg_clip(ctx);
+
+ vkvg_set_source_rgb(ctx, 1, 0, 0);
+ vkvg_paint(ctx);
+
+ vkvg_restore(ctx);
+
+ vkvg_set_source_rgb(ctx, 1, 0, 1);
+ vkvg_move_to(ctx, 0,0);
+ vkvg_line_to(ctx, 512,512);
+ vkvg_stroke(ctx);
vkvg_destroy(ctx);
compareWithRefImage();
-}
+} \ No newline at end of file
diff --git a/samples/tests/clip.cpp b/samples/tests/clip.cpp
index 0008dc0..c57c8e2 100644
--- a/samples/tests/clip.cpp
+++ b/samples/tests/clip.cpp
@@ -22,7 +22,7 @@ TEST(clipped_paint_eo) {
vkvg_destroy(ctx);
}
-TEST(clipped_paint2_nz) {
+TEST(clip_reset_nz) {
VkvgContext ctx = vkvg_create(test->surf);
vkvg_set_fill_rule(ctx, VKVG_FILL_RULE_NON_ZERO);
vkvg_set_source_rgb(ctx, 1, 0, 0);
diff --git a/samples/tests/save_restore.cpp b/samples/tests/save_restore.cpp
index 66168cb..2b0db35 100644
--- a/samples/tests/save_restore.cpp
+++ b/samples/tests/save_restore.cpp
@@ -38,14 +38,14 @@ void recurse_draw_clipped(VkvgContext ctx, int depth, int maxDepth) {
float x = cos(a) * 256;
float y = sin(a) * 256;
+ vkvg_restore(ctx);
+
vkvg_set_line_width(ctx, 2.f);
vkvg_move_to(ctx, 256.f - x, 256.f - y);
vkvg_line_to(ctx, 256.f + x, 256.f + y);
vkvg_set_source_rgba(ctx, 0.f, 1.f, 0.f, 0.6f);
vkvg_stroke(ctx);
- vkvg_restore(ctx);
-
depth--;
}
@@ -133,14 +133,83 @@ TEST(save_restrore_nz2) {
vkvg_set_line_width(ctx, 20);
vkvg_set_source_rgb(ctx, 1, 0, 0);
- vkvg_stroke_preserve(ctx);
+ vkvg_stroke(ctx);
- /*vkvg_restore(ctx);
+ vkvg_destroy(ctx);
+}
+TEST(save_restrore_clip_reset_nz) {
+ VkvgContext ctx = vkvg_create(test->surf);
+ vkvg_set_fill_rule(ctx, VKVG_FILL_RULE_NON_ZERO);
+ vkvg_set_line_width(ctx, 20);
- vkvg_set_line_width(ctx, 10);
- vkvg_set_source_rgb(ctx, 1, 1, 0);
- vkvg_stroke(ctx);*/
+ vkvg_rectangle(ctx, 50, 50, 200, 200);
+ vkvg_clip(ctx);
+
+ vkvg_set_source_rgb(ctx, 0, 0, 1);
+ vkvg_paint(ctx);
+
+ vkvg_save(ctx);
+
+ vkvg_rectangle(ctx, 75, 75, 150, 150);
+ vkvg_clip(ctx);
+
+ vkvg_set_source_rgb(ctx, 0, 1, 0);
+ vkvg_paint(ctx);
+
+ vkvg_reset_clip(ctx);
+
+ vkvg_set_source_rgb(ctx, 1, 1, 0);
+ vkvg_move_to(ctx, 512,0);
+ vkvg_line_to(ctx, 0,512);
+ vkvg_stroke(ctx);
+
+ vkvg_restore(ctx);
+
+ vkvg_set_source_rgb(ctx, 1, 0, 0);
+ vkvg_move_to(ctx, 0,0);
+ vkvg_line_to(ctx, 512,512);
+ vkvg_stroke(ctx);
vkvg_destroy(ctx);
}
+TEST(save_restrore_clip_reset2_nz) {
+ VkvgContext ctx = vkvg_create(test->surf);
+ vkvg_set_fill_rule(ctx, VKVG_FILL_RULE_NON_ZERO);
+ vkvg_set_line_width(ctx, 20);
+
+ vkvg_rectangle(ctx, 50, 50, 200, 200);
+ vkvg_clip(ctx);
+
+ vkvg_set_source_rgb(ctx, 0, 0, 1);
+ vkvg_paint(ctx);
+
+ vkvg_save(ctx);
+
+ vkvg_rectangle(ctx, 75, 75, 150, 150);
+ vkvg_clip(ctx);
+ vkvg_set_source_rgb(ctx, 0, 1, 0);
+ vkvg_paint(ctx);
+
+ vkvg_reset_clip(ctx);
+
+ vkvg_set_source_rgb(ctx, 1, 1, 0);
+ vkvg_move_to(ctx, 512,0);
+ vkvg_line_to(ctx, 0,512);
+ vkvg_stroke(ctx);
+
+ vkvg_rectangle(ctx, 85, 20, 30, 260);
+ vkvg_clip(ctx);
+
+ vkvg_set_source_rgb(ctx, 1, 0, 0);
+ vkvg_paint(ctx);
+
+ vkvg_restore(ctx);
+
+ vkvg_set_source_rgb(ctx, 1, 0, 1);
+ vkvg_move_to(ctx, 0,0);
+ vkvg_line_to(ctx, 512,512);
+ vkvg_stroke(ctx);
+
+ vkvg_destroy(ctx);
+} \ No newline at end of file
diff --git a/src/vkvg_context.c b/src/vkvg_context.c
index 51f3a04..8f35871 100644
--- a/src/vkvg_context.c
+++ b/src/vkvg_context.c
@@ -208,23 +208,24 @@ void _clear_context(VkvgContext ctx) {
// free saved context stack elmt
while (ctx->ctxSaveCount > 0) {
ctx->ctxSaveCount--;
- pat = ctx->pSavedCtxs[ctx->ctxSaveCount].pattern;
- if (pat)
- vkvg_pattern_destroy(pat);
- font = ctx->pSavedCtxs[ctx->ctxSaveCount].currentFont;
- if (font)
- vkvg_font_destroy(font);
+ vkvg_context_save_t* sav = &ctx->pSavedCtxs[ctx->ctxSaveCount];
+ if (sav->pattern)
+ vkvg_pattern_destroy(sav->pattern);
+ if (sav->currentFont)
+ vkvg_font_destroy(sav->currentFont);
+ if (sav->stencil)
+ vkh_image_destroy(sav->stencil);
}
// free additional stencil use in save/restore process
- if (ctx->savedStencils) {
+ /*if (ctx->savedStencils) {
uint8_t curSaveStencil = ctx->curSavBit / 6;
for (int i = curSaveStencil; i > 0; i--)
vkh_image_destroy(ctx->savedStencils[i - 1]);
free(ctx->savedStencils);
ctx->savedStencils = NULL;
ctx->curSavBit = 0;
- }
+ }*/
}
void vkvg_destroy(VkvgContext ctx) {
@@ -728,17 +729,66 @@ static const VkClearAttachment clearStencil = {VK_IMAGE_ASPECT_STENCIL_BIT,
static const VkClearAttachment clearColorAttach = {VK_IMAGE_ASPECT_COLOR_BIT, 0, {{{0}}}};
void _reset_clip(VkvgContext ctx) {
+ if (ctx->curClipRef == 0)
+ return; //nothing to do
+
_emit_draw_cmd_undrawn_vertices(ctx);
+
+ if (ctx->ctxSaveCount > 0) {
+ vkvg_context_save_t* sav = &ctx->pSavedCtxs[ctx->ctxSaveCount - 1];
+ if (sav->curClipRef > 0) {
+ //cur stencil must be saved
+ _flush_cmd_buff(ctx);
+ _wait_ctx_flush_end(ctx);
+
+ VkvgDevice dev = ctx->dev;
+ sav->stencil = vkh_image_ms_create(
+ dev->vkhDev, dev->stencilFormat, ctx->pSurf->surfClass->samples, ctx->pSurf->width, ctx->pSurf->height,
+ VKH_MEMORY_USAGE_GPU_ONLY, VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT);
+ vkh_cmd_begin(ctx->cmd, VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT);
+ ctx->cmdStarted = true;
+
+#if defined(DEBUG) && defined(VKVG_DBG_UTILS)
+ vkh_cmd_label_start(ctx->cmd, "new save/restore stencil", DBG_LAB_COLOR_SAV);
+#endif
+
+ vkh_image_set_layout(ctx->cmd, ctx->pSurf->stencil, dev->stencilAspectFlag,
+ VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
+ VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT);
+ vkh_image_set_layout(ctx->cmd, sav->stencil, dev->stencilAspectFlag, VK_IMAGE_LAYOUT_GENERAL,
+ VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT,
+ VK_PIPELINE_STAGE_TRANSFER_BIT);
+
+ VkImageCopy cregion = {.srcSubresource = {VK_IMAGE_ASPECT_STENCIL_BIT, 0, 0, 1},
+ .dstSubresource = {VK_IMAGE_ASPECT_STENCIL_BIT, 0, 0, 1},
+ .extent = {ctx->pSurf->width, ctx->pSurf->height, 1}};
+ vkCmdCopyImage(ctx->cmd, vkh_image_get_vkimage(ctx->pSurf->stencil), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
+ vkh_image_get_vkimage(sav->stencil), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &cregion);
+
+ vkh_image_set_layout(ctx->cmd, ctx->pSurf->stencil, dev->stencilAspectFlag,
+ VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
+ VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT);
+
+#if defined(DEBUG) && defined(VKVG_DBG_UTILS)
+ vkh_cmd_label_end(ctx->cmd);
+#endif
+ VK_CHECK_RESULT(vkEndCommandBuffer(ctx->cmd));
+ _wait_and_submit_cmd(ctx);
+ }
+ }
+
ctx->curClipRef = 0;
- if (!ctx->cmdStarted) {
+
+ if (ctx->cmdStarted) {
+ vkCmdClearAttachments(ctx->cmd, 1, &clearStencil, 1, &ctx->clearRect);
+ CmdSetStencilReference(ctx->cmd, VK_STENCIL_FRONT_AND_BACK, ctx->curClipRef);
+ } else {
// if command buffer is not already started and in a renderpass, we use the renderpass
// with the loadop clear for stencil
ctx->renderPassBeginInfo.renderPass = ctx->pSurf->surfClass->renderPass_ClearStencil;
// force run of one renderpass (even empty) to perform clear load op
_start_cmd_for_render_pass(ctx);
- return;
}
- vkCmdClearAttachments(ctx->cmd, 1, &clearStencil, 1, &ctx->clearRect);
}
void vkvg_reset_clip(VkvgContext ctx) {
@@ -747,12 +797,12 @@ void vkvg_reset_clip(VkvgContext ctx) {
RECORD(ctx, VKVG_CMD_RESET_CLIP);
- if (ctx->curClipState == vkvg_clip_state_clear)
+ /*if (ctx->curClipState == vkvg_clip_state_clear)
return;
if (_get_previous_clip_state(ctx) == vkvg_clip_state_clear)
ctx->curClipState = vkvg_clip_state_none;
else
- ctx->curClipState = vkvg_clip_state_clear;
+ ctx->curClipState = vkvg_clip_state_clear;*/
_reset_clip(ctx);
}
@@ -1328,20 +1378,22 @@ void vkvg_save(VkvgContext ctx) {
return;
}*/
- sav->curClipRef = ctx->curClipRef;
+ /*
if (ctx->curClipState == vkvg_clip_state_clip) {
sav->clippingState = vkvg_clip_state_clip_saved;
} else if (ctx->curClipState == vkvg_clip_state_none)
sav->clippingState = (_get_previous_clip_state(ctx) & 0x03);
else
- sav->clippingState = vkvg_clip_state_clear;
+ sav->clippingState = vkvg_clip_state_clear;*/
memcpy((void*)sav, (void*)&(ctx->curColor), (void*)&(ctx->indCount) - (void*)&(ctx->curColor));
+ sav->curClipRef = ctx->curClipRef;
if (ctx->pattern)
vkvg_pattern_reference(ctx->pattern);
if (ctx->currentFont)
vkvg_font_reference(ctx->currentFont);
+ sav->stencil = NULL;
ctx->ctxSaveCount++;
}
@@ -1360,56 +1412,52 @@ void vkvg_restore(VkvgContext ctx) {
vkvg_context_save_t* sav = &ctx->pSavedCtxs[ctx->ctxSaveCount-1];
- //_flush_cmd_buff(ctx);
_emit_draw_cmd_undrawn_vertices(ctx);
ctx->curClipRef = sav->curClipRef;
- if (ctx->cmdStarted)
- CmdSetStencilReference(ctx->cmd, VK_STENCIL_FRONT_AND_BACK, ctx->curClipRef);
-
- if (ctx->curClipState) { //!=none
-
- /*if (!_wait_ctx_flush_end(ctx))
- return;
-
- if (ctx->curClipState == vkvg_clip_state_clip && sav->clippingState == vkvg_clip_state_clear) {
- _reset_clip(ctx);
- } else {
- uint8_t curSaveBit = 1 << ((ctx->curSavBit - 1) % 6 + 2);
+ if (sav->stencil) {
+ //restore stencil
+ _flush_cmd_buff(ctx);
+ _wait_ctx_flush_end(ctx);
- //ctx->renderPassBeginInfo.renderPass = ctx->pSurf->surfClass->renderPass_ClearStencil;
- _start_cmd_for_render_pass(ctx);
+ vkh_cmd_begin(ctx->cmd, VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT);
+ ctx->cmdStarted = true;
#if defined(DEBUG) && defined(VKVG_DBG_UTILS)
- vkh_cmd_label_start(ctx->cmd, "restore rp", DBG_LAB_COLOR_SAV);
+ vkh_cmd_label_start(ctx->cmd, "additional stencil copy while restoring", DBG_LAB_COLOR_SAV);
#endif
- CmdBindPipeline(ctx->cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, ctx->pSurf->surfClass->pipelineClipping);
-
- CmdSetStencilReference(ctx->cmd, VK_STENCIL_FRONT_AND_BACK, STENCIL_CLIP_BIT | curSaveBit);
- CmdSetStencilCompareMask(ctx->cmd, VK_STENCIL_FRONT_AND_BACK, curSaveBit);
- CmdSetStencilWriteMask(ctx->cmd, VK_STENCIL_FRONT_AND_BACK, STENCIL_CLIP_BIT);
-
- _draw_full_screen_quad(ctx, NULL);
+ vkh_image_set_layout(ctx->cmd, ctx->pSurf->stencil, ctx->dev->stencilAspectFlag,
+ VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
+ VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT);
+ vkh_image_set_layout(ctx->cmd, sav->stencil, ctx->dev->stencilAspectFlag,
+ VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
+ VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT);
- _bind_draw_pipeline(ctx);
- CmdSetStencilCompareMask(ctx->cmd, VK_STENCIL_FRONT_AND_BACK, STENCIL_CLIP_BIT);
+ VkImageCopy cregion = {.srcSubresource = {VK_IMAGE_ASPECT_STENCIL_BIT, 0, 0, 1},
+ .dstSubresource = {VK_IMAGE_ASPECT_STENCIL_BIT, 0, 0, 1},
+ .extent = {ctx->pSurf->width, ctx->pSurf->height, 1}};
+ vkCmdCopyImage(ctx->cmd, vkh_image_get_vkimage(sav->stencil), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
+ vkh_image_get_vkimage(ctx->pSurf->stencil), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1,
+ &cregion);
+ vkh_image_set_layout(ctx->cmd, ctx->pSurf->stencil, ctx->dev->stencilAspectFlag,
+ VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
+ VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT);
#if defined(DEBUG) && defined(VKVG_DBG_UTILS)
- vkh_cmd_label_end(ctx->cmd);
+ vkh_cmd_label_end(ctx->cmd);
#endif
- _flush_cmd_buff(ctx);
- if (!_wait_ctx_flush_end(ctx))
- return;
- }*/
- }
- if (sav->clippingState == vkvg_clip_state_clip_saved) {
-
+ VK_CHECK_RESULT(vkEndCommandBuffer(ctx->cmd));
+ _wait_and_submit_cmd(ctx);
+ if (!_wait_ctx_flush_end(ctx))
+ return;
+ vkh_image_destroy(sav->stencil);
}
- ctx->curClipState = vkvg_clip_state_none;
+ if (ctx->cmdStarted)
+ CmdSetStencilReference(ctx->cmd, VK_STENCIL_FRONT_AND_BACK, ctx->curClipRef);
memcpy((void*)&(ctx->curColor), (void*)sav, (void*)&(ctx->pattern) - (void*)&(ctx->curColor));
diff --git a/src/vkvg_context_internal.h b/src/vkvg_context_internal.h
index 79f3bd3..b4f5f43 100644
--- a/src/vkvg_context_internal.h
+++ b/src/vkvg_context_internal.h
@@ -101,6 +101,7 @@ typedef struct _vkvg_context_save_t {
VkvgFont currentFont;
vkvg_clip_state_t clippingState;
uint32_t curClipRef;
+ VkhImage stencil;
} vkvg_context_save_t;
typedef struct _vkvg_context_t {
@@ -199,7 +200,6 @@ typedef struct _vkvg_context_t {
vkvg_clip_state_t curClipState; // current clipping status relative to the previous saved one or clear state if
uint32_t curClipRef;
- uint32_t savedClipOffset;
VkhImage* savedStencils; // additional image for saving contexes once more than 6 save/restore are reached
VkRenderPassBeginInfo renderPassBeginInfo;