summaryrefslogtreecommitdiffstatsci
path: root/src
diff options
context:
space:
mode:
authorJean-Philippe Bruyère <jp_bruyere@hotmail.com>2022-01-13 07:52:37 +0100
committerJean-Philippe Bruyère <jp_bruyere@hotmail.com>2022-01-13 07:52:37 +0100
commit89d10c294a8bcb2a66ce98a6319e90fac57786b5 (patch)
treed4f77f01c599b6d20b3810c817a12e591030c71b /src
parent80e9cd4e91f93df0e53e6fa75af4c2e2f8e388f2 (diff)
vkvg_clip_state_t implementation
Diffstat (limited to 'src')
-rw-r--r--src/vkvg_context.c184
-rw-r--r--src/vkvg_context_internal.h12
2 files changed, 119 insertions, 77 deletions
diff --git a/src/vkvg_context.c b/src/vkvg_context.c
index a0b6e3a..2cb248b 100644
--- a/src/vkvg_context.c
+++ b/src/vkvg_context.c
@@ -663,16 +663,15 @@ void vkvg_path_extents (VkvgContext ctx, float *x1, float *y1, float *x2, float
_vkvg_path_extents(ctx, false, x1, y1, x2, y2);
}
-
+vkvg_clip_state_t _get_previous_clip_state (VkvgContext ctx) {
+ if (!ctx->pSavedCtxs)//no clip saved => clear
+ return vkvg_clip_state_clear;
+ return ctx->pSavedCtxs->clippingState;
+}
static const VkClearAttachment clearStencil = {VK_IMAGE_ASPECT_STENCIL_BIT, 1, {{{0}}}};
static const VkClearAttachment clearColorAttach = {VK_IMAGE_ASPECT_COLOR_BIT, 0, {{{0}}}};
-void vkvg_reset_clip (VkvgContext ctx){
- if (ctx->status)
- return;
- if (!(ctx->isClipped || ctx->curSavBit))//if not clipped and no clipping has been saved, nothing to reset
- return;
- RECORD(ctx, VKVG_CMD_RESET_CLIP);
+void _reset_clip (VkvgContext ctx) {
_emit_draw_cmd_undrawn_vertices(ctx);
if (!ctx->cmdStarted) {
//if command buffer is not already started and in a renderpass, we use the renderpass
@@ -683,13 +682,34 @@ void vkvg_reset_clip (VkvgContext ctx){
return;
}
vkCmdClearAttachments(ctx->cmd, 1, &clearStencil, 1, &ctx->clearRect);
- if (!ctx->curSavBit)//if another clipping has been saved, reset preserve isClipped=true
- ctx->isClipped = false;
+}
+
+void vkvg_reset_clip (VkvgContext ctx){
+ if (ctx->status)
+ return;
+
+ RECORD(ctx, VKVG_CMD_RESET_CLIP);
+
+ 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;
+
+ _reset_clip (ctx);
}
void vkvg_clear (VkvgContext ctx){
if (ctx->status)
return;
+
RECORD(ctx, VKVG_CMD_CLEAR);
+
+ if (_get_previous_clip_state(ctx) == vkvg_clip_state_clear)
+ ctx->curClipState = vkvg_clip_state_none;
+ else
+ ctx->curClipState = vkvg_clip_state_clear;
+
_emit_draw_cmd_undrawn_vertices(ctx);
if (!ctx->cmdStarted) {
ctx->renderPassBeginInfo.renderPass = ctx->pSurf->dev->renderPass_ClearAll;
@@ -698,9 +718,6 @@ void vkvg_clear (VkvgContext ctx){
}
VkClearAttachment ca[2] = {clearColorAttach, clearStencil};
vkCmdClearAttachments(ctx->cmd, 2, ca, 1, &ctx->clearRect);
-
- if (!ctx->curSavBit)//if another clipping has been saved, reset preserve isClipped=true
- ctx->isClipped = false;
}
void _clip_preserve (VkvgContext ctx){
_finish_path(ctx);
@@ -741,7 +758,8 @@ void _clip_preserve (VkvgContext ctx){
#if defined(DEBUG) && defined (VKVG_DBG_UTILS)
vkh_cmd_label_end (ctx->cmd);
#endif
- ctx->isClipped = true;
+
+ ctx->curClipState = vkvg_clip_state_clip;
}
void _fill_preserve (VkvgContext ctx){
_finish_path(ctx);
@@ -1142,15 +1160,15 @@ void vkvg_save (VkvgContext ctx){
VkvgDevice dev = ctx->pSurf->dev;
vkvg_context_save_t* sav = (vkvg_context_save_t*)calloc(1,sizeof(vkvg_context_save_t));
- if (ctx->isClipped) {
+ _flush_cmd_buff (ctx);
+ if (!_wait_flush_fence (ctx)) {
+ free (sav);
+ return;
+ }
- _flush_cmd_buff (ctx);
- if (!_wait_flush_fence (ctx)) {
- free (sav);
- return;
- }
+ if (ctx->curClipState == vkvg_clip_state_clip) {
+ sav->clippingState = vkvg_clip_state_clip_saved;
- sav->clippingState = true;
uint8_t curSaveStencil = ctx->curSavBit / 6;
if (ctx->curSavBit > 0 && ctx->curSavBit % 6 == 0){//new save/restore stencil image have to be created
@@ -1222,7 +1240,11 @@ void vkvg_save (VkvgContext ctx){
vkh_cmd_label_end (ctx->cmd);
#endif
ctx->curSavBit++;
- }
+ } else if (ctx->curClipState == vkvg_clip_state_none)
+ sav->clippingState = (_get_previous_clip_state(ctx) & 0x03);
+ else
+ sav->clippingState = vkvg_clip_state_clear;
+
sav->dashOffset = ctx->dashOffset;
sav->dashCount = ctx->dashCount;
if (ctx->dashCount > 0) {
@@ -1242,17 +1264,20 @@ void vkvg_save (VkvgContext ctx){
sav->currentFont = ctx->currentFont;
sav->textDirection= ctx->textDirection;
sav->pushConsts = ctx->pushConsts;
- //sav->pattern = ctx->pattern;//TODO:pattern sav must be imutable (copy?)
+ if (ctx->pattern) {
+ sav->pattern = ctx->pattern;//TODO:pattern sav must be imutable (copy?)
+ vkvg_pattern_reference (ctx->pattern);
+ } else
+ sav->curColor = ctx->curColor;
sav->pNext = ctx->pSavedCtxs;
ctx->pSavedCtxs = sav;
- /*if (ctx->pattern)
- vkvg_pattern_reference (ctx->pattern);*/
}
void vkvg_restore (VkvgContext ctx){
if (ctx->status)
return;
+
RECORD(ctx, VKVG_CMD_RESTORE);
if (ctx->pSavedCtxs == NULL){
@@ -1265,27 +1290,25 @@ void vkvg_restore (VkvgContext ctx){
vkvg_context_save_t* sav = ctx->pSavedCtxs;
ctx->pSavedCtxs = sav->pNext;
+ _flush_cmd_buff (ctx);
+ if (!_wait_flush_fence (ctx))
+ return;
+
ctx->pushConsts = sav->pushConsts;
ctx->pushCstDirty = true;
- /*if (sav->pattern)
- _update_cur_pattern (ctx, sav->pattern);*/
-
- if (ctx->isClipped) {//previous clipping state has to be restored
- if (!ctx->curSavBit) {//no clipping state has been saved, clipping has to be reseted
- vkvg_reset_clip (ctx);
+ if (ctx->curClipState) {//!=none
+ if (ctx->curClipState == vkvg_clip_state_clip && sav->clippingState == vkvg_clip_state_clear) {
+ _reset_clip (ctx);
} else {
- _flush_cmd_buff (ctx);
- if (!_wait_flush_fence (ctx))
- return;
uint8_t curSaveBit = 1 << ((ctx->curSavBit-1) % 6 + 2);
_start_cmd_for_render_pass (ctx);
- #if defined(DEBUG) && defined (VKVG_DBG_UTILS)
+#if defined(DEBUG) && defined (VKVG_DBG_UTILS)
vkh_cmd_label_start(ctx->cmd, "restore rp", DBG_LAB_COLOR_SAV);
- #endif
+#endif
CmdBindPipeline (ctx->cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, ctx->pSurf->dev->pipelineClipping);
@@ -1298,60 +1321,61 @@ void vkvg_restore (VkvgContext ctx){
_bind_draw_pipeline (ctx);
CmdSetStencilCompareMask (ctx->cmd, VK_STENCIL_FRONT_AND_BACK, STENCIL_CLIP_BIT);
- #if defined(DEBUG) && defined (VKVG_DBG_UTILS)
+#if defined(DEBUG) && defined (VKVG_DBG_UTILS)
vkh_cmd_label_end (ctx->cmd);
- #endif
+#endif
_flush_cmd_buff (ctx);
if (!_wait_flush_fence (ctx))
return;
+ }
+ }
+ if (sav->clippingState == vkvg_clip_state_clip_saved) {
+ ctx->curSavBit--;
- if (sav->clippingState) {//if clipping is saved on that level, process savebit decrease
- ctx->curSavBit--;
-
-
- uint8_t curSaveStencil = ctx->curSavBit / 6;
- if (ctx->curSavBit > 0 && ctx->curSavBit % 6 == 0){//addtional save/restore stencil image have to be copied back to surf stencil first
- VkhImage savStencil = ctx->savedStencils[curSaveStencil-1];
+ uint8_t curSaveStencil = ctx->curSavBit / 6;
+ if (ctx->curSavBit > 0 && ctx->curSavBit % 6 == 0){//addtional save/restore stencil image have to be copied back to surf stencil first
+ VkhImage savStencil = ctx->savedStencils[curSaveStencil-1];
- vkh_cmd_begin (ctx->cmd, VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT);
- ctx->cmdStarted = true;
+ 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, "additional stencil copy while restoring", DBG_LAB_COLOR_SAV);
- #endif
+#if defined(DEBUG) && defined (VKVG_DBG_UTILS)
+ vkh_cmd_label_start(ctx->cmd, "additional stencil copy while restoring", DBG_LAB_COLOR_SAV);
+#endif
- vkh_image_set_layout (ctx->cmd, ctx->pSurf->stencil, VK_IMAGE_ASPECT_STENCIL_BIT,
- 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, savStencil, VK_IMAGE_ASPECT_STENCIL_BIT,
- VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
- VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT);
+ vkh_image_set_layout (ctx->cmd, ctx->pSurf->stencil, VK_IMAGE_ASPECT_STENCIL_BIT,
+ 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, savStencil, VK_IMAGE_ASPECT_STENCIL_BIT,
+ VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
+ VK_PIPELINE_STAGE_TRANSFER_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 (savStencil), 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, VK_IMAGE_ASPECT_STENCIL_BIT,
- 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);
+ 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 (savStencil), 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, VK_IMAGE_ASPECT_STENCIL_BIT,
+ 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);
- #endif
+#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);
- if (!_wait_flush_fence (ctx))
- return;
- vkh_image_destroy (savStencil);
- }
- }
+ VK_CHECK_RESULT(vkEndCommandBuffer(ctx->cmd));
+ _wait_and_submit_cmd (ctx);
+ if (!_wait_flush_fence (ctx))
+ return;
+ vkh_image_destroy (savStencil);
}
}
+
+ ctx->curClipState = vkvg_clip_state_none;
+
ctx->dashOffset = sav->dashOffset;
if (ctx->dashCount > 0)
free (ctx->dashes);
@@ -1373,6 +1397,16 @@ void vkvg_restore (VkvgContext ctx){
ctx->currentFont = sav->currentFont;
ctx->textDirection= sav->textDirection;
+ if (sav->pattern) {
+ if (sav->pattern != ctx->pattern)
+ _update_cur_pattern (ctx, sav->pattern);
+ else
+ vkvg_pattern_destroy(sav->pattern);
+ } else {
+ ctx->curColor = sav->curColor;
+ _update_cur_pattern (ctx, NULL);
+ }
+
_free_ctx_save(sav);
}
diff --git a/src/vkvg_context_internal.h b/src/vkvg_context_internal.h
index 8a94d8c..52fa767 100644
--- a/src/vkvg_context_internal.h
+++ b/src/vkvg_context_internal.h
@@ -80,6 +80,13 @@ typedef struct {
vkvg_matrix_t matInv;
}push_constants;
+typedef enum {
+ vkvg_clip_state_none = 0x00,
+ vkvg_clip_state_clear = 0x01,
+ vkvg_clip_state_clip = 0x02,
+ vkvg_clip_state_clip_saved = 0x06,
+} vkvg_clip_state_t;
+
typedef struct _vkvg_context_save_t{
struct _vkvg_context_save_t* pNext;
@@ -100,8 +107,9 @@ typedef struct _vkvg_context_save_t{
_vkvg_font_identity_t* currentFont; //font ready for lookup
vkvg_direction_t textDirection;
push_constants pushConsts;
+ uint32_t curColor;
VkvgPattern pattern;
- bool clippingState; //true if previous clipping region as been saved
+ vkvg_clip_state_t clippingState;
}vkvg_context_save_t;
@@ -198,10 +206,10 @@ typedef struct _vkvg_context_t {
vkvg_context_save_t* pSavedCtxs; //last ctx saved ptr
uint8_t curSavBit; //current stencil bit used to save context, 6 bits used by stencil for save/restore
VkhImage* savedStencils; //additional image for saving contexes once more than 6 save/restore are reached
+ vkvg_clip_state_t curClipState; //current clipping status relative to the previous saved one or clear state if none.
VkClearRect clearRect;
VkRenderPassBeginInfo renderPassBeginInfo;
- bool isClipped; //true if clipped since the last clip reset or last save
}vkvg_context;
typedef struct _ear_clip_point{