[Bf-blender-cvs] [9ef18d8b36a] greasepencil-refactor: GPencil: Refactor: Add implementation of new mask list system

Clément Foucault noreply at git.blender.org
Tue Feb 11 00:15:56 CET 2020


Commit: 9ef18d8b36a6b6f834be56f181af5fca9685b376
Author: Clément Foucault
Date:   Tue Feb 11 00:05:39 2020 +0100
Branches: greasepencil-refactor
https://developer.blender.org/rB9ef18d8b36a6b6f834be56f181af5fca9685b376

GPencil: Refactor: Add implementation of new mask list system

This system makes it possible to have up to 256 layers in a GPencil Object
that can be used as masks. User can use more than 256 layers and use mask
on them but the masking one must be from one of the first 256.

This commit does not include optimizations.

===================================================================

M	source/blender/draw/engines/gpencil/gpencil_cache_utils.c
M	source/blender/draw/engines/gpencil/gpencil_draw_data.c
M	source/blender/draw/engines/gpencil/gpencil_engine.c
M	source/blender/draw/engines/gpencil/gpencil_engine.h

===================================================================

diff --git a/source/blender/draw/engines/gpencil/gpencil_cache_utils.c b/source/blender/draw/engines/gpencil/gpencil_cache_utils.c
index b05e3fe4ebd..3caaea0516b 100644
--- a/source/blender/draw/engines/gpencil/gpencil_cache_utils.c
+++ b/source/blender/draw/engines/gpencil/gpencil_cache_utils.c
@@ -115,6 +115,7 @@ GPENCIL_tLayer *gpencil_layer_cache_add(GPENCIL_PrivateData *pd, Object *ob, bGP
   const bool is_obact = ((pd->obact) && (pd->obact == ob));
   const bool is_fade = ((pd->fade_layer_opacity > -1.0f) && (is_obact) &&
                         ((gpl->flag & GP_LAYER_ACTIVE) == 0));
+  const bool use_mask = (gpl->flag & GP_LAYER_USE_MASK) != 0;
   bool mask_invert = true; /* True because we invert the dummy texture red channel. */
 
   /* Defines layer opacity. For active object depends of layer opacity factor, and
@@ -132,17 +133,36 @@ GPENCIL_tLayer *gpencil_layer_cache_add(GPENCIL_PrivateData *pd, Object *ob, bGP
   bGPdata *gpd = (bGPdata *)ob->data;
   GPENCIL_tLayer *tgp_layer = BLI_memblock_alloc(pd->gp_layer_pool);
   tgp_layer->layer_id = BLI_findindex(&gpd->layers, gpl);
-  tgp_layer->mask_id = -1;
+  tgp_layer->mask_bits = NULL;
+
+  if (use_mask && !BLI_listbase_is_empty(&gpl->mask_layers)) {
+    bool valid_mask = false;
+    /* Warning: only GP_MAX_MASKBITS amount of bits.
+     * TODO(fclem) Find a better system without any limitation. */
+    tgp_layer->mask_bits = BLI_memblock_alloc(pd->gp_maskbit_pool);
+    BLI_bitmap_set_all(tgp_layer->mask_bits, false, GP_MAX_MASKBITS);
+
+    LISTBASE_FOREACH (bGPDlayer_Mask *, mask, &gpl->mask_layers) {
+      bGPDlayer *gpl_mask = BKE_gpencil_layer_named_get(gpd, mask->name);
+      if (gpl_mask && (gpl_mask != gpl) && ((gpl_mask->flag & GP_LAYER_HIDE) == 0)) {
+        int index = BLI_findindex(&gpd->layers, gpl_mask);
+        if (index < GP_MAX_MASKBITS) {
+          BLI_BITMAP_SET(tgp_layer->mask_bits, index, true);
+          valid_mask = true;
+        }
+      }
+    }
 
-  // TODO GPXX (New masking)
-  // bGPDlayer *gpl_mask = BKE_gpencil_layer_named_get(gpd, gpl->mask_layer);
-  // if (gpl_mask && (gpl_mask != gpl) && ((gpl_mask->flag & GP_LAYER_HIDE) == 0)) {
-  //  mask_invert = (gpl->flag & GP_LAYER_MASK_INVERT) != 0;
-  //  tgp_layer->mask_id = BLI_findindex(&gpd->layers, gpl_mask);
-  //  pd->use_mask_fb = true;
-  //}
+    if (valid_mask) {
+      mask_invert = (gpl->flag & GP_LAYER_MASK_INVERT) != 0;
+      pd->use_mask_fb = true;
+    }
+    else {
+      tgp_layer->mask_bits = NULL;
+    }
+  }
 
-  const bool is_masked = tgp_layer->mask_id != -1;
+  const bool is_masked = tgp_layer->mask_bits != NULL;
 
   {
     DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_BLEND_ALPHA_PREMUL;
diff --git a/source/blender/draw/engines/gpencil/gpencil_draw_data.c b/source/blender/draw/engines/gpencil/gpencil_draw_data.c
index 97e5a44f0ab..58b1b72dd66 100644
--- a/source/blender/draw/engines/gpencil/gpencil_draw_data.c
+++ b/source/blender/draw/engines/gpencil/gpencil_draw_data.c
@@ -479,6 +479,7 @@ static void gpencil_view_layer_data_free(void *storage)
 
   BLI_memblock_destroy(vldata->gp_light_pool, gpencil_light_pool_free);
   BLI_memblock_destroy(vldata->gp_material_pool, gpencil_material_pool_free);
+  BLI_memblock_destroy(vldata->gp_maskbit_pool, NULL);
   BLI_memblock_destroy(vldata->gp_object_pool, NULL);
   BLI_memblock_destroy(vldata->gp_layer_pool, NULL);
   BLI_memblock_destroy(vldata->gp_vfx_pool, NULL);
@@ -497,6 +498,7 @@ GPENCIL_ViewLayerData *GPENCIL_view_layer_data_ensure(void)
 
     (*vldata)->gp_light_pool = BLI_memblock_create(sizeof(GPENCIL_LightPool));
     (*vldata)->gp_material_pool = BLI_memblock_create(sizeof(GPENCIL_MaterialPool));
+    (*vldata)->gp_maskbit_pool = BLI_memblock_create(BLI_BITMAP_SIZE(GP_MAX_MASKBITS));
     (*vldata)->gp_object_pool = BLI_memblock_create(sizeof(GPENCIL_tObject));
     (*vldata)->gp_layer_pool = BLI_memblock_create(sizeof(GPENCIL_tLayer));
     (*vldata)->gp_vfx_pool = BLI_memblock_create(sizeof(GPENCIL_tVfx));
diff --git a/source/blender/draw/engines/gpencil/gpencil_engine.c b/source/blender/draw/engines/gpencil/gpencil_engine.c
index fb67db00b09..5c760023a05 100644
--- a/source/blender/draw/engines/gpencil/gpencil_engine.c
+++ b/source/blender/draw/engines/gpencil/gpencil_engine.c
@@ -82,9 +82,11 @@ void GPENCIL_engine_init(void *ved)
   BLI_memblock_clear(vldata->gp_object_pool, NULL);
   BLI_memblock_clear(vldata->gp_layer_pool, NULL);
   BLI_memblock_clear(vldata->gp_vfx_pool, NULL);
+  BLI_memblock_clear(vldata->gp_maskbit_pool, NULL);
 
   stl->pd->gp_light_pool = vldata->gp_light_pool;
   stl->pd->gp_material_pool = vldata->gp_material_pool;
+  stl->pd->gp_maskbit_pool = vldata->gp_maskbit_pool;
   stl->pd->gp_object_pool = vldata->gp_object_pool;
   stl->pd->gp_layer_pool = vldata->gp_layer_pool;
   stl->pd->gp_vfx_pool = vldata->gp_vfx_pool;
@@ -824,7 +826,7 @@ static void GPENCIL_draw_scene_depth_only(void *ved)
     GPU_framebuffer_bind(dfbl->default_fb);
   }
 
-  pd->gp_object_pool = pd->gp_layer_pool = pd->gp_vfx_pool = NULL;
+  pd->gp_object_pool = pd->gp_layer_pool = pd->gp_vfx_pool = pd->gp_maskbit_pool = NULL;
 
   /* Free temp stroke buffers. */
   if (pd->sbuffer_gpd) {
@@ -832,13 +834,40 @@ static void GPENCIL_draw_scene_depth_only(void *ved)
   }
 }
 
+static void gpencil_draw_mask(GPENCIL_Data *vedata, GPENCIL_tObject *ob, GPENCIL_tLayer *layer)
+{
+  GPENCIL_FramebufferList *fbl = vedata->fbl;
+  float clear_col[4] = {1.0f, 1.0f, 1.0f, 1.0f};
+
+  DRW_stats_group_start("GPencil Mask");
+
+  /* OPTI(fclem) we could optimize by only clearing if the new mask_bits contains all
+   * the masks already rendered in the buffer, and drawing only the layers not already drawn. */
+  if (true) {
+    GPU_framebuffer_bind(fbl->mask_fb);
+    GPU_framebuffer_clear_color_depth(fbl->mask_fb, clear_col, ob->is_drawmode3d ? 1.0f : 0.0f);
+  }
+
+  for (int i = 0; i < GP_MAX_MASKBITS; i++) {
+    if (!BLI_BITMAP_TEST(layer->mask_bits, i)) {
+      continue;
+    }
+
+    GPENCIL_tLayer *mask_layer = gpencil_layer_cache_get(ob, i);
+    BLI_assert(mask_layer);
+
+    DRW_draw_pass(mask_layer->geom_ps);
+  }
+
+  DRW_stats_group_end();
+}
+
 static void GPENCIL_draw_object(GPENCIL_Data *vedata, GPENCIL_tObject *ob)
 {
   GPENCIL_PassList *psl = vedata->psl;
   GPENCIL_PrivateData *pd = vedata->stl->pd;
   GPENCIL_FramebufferList *fbl = vedata->fbl;
   float clear_cols[2][4] = {{0.0f, 0.0f, 0.0f, 0.0f}, {1.0f, 1.0f, 1.0f, 1.0f}};
-  GPENCIL_tLayer *cached_mask = NULL;
 
   DRW_stats_group_start("GPencil Object");
 
@@ -852,15 +881,8 @@ static void GPENCIL_draw_object(GPENCIL_Data *vedata, GPENCIL_tObject *ob)
   }
 
   for (GPENCIL_tLayer *layer = ob->layers.first; layer; layer = layer->next) {
-    GPENCIL_tLayer *mask_layer = gpencil_layer_cache_get(ob, layer->mask_id);
-    if ((mask_layer != NULL) && (mask_layer != cached_mask)) {
-      cached_mask = mask_layer;
-
-      GPU_framebuffer_bind(fbl->mask_fb);
-      GPU_framebuffer_clear_color_depth(
-          fbl->mask_fb, clear_cols[1], ob->is_drawmode3d ? 1.0f : 0.0f);
-
-      DRW_draw_pass(mask_layer->geom_ps);
+    if (layer->mask_bits) {
+      gpencil_draw_mask(vedata, ob, layer);
     }
 
     if (layer->blend_ps) {
@@ -978,7 +1000,7 @@ void GPENCIL_draw_scene(void *ved)
     DRW_draw_pass(psl->composite_ps);
   }
 
-  pd->gp_object_pool = pd->gp_layer_pool = pd->gp_vfx_pool = NULL;
+  pd->gp_object_pool = pd->gp_layer_pool = pd->gp_vfx_pool = pd->gp_maskbit_pool = NULL;
 
   /* Free temp stroke buffers. */
   if (pd->sbuffer_gpd) {
diff --git a/source/blender/draw/engines/gpencil/gpencil_engine.h b/source/blender/draw/engines/gpencil/gpencil_engine.h
index 620cceef12d..1dec9feb61b 100644
--- a/source/blender/draw/engines/gpencil/gpencil_engine.h
+++ b/source/blender/draw/engines/gpencil/gpencil_engine.h
@@ -25,6 +25,8 @@
 
 #include "DNA_gpencil_types.h"
 
+#include "BLI_bitmap.h"
+
 #include "GPU_batch.h"
 
 extern DrawEngineType draw_engine_gpencil_type;
@@ -50,6 +52,8 @@ struct GPUVertFormat;
 
 #define GP_IS_CAMERAVIEW ((rv3d != NULL) && (rv3d->persp == RV3D_CAMOB && v3d->camera))
 
+#define GP_MAX_MASKBITS 256
+
 /* UBO structure. Watch out for padding. Must match GLSL declaration. */
 typedef struct gpMaterial {
   float stroke_color[4];
@@ -135,6 +139,8 @@ typedef struct GPENCIL_ViewLayerData {
   struct BLI_memblock *gp_material_pool;
   /* GPENCIL_LightPool */
   struct BLI_memblock *gp_light_pool;
+  /* BLI_bitmap */
+  struct BLI_memblock *gp_maskbit_pool;
 } GPENCIL_ViewLayerData;
 
 /* *********** GPencil  *********** */
@@ -154,10 +160,10 @@ typedef struct GPENCIL_tLayer {
   DRWPass *geom_ps;
   /** Blend pass to composite onto the target buffer (blends modes). NULL if not needed. */
   DRWPass *blend_ps;
+  /** Layer id of the mask. */
+  BLI_bitmap *mask_bits;
   /** Index in the layer list. Used as id for masking. */
   int layer_id;
-  /** Layer id of the mask. */
-  int mask_id;
 } GPENCIL_tLayer;
 
 typedef struct GPENCIL_tObject {
@@ -240,6 +246,7 @@ typedef struct GPENCIL_PrivateData {
   struct BLI_memblock *gp_vfx_pool;
   struct BLI_memblock *gp_material_pool;
   struct BLI_memblock *gp_light_pool;
+  struct BLI_memblock *gp_maskbit_pool;
   /* Last used material pool. */
   GPENCIL_MaterialPool *last_material_pool;
   /* Last used light pool. */



More information about the Bf-blender-cvs mailing list