ctx->pointCount -= ctx->pathes[ctx->pathPtr];//what about the bounds?
ctx->pathes[ctx->pathPtr] = 0;
ctx->segmentPtr = 0;
+ ctx->curPathDotSignPos = ctx->curPathIsConcave = false;
return;
}
+ if (ctx->curPathIsConcave)
+ ctx->pathes[ctx->pathPtr] |= PATH_IS_CONCAVE_BIT;
+ ctx->curPathDotSignPos = ctx->curPathIsConcave = false;
+
if (ctx->segmentPtr > 0) {
ctx->pathes[ctx->pathPtr] |= PATH_HAS_CURVES_BIT;
//if last segment is not a curve and point count > 0
ctx->pathes [ctx->pathPtr] = 0;
ctx->pointCount = 0;
ctx->segmentPtr = 0;
+ ctx->curPathDotSignPos = ctx->curPathIsConcave = false;
_resetMinMax(ctx);
}
void _remove_last_point (VkvgContext ctx){
void _bind_draw_pipeline (VkvgContext ctx) {
switch (ctx->curOperator) {
case VKVG_OPERATOR_OVER:
- CmdBindPipeline(ctx->cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, ctx->pSurf->dev->pipe_OVER);
+ CmdBindPipeline(ctx->cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, ctx->pSurf->dev->pipe_TF_OVER);
break;
case VKVG_OPERATOR_CLEAR:
vkvg_set_source_rgba(ctx,0,0,0,0);
uint32_t pathPointCount = ctx->pathes[ptrPath] & PATH_ELT_MASK;
- VKVG_IBO_INDEX_TYPE firstVertIdx = (VKVG_IBO_INDEX_TYPE)(ctx->vertCount - ctx->curVertOffset);
- ear_clip_point* ecps = (ear_clip_point*)malloc(pathPointCount*sizeof(ear_clip_point));
- uint32_t ecps_count = pathPointCount;
- VKVG_IBO_INDEX_TYPE i = 0;
+ if (!(ctx->pathes[ptrPath] & PATH_IS_CONCAVE_BIT)){//} && pathPointCount > 50) {
+ _emit_draw_cmd_undrawn_vertices (ctx);
+ VKVG_IBO_INDEX_TYPE firstVertIdx = (VKVG_IBO_INDEX_TYPE)(ctx->vertCount);
+ if (ctx->sizeVertices < ctx->vertCount + pathPointCount) {
+ uint32_t newSize = (uint32_t)ceilf((float)(ctx->vertCount + pathPointCount)/VKVG_VBO_SIZE) * VKVG_VBO_SIZE;
+ _resize_vertex_cache (ctx, newSize);
+ }
+ if (ctx->sizeVertices > ctx->sizeVBO) {
+ if (ctx->cmdStarted) {
+ _flush_cmd_until_vx_base (ctx);
+ firstVertIdx = (VKVG_IBO_INDEX_TYPE)(ctx->vertCount);
+ }
+ _resize_vbo(ctx, ctx->sizeVertices);
+ }
+ firstVertIdx = (VKVG_IBO_INDEX_TYPE)(ctx->vertCount);
+ for (uint32_t i = 0; i < pathPointCount; i++) {
+ v.pos = ctx->points [i+firstPtIdx];
+ ctx->vertexCache[ctx->vertCount++] = v;
+ }
+ LOG(VKVG_LOG_DBG_ARRAYS, "\tpoint count = %d; 1st vert = %d; vert count = %d; vx tot = %d\n", pathPointCount, firstVertIdx, ctx->vertCount - firstVertIdx, ctx->vertCount);
+ _ensure_renderpass_is_started (ctx);
+ CmdDraw (ctx->cmd, pathPointCount, 1, firstVertIdx , 0);
+ ctx->curVertOffset = ctx->vertCount;
+ }else{
+ VKVG_IBO_INDEX_TYPE firstVertIdx = (VKVG_IBO_INDEX_TYPE)(ctx->vertCount - ctx->curVertOffset);
+ ear_clip_point* ecps = (ear_clip_point*)malloc(pathPointCount*sizeof(ear_clip_point));
+ uint32_t ecps_count = pathPointCount;
+ VKVG_IBO_INDEX_TYPE i = 0;
+
+ //init points link list
+ while (i < pathPointCount-1){
+ v.pos = ctx->points[i+firstPtIdx];
+ ear_clip_point ecp = {v.pos, firstVertIdx+i, &ecps[i+1]};
+ ecps[i] = ecp;
+ _add_vertex(ctx, v);
+ i++;
+ }
- //init points link list
- while (i < pathPointCount-1){
v.pos = ctx->points[i+firstPtIdx];
- ear_clip_point ecp = {v.pos, firstVertIdx+i, &ecps[i+1]};
+ ear_clip_point ecp = {v.pos, firstVertIdx+i, ecps};
ecps[i] = ecp;
_add_vertex(ctx, v);
- i++;
- }
-
- v.pos = ctx->points[i+firstPtIdx];
- ear_clip_point ecp = {v.pos, firstVertIdx+i, ecps};
- ecps[i] = ecp;
- _add_vertex(ctx, v);
- ear_clip_point* ecp_current = ecps;
- uint32_t tries = 0;
+ ear_clip_point* ecp_current = ecps;
+ uint32_t tries = 0;
- while (ecps_count > 3) {
- if (tries > ecps_count) {
- break;
- }
- ear_clip_point* v0 = ecp_current->next,
- *v1 = ecp_current, *v2 = ecp_current->next->next;
- if (ecp_zcross (v0, v2, v1)<0){
- ecp_current = ecp_current->next;
- tries++;
- continue;
- }
- ear_clip_point* vP = v2->next;
- bool isEar = true;
- while (vP!=v1){
- if (ptInTriangle (vP->pos, v0->pos, v2->pos, v1->pos)){
- isEar = false;
+ while (ecps_count > 3) {
+ if (tries > ecps_count) {
break;
}
- vP = vP->next;
- }
- if (isEar){
- _add_triangle_indices (ctx, v0->idx, v1->idx, v2->idx);
- v1->next = v2;
- ecps_count --;
- tries = 0;
- }else{
- ecp_current = ecp_current->next;
- tries++;
+ ear_clip_point* v0 = ecp_current->next,
+ *v1 = ecp_current, *v2 = ecp_current->next->next;
+ if (ecp_zcross (v0, v2, v1)<0){
+ ecp_current = ecp_current->next;
+ tries++;
+ continue;
+ }
+ ear_clip_point* vP = v2->next;
+ bool isEar = true;
+ while (vP!=v1){
+ if (ptInTriangle (vP->pos, v0->pos, v2->pos, v1->pos)){
+ isEar = false;
+ break;
+ }
+ vP = vP->next;
+ }
+ if (isEar){
+ _add_triangle_indices (ctx, v0->idx, v1->idx, v2->idx);
+ v1->next = v2;
+ ecps_count --;
+ tries = 0;
+ }else{
+ ecp_current = ecp_current->next;
+ tries++;
+ }
}
+ if (ecps_count == 3)
+ _add_triangle_indices(ctx, ecp_current->next->idx, ecp_current->idx, ecp_current->next->next->idx);
+ free (ecps);
}
- if (ecps_count == 3)
- _add_triangle_indices(ctx, ecp_current->next->idx, ecp_current->idx, ecp_current->next->next->idx);
- free (ecps);
-
firstPtIdx += pathPointCount;
if (_path_has_curves (ctx, ptrPath)) {
//skip segments lengths used in stroke
totPts += (ctx->pathes[ptrPath++] & PATH_ELT_MASK);
}else
ptrPath++;
+
}
}
uint32_t* pathes;
uint32_t sizePathes;
+
+ bool curPathIsConcave;
+ bool curPathDotSignPos;
uint32_t segmentPtr; //current segment count in current path having curves
float lineWidth;
vkDestroyPipeline (dev->vkDev, dev->pipe_SUB, NULL);
vkDestroyPipeline (dev->vkDev, dev->pipe_CLEAR, NULL);
+ vkDestroyPipeline (dev->vkDev, dev->pipe_TF_OVER, NULL);
+
#ifdef VKVG_WIRED_DEBUG
vkDestroyPipeline (dev->vkDev, dev->pipelineWired, NULL);
vkDestroyPipeline (dev->vkDev, dev->pipelineLineList, NULL);
PFN_vkCmdPushConstants CmdPushConstants;
PFN_vkCmdPushDescriptorSetKHR CmdPushDescriptorSet;
+//PFN_vkCmdSetPrimitiveTopologyEXT CmdSetPrimitiveTopology;
void _flush_all_contexes (VkvgDevice dev){
VkvgContext ctx = dev->lastCtx;
VkDynamicState dynamicStateEnables[] = {
VK_DYNAMIC_STATE_VIEWPORT,
VK_DYNAMIC_STATE_SCISSOR,
- VK_DYNAMIC_STATE_STENCIL_COMPARE_MASK,
+ VK_DYNAMIC_STATE_STENCIL_COMPARE_MASK,
VK_DYNAMIC_STATE_STENCIL_REFERENCE,
- VK_DYNAMIC_STATE_STENCIL_WRITE_MASK,
+ VK_DYNAMIC_STATE_STENCIL_WRITE_MASK
};
VkPipelineDynamicStateCreateInfo dynamicState = { .sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO,
.dynamicStateCount = 2,
pipelineCreateInfo.stageCount = 2;
VK_CHECK_RESULT(vkCreateGraphicsPipelines(dev->vkDev, dev->pipelineCache, 1, &pipelineCreateInfo, NULL, &dev->pipe_OVER));
+ inputAssemblyState.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN;
+ VK_CHECK_RESULT(vkCreateGraphicsPipelines(dev->vkDev, dev->pipelineCache, 1, &pipelineCreateInfo, NULL, &dev->pipe_TF_OVER));
+
blendAttachmentState.alphaBlendOp = blendAttachmentState.colorBlendOp = VK_BLEND_OP_SUBTRACT;
VK_CHECK_RESULT(vkCreateGraphicsPipelines(dev->vkDev, dev->pipelineCache, 1, &pipelineCreateInfo, NULL, &dev->pipe_SUB));
CmdSetScissor = GetInstProcAddress(dev->instance, vkCmdSetScissor);
CmdPushConstants = GetInstProcAddress(dev->instance, vkCmdPushConstants);
CmdPushDescriptorSet = (PFN_vkCmdPushDescriptorSetKHR)vkGetInstanceProcAddr(dev->instance, "vkCmdDescriptorSet");
+// CmdSetPrimitiveTopology = (PFN_vkCmdSetPrimitiveTopologyEXT)vkGetInstanceProcAddr(dev->instance, "vkCmdSetPrimitiveTopologyEXT");
return true;
}
extern PFN_vkCmdPushConstants CmdPushConstants;
extern PFN_vkCmdPushDescriptorSetKHR CmdPushDescriptorSet;
+//extern PFN_vkCmdSetPrimitiveTopologyEXT CmdSetPrimitiveTopology;
typedef struct _vkvg_device_t{
VkDevice vkDev; /**< Vulkan Logical Device */
VkPipeline pipe_SUB;
VkPipeline pipe_CLEAR; /**< clear operator */
+ VkPipeline pipe_TF_OVER; /**< default operator triangle fan*/
+
VkPipeline pipelinePolyFill; /**< even-odd polygon filling first step */
VkPipeline pipelineClipping; /**< draw on stencil to update clipping regions */
#define PATH_HAS_CURVES_BIT 0x40000000 /* 2rd most significant bit of path elmts is curved status
* for main path, this indicate that curve datas are present
* for segments, this indicate that the segment is curved or not */
-#define PATH_ELT_MASK 0x3FFFFFFF /* Bit mask for fetching path element value */
+#define PATH_IS_CONCAVE_BIT 0x20000000 /* 3rd most significant bit of path elmts is concave/convex bit
+ * 0=>simple concave path
+ * 1=>convex */
+#define PATH_DOT_PLUS_BIT 0x10000000 /* 4rd most significant bit of path elmts is current sign of dot product
+ * dotproduct is computed for last vector, if the sign is the same along
+ * a path, then it's a single concave path. This bit holds the current sign.
+ * If the last dot product sign is different from the one held by this bit,
+ * the 3rd bit is used to mark this path as convex.
+ * Some draw primitive have known dot product. positive arc is -, negative is +,
+ * rectangle is -.
+ * 0=>current dot product sign is negative.
+ * 1=>current dot product sign is positive.
+ *
+ *
+ * 1=>convex */
+#define PATH_ELT_MASK 0x0FFFFFFF /* Bit mask for fetching path element value */
#define ROUNDF(f, c) (((float)((int)((f) * (c))) / (c)))
#define ROUND_DOWN(v,p) (floorf(v * p) / p)
//vkvg_log_level = VKVG_LOG_ERR|VKVG_LOG_DEBUG|VKVG_LOG_INFO|VKVG_LOG_INFO_PATH|VKVG_LOG_DBG_ARRAYS|VKVG_LOG_FULL;
PERFORM_TEST (rectangles_fill, argc, argv);
- PERFORM_TEST (rectangles_stroke, argc, argv);
- PERFORM_TEST (rectangles_fill_stroke, argc, argv);
+ //PERFORM_TEST (rectangles_stroke, argc, argv);
+ //PERFORM_TEST (rectangles_fill_stroke, argc, argv);
PERFORM_TEST (rounded_rects_fill, argc, argv);
- PERFORM_TEST (rounded_rects_stroke, argc, argv);
- PERFORM_TEST (rounded_rects_fill_stroke, argc, argv);
+ //PERFORM_TEST (rounded_rects_stroke, argc, argv);
+ //PERFORM_TEST (rounded_rects_fill_stroke, argc, argv);
PERFORM_TEST (circles_fill, argc, argv);
- PERFORM_TEST (circles_stroke, argc, argv);
- PERFORM_TEST (circles_fill_stroke, argc, argv);
+ //PERFORM_TEST (circles_stroke, argc, argv);
+ //PERFORM_TEST (circles_fill_stroke, argc, argv);
PERFORM_TEST (stars_fill, argc, argv);
- PERFORM_TEST (stars_stroke, argc, argv);
- PERFORM_TEST (stars_fill_stroke, argc, argv);
+ //PERFORM_TEST (stars_stroke, argc, argv);
+ //PERFORM_TEST (stars_fill_stroke, argc, argv);
PERFORM_TEST (random_fill, argc, argv);
- PERFORM_TEST (random_stroke, argc, argv);
- PERFORM_TEST (random_fill_stroke, argc, argv);
+ //PERFORM_TEST (random_stroke, argc, argv);
+ //PERFORM_TEST (random_fill_stroke, argc, argv);
return 0;
}