diff --git a/source/Lib/CommonLib/CommonDef.h b/source/Lib/CommonLib/CommonDef.h
index 59ade8e0b6c87c087a4458a9ff4d4e1eee36e577..2041fcf01365cd3dda1cad752aef45a89e6b96e5 100644
--- a/source/Lib/CommonLib/CommonDef.h
+++ b/source/Lib/CommonLib/CommonDef.h
@@ -1001,15 +1001,27 @@ static const int CCCM_DECIM_BITS          = 22;
 static const int CCCM_DECIM_ROUND         = ( 1 << (CCCM_DECIM_BITS - 1 ) );
 #if JVET_AB0143_CCCM_TS
 #if MMLM
+#if JVET_AC0054_GLCCCM
+static const int CCCM_NUM_MODES           = 12;
+#else
+static const int CCCM_NUM_MODES           = 6;
+#endif
+#else
+#if JVET_AC0054_GLCCCM
 static const int CCCM_NUM_MODES           = 6;
 #else
 static const int CCCM_NUM_MODES           = 3;
 #endif
 #endif
+#endif
 #if JVET_AC0147_CCCM_NO_SUBSAMPLING
 static const int CCCM_NO_SUB_NUM_PARAMS   = 11;
 static const double CCCM_NO_SUB_WEIGHT    = 1.1; 
 #endif
+#if JVET_AC0054_GLCCCM
+static const int CCCM_LOC_SHIFT           = 3;
+static const int CCCM_LOC_OFFSET          = (1 << CCCM_LOC_SHIFT);
+#endif
 #endif
 
 #if JVET_AA0126_GLM
diff --git a/source/Lib/CommonLib/Contexts.cpp b/source/Lib/CommonLib/Contexts.cpp
index 25ed082fe83f3269f02fd86a7c65768abc024ff0..b7c83642d15442f387151e22ccb478c8b9304fe8 100644
--- a/source/Lib/CommonLib/Contexts.cpp
+++ b/source/Lib/CommonLib/Contexts.cpp
@@ -3181,7 +3181,19 @@ const CtxSet ContextSetCfg::GlmFlags = ContextSetCfg::addCtxSet
 #if JVET_AA0057_CCCM
 const CtxSet ContextSetCfg::CccmFlag = ContextSetCfg::addCtxSet
 ({
-#if JVET_AC0147_CCCM_NO_SUBSAMPLING  
+#if JVET_AC0147_CCCM_NO_SUBSAMPLING && JVET_AC0054_GLCCCM
+  { CNU, CNU, CNU, },
+  { CNU, CNU, CNU, },
+  { CNU, CNU, CNU, },
+  { DWS, DWS, DWS, },
+  { DWS, DWS, DWS, },
+  { DWS, DWS, DWS, },
+  { DWE, DWE, DWE, },
+  { DWE, DWE, DWE, },
+  { DWE, DWE, DWE, },
+  { DWO, DWO, DWO, },
+  { DWO, DWO, DWO, },
+#elif JVET_AC0147_CCCM_NO_SUBSAMPLING || JVET_AC0054_GLCCCM
   { CNU, CNU, },
   { CNU, CNU, },
   { CNU, CNU, },
@@ -4867,7 +4879,14 @@ const CtxSet ContextSetCfg::GlmFlags = ContextSetCfg::addCtxSet
 #if JVET_AA0057_CCCM
 const CtxSet ContextSetCfg::CccmFlag = ContextSetCfg::addCtxSet
 ({
-#if JVET_AC0147_CCCM_NO_SUBSAMPLING
+#if JVET_AC0147_CCCM_NO_SUBSAMPLING && JVET_AC0054_GLCCCM
+  { CNU, CNU, CNU, },
+  { CNU, CNU, CNU, },
+  { CNU, CNU, CNU, },
+  { DWS, DWS, DWS, },
+  { DWS, DWS, DWS, },
+  { DWS, DWS, DWS, },
+#elif JVET_AC0147_CCCM_NO_SUBSAMPLING || JVET_AC0054_GLCCCM
   { CNU, CNU, },
   { CNU, CNU, },
   { CNU, CNU, },
@@ -6056,7 +6075,12 @@ const CtxSet ContextSetCfg::GlmFlags = ContextSetCfg::addCtxSet
 #if JVET_AA0057_CCCM
 const CtxSet ContextSetCfg::CccmFlag = ContextSetCfg::addCtxSet
 ({
-#if JVET_AC0147_CCCM_NO_SUBSAMPLING
+#if JVET_AC0147_CCCM_NO_SUBSAMPLING && JVET_AC0054_GLCCCM
+  { CNU, CNU, CNU, },
+  { CNU, CNU, CNU, },
+  { CNU, CNU, CNU, },
+  { DWS, DWS, DWS, },
+#elif JVET_AC0147_CCCM_NO_SUBSAMPLING || JVET_AC0054_GLCCCM
   { CNU, CNU, },
   { CNU, CNU, },
   { CNU, CNU, },
diff --git a/source/Lib/CommonLib/IntraPrediction.cpp b/source/Lib/CommonLib/IntraPrediction.cpp
index 382181d2df2b11f07a71536b8d8c7dd478b19f76..e454a0c3360d91afcbdc304143925d2f2b2ab555 100644
--- a/source/Lib/CommonLib/IntraPrediction.cpp
+++ b/source/Lib/CommonLib/IntraPrediction.cpp
@@ -10830,7 +10830,10 @@ void IntraPrediction::xCccmApplyModel(const PredictionUnit& pu, const ComponentI
 #if JVET_AC0147_CCCM_NO_SUBSAMPLING
   CHECK( pu.cccmNoSubFlag, "cccmNoSubFlag shall be disabled" );
 #endif
-
+#if JVET_AC0054_GLCCCM
+  int refSizeX   = m_cccmBlkArea.x - m_cccmRefArea.x; // Reference lines available left and above
+  int refSizeY   = m_cccmBlkArea.y - m_cccmRefArea.y;
+#endif
   CPelBuf refLumaBlk = xCccmGetLumaPuBuf(pu);
 
   for (int y = 0; y < refLumaBlk.height; y++)
@@ -10847,6 +10850,30 @@ void IntraPrediction::xCccmApplyModel(const PredictionUnit& pu, const ComponentI
       }
       
       // 7-tap cross
+#if JVET_AC0054_GLCCCM
+      if (!pu.glCccmFlag)
+      {
+        samples[0] = refLumaBlk.at( x  , y   ); // C
+        samples[1] = refLumaBlk.at( x  , y-1 ); // N
+        samples[2] = refLumaBlk.at( x  , y+1 ); // S
+        samples[3] = refLumaBlk.at( x-1, y   ); // W
+        samples[4] = refLumaBlk.at( x+1, y   ); // E
+        samples[5] = cccmModel.nonlinear( refLumaBlk.at( x, y) );
+        samples[6] = cccmModel.bias();
+      }
+      else
+      {
+        samples[0] = refLumaBlk.at( x  , y   ); // C
+        samples[1] = (2 * refLumaBlk.at( x  , y-1 ) + refLumaBlk.at( x-1  , y-1 ) + refLumaBlk.at( x+1  , y-1 ))
+          -(2 * refLumaBlk.at( x  , y+1 ) + refLumaBlk.at( x-1  , y+1 ) + refLumaBlk.at( x+1  , y+1 )); // Vertical gradient
+        samples[2] = (2 * refLumaBlk.at( x-1, y   ) + refLumaBlk.at( x-1  , y-1 ) + refLumaBlk.at( x-1  , y+1 ))
+          -(2 * refLumaBlk.at( x+1, y   ) + refLumaBlk.at( x+1  , y-1 ) + refLumaBlk.at( x+1  , y+1 )); // Horizontal gradient
+        samples[3] = ((y + refSizeY + CCCM_LOC_OFFSET) << CCCM_LOC_SHIFT); // Y coordinate
+        samples[4] = ((x + refSizeX + CCCM_LOC_OFFSET) << CCCM_LOC_SHIFT); // X coordinate
+        samples[5] = cccmModel.nonlinear( refLumaBlk.at( x, y) );
+        samples[6] = cccmModel.bias();
+      }
+#else
       samples[0] = refLumaBlk.at( x  , y   ); // C
       samples[1] = refLumaBlk.at( x  , y-1 ); // N
       samples[2] = refLumaBlk.at( x  , y+1 ); // S
@@ -10854,7 +10881,8 @@ void IntraPrediction::xCccmApplyModel(const PredictionUnit& pu, const ComponentI
       samples[4] = refLumaBlk.at( x+1, y   ); // E
       samples[5] = cccmModel.nonlinear( refLumaBlk.at( x, y) );
       samples[6] = cccmModel.bias();
-
+#endif
+        
       piPred.at(x, y) = ClipPel<Pel>( cccmModel.convolve(samples), clpRng );
     }
   }
@@ -10924,6 +10952,30 @@ void IntraPrediction::xCccmCalcModels(const PredictionUnit& pu, CccmModel<CCCM_N
       }
 
       // 7-tap cross
+#if JVET_AC0054_GLCCCM
+      if (!pu.glCccmFlag)
+      {
+        A[0][sampleNum] = refLuma.at( x  , y   ); // C
+        A[1][sampleNum] = refLuma.at( x  , y-1 ); // N
+        A[2][sampleNum] = refLuma.at( x  , y+1 ); // S
+        A[3][sampleNum] = refLuma.at( x-1, y   ); // W
+        A[4][sampleNum] = refLuma.at( x+1, y   ); // E
+        A[5][sampleNum] = cccmModelCb.nonlinear( refLuma.at( x, y) );
+        A[6][sampleNum] = cccmModelCb.bias();
+      }
+      else
+      {
+        A[0][sampleNum] = refLuma.at( x  , y   ); // C
+        A[1][sampleNum] = (2 * refLuma.at( x  , y-1 ) + refLuma.at( x-1  , y-1 ) + refLuma.at( x+1  , y-1 ))
+                           -(2 * refLuma.at( x  , y+1 ) + refLuma.at( x-1  , y+1 ) + refLuma.at( x+1  , y+1 )); // Vertical gradient
+        A[2][sampleNum] = (2 * refLuma.at( x-1, y   ) + refLuma.at( x-1  , y-1 ) + refLuma.at( x-1  , y+1 ))
+                           -(2 * refLuma.at( x+1, y   ) + refLuma.at( x+1  , y-1 ) + refLuma.at( x+1  , y+1 )); // Horizontal gradient
+        A[3][sampleNum] = ((y + CCCM_LOC_OFFSET) << CCCM_LOC_SHIFT); // Y coordinate
+        A[4][sampleNum] = ((x + CCCM_LOC_OFFSET) << CCCM_LOC_SHIFT); // X coordinate
+        A[5][sampleNum] = cccmModelCb.nonlinear( refLuma.at( x, y) );
+        A[6][sampleNum] = cccmModelCb.bias();
+      }
+#else
       A[0][sampleNum] = refLuma.at( x  , y   ); // C
       A[1][sampleNum] = refLuma.at( x  , y-1 ); // N
       A[2][sampleNum] = refLuma.at( x  , y+1 ); // S
@@ -10931,7 +10983,8 @@ void IntraPrediction::xCccmCalcModels(const PredictionUnit& pu, CccmModel<CCCM_N
       A[4][sampleNum] = refLuma.at( x+1, y   ); // E
       A[5][sampleNum] = cccmModelCb.nonlinear( refLuma.at( x, y) );
       A[6][sampleNum] = cccmModelCb.bias();
-
+#endif
+        
       YCb[sampleNum]   = recoCb.at(refPosPicX + x, refPosPicY + y);
       YCr[sampleNum++] = recoCr.at(refPosPicX + x, refPosPicY + y);
     }
diff --git a/source/Lib/CommonLib/TypeDef.h b/source/Lib/CommonLib/TypeDef.h
index 6c0b9a3af5922fb0bb4e23068c83126e2d5ebc7c..9579e589afb1574c233fe0571d2ea4540d6aaa8d 100644
--- a/source/Lib/CommonLib/TypeDef.h
+++ b/source/Lib/CommonLib/TypeDef.h
@@ -157,6 +157,7 @@
 #if JVET_AA0057_CCCM
 #define JVET_AB0143_CCCM_TS                               1 // JVET-AB0143: CCCM template selection
 #define JVET_AC0147_CCCM_NO_SUBSAMPLING                   1 // JVET-AC0147: Subsampling is not applied to CCCM
+#define JVET_AC0054_GLCCCM                                1 // JVET_AC0054: Gradient and location based CCCM
 #endif
 #define JVET_AA0126_GLM                                   1 // JVET-AA0126: Gradient linear model
 #if JVET_AA0126_GLM
diff --git a/source/Lib/CommonLib/Unit.cpp b/source/Lib/CommonLib/Unit.cpp
index 0063dfab62529765392859bc5010d12b9fa1925f..55fdbe0ec8bea66b3429ecbe1d006ea4eac4feff 100644
--- a/source/Lib/CommonLib/Unit.cpp
+++ b/source/Lib/CommonLib/Unit.cpp
@@ -799,6 +799,9 @@ void PredictionUnit::initData()
 #if JVET_AC0147_CCCM_NO_SUBSAMPLING
   cccmNoSubFlag = 0;
 #endif
+#if JVET_AC0054_GLCCCM
+  glCccmFlag = 0;
+#endif
 #endif
   // inter data
 #if ENABLE_INTER_TEMPLATE_MATCHING && JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION
@@ -950,6 +953,9 @@ PredictionUnit& PredictionUnit::operator=(const IntraPredictionData& predData)
 #if JVET_AC0147_CCCM_NO_SUBSAMPLING
   cccmNoSubFlag = predData.cccmNoSubFlag;
 #endif
+#if JVET_AC0054_GLCCCM
+  glCccmFlag = predData.glCccmFlag;
+#endif
 #endif
   return *this;
 }
@@ -1098,6 +1104,9 @@ PredictionUnit& PredictionUnit::operator=( const PredictionUnit& other )
 #if JVET_AC0147_CCCM_NO_SUBSAMPLING
   cccmNoSubFlag = other.cccmNoSubFlag;
 #endif
+#if JVET_AC0054_GLCCCM
+  glCccmFlag = other.glCccmFlag;
+#endif
 #endif
 
   mergeFlag   = other.mergeFlag;
diff --git a/source/Lib/CommonLib/Unit.h b/source/Lib/CommonLib/Unit.h
index 271adcf25e5591770d73dd05cbe3321cea1e9f0e..7f813e65215a0be295460a689d8e5335fe0b543c 100644
--- a/source/Lib/CommonLib/Unit.h
+++ b/source/Lib/CommonLib/Unit.h
@@ -509,6 +509,9 @@ struct IntraPredictionData
 #if JVET_AC0147_CCCM_NO_SUBSAMPLING
   int       cccmNoSubFlag;
 #endif
+#if JVET_AC0054_GLCCCM
+  int       glCccmFlag;
+#endif
 #endif
 };
 
diff --git a/source/Lib/DecoderLib/CABACReader.cpp b/source/Lib/DecoderLib/CABACReader.cpp
index 9ddfc8dcf4f42acfeca1702adca032c2fec0ccf7..ffa57642590c4bafbb5aff55b2c4067f0127f937 100644
--- a/source/Lib/DecoderLib/CABACReader.cpp
+++ b/source/Lib/DecoderLib/CABACReader.cpp
@@ -2528,12 +2528,25 @@ void CABACReader::cccmFlag(PredictionUnit& pu)
 #else
       pu.cccmFlag = (intraDir == MDLM_T_IDX) ? 3 : (intraDir == MDLM_L_IDX) ? 2 : 1;
 #endif
+        
 #if JVET_AC0147_CCCM_NO_SUBSAMPLING
       pu.cccmNoSubFlag = 0;
       if ( pu.cs->sps->getUseCccm() == 2 )
       {    
         pu.cccmNoSubFlag += m_BinDecoder.decodeBin( Ctx::CccmFlag( 1 ) );
-      }         
+      }
+#endif
+#if JVET_AC0054_GLCCCM
+      pu.glCccmFlag = 0;
+#if !JVET_AC0147_CCCM_NO_SUBSAMPLING
+      unsigned ctxId = 1;
+#else
+      unsigned ctxId = 2;
+      if (!pu.cccmNoSubFlag)
+#endif
+      {
+        pu.glCccmFlag = m_BinDecoder.decodeBin( Ctx::CccmFlag( ctxId ) );
+      }
 #endif
     }
 #endif
diff --git a/source/Lib/EncoderLib/CABACWriter.cpp b/source/Lib/EncoderLib/CABACWriter.cpp
index 0ab51eebddc0dc09b7569d91d7c4f803fe350f2b..417998113cdcfc67e67364cca2c3418c59168e84 100644
--- a/source/Lib/EncoderLib/CABACWriter.cpp
+++ b/source/Lib/EncoderLib/CABACWriter.cpp
@@ -2258,10 +2258,22 @@ void CABACWriter::cccmFlag(const PredictionUnit& pu)
   {
     m_BinEncoder.encodeBin( pu.cccmFlag ? 1 : 0, Ctx::CccmFlag( 0 ) );
 #if JVET_AC0147_CCCM_NO_SUBSAMPLING
-    if ( pu.cccmFlag && ( pu.cs->sps->getUseCccm() == 2 ) ) 
+    if ( pu.cccmFlag && ( pu.cs->sps->getUseCccm() == 2 ) )
     {
       m_BinEncoder.encodeBin( pu.cccmNoSubFlag ? 1 : 0, Ctx::CccmFlag( 1 ) );
     }
+#endif
+#if JVET_AC0054_GLCCCM
+#if !JVET_AC0147_CCCM_NO_SUBSAMPLING
+    unsigned ctxId = 1;
+    if (pu.cccmFlag)
+#else
+    unsigned ctxId = 2;
+    if (pu.cccmFlag && !pu.cccmNoSubFlag)
+#endif
+    {
+      m_BinEncoder.encodeBin( pu.glCccmFlag ? 1 : 0, Ctx::CccmFlag( ctxId ) );
+    }
 #endif
   }
 }
diff --git a/source/Lib/EncoderLib/IntraSearch.cpp b/source/Lib/EncoderLib/IntraSearch.cpp
index feedffd6e1f78f7ab04314f78c478dd1b5d0f54d..6ad13a4ef028e23b70349364e401726042b0b7cc 100644
--- a/source/Lib/EncoderLib/IntraSearch.cpp
+++ b/source/Lib/EncoderLib/IntraSearch.cpp
@@ -2575,6 +2575,9 @@ void IntraSearch::estIntraPredChromaQT( CodingUnit &cu, Partitioner &partitioner
 #if JVET_AC0147_CCCM_NO_SUBSAMPLING
     int      cccmNoSubBest = 0;
 #endif
+#if JVET_AC0054_GLCCCM
+    int      glCccmBest = 0;
+#endif
 #endif
 #if JVET_Z0050_CCLM_SLOPE
     CclmOffsets bestCclmOffsets = {};
@@ -2933,11 +2936,25 @@ void IntraSearch::estIntraPredChromaQT( CodingUnit &cu, Partitioner &partitioner
 
 #if JVET_AB0143_CCCM_TS
 #if MMLM
+#if JVET_AC0054_GLCCCM
+      uint32_t chromaCandCccmModes[CCCM_NUM_MODES] = { LM_CHROMA_IDX, MDLM_L_IDX, MDLM_T_IDX, MMLM_CHROMA_IDX, MMLM_L_IDX, MMLM_T_IDX
+                                                     , LM_CHROMA_IDX, MDLM_L_IDX, MDLM_T_IDX, MMLM_CHROMA_IDX, MMLM_L_IDX, MMLM_T_IDX };
+#else
       uint32_t chromaCandCccmModes[CCCM_NUM_MODES] = { LM_CHROMA_IDX, MDLM_L_IDX, MDLM_T_IDX, MMLM_CHROMA_IDX, MMLM_L_IDX, MMLM_T_IDX };
+#endif
+#else
+#if JVET_AC0054_GLCCCM
+      uint32_t chromaCandCccmModes[CCCM_NUM_MODES] = { LM_CHROMA_IDX, MDLM_L_IDX, MDLM_T_IDX
+                                                     , LM_CHROMA_IDX, MDLM_L_IDX, MDLM_T_IDX };
 #else
       uint32_t chromaCandCccmModes[CCCM_NUM_MODES] = { LM_CHROMA_IDX, MDLM_L_IDX, MDLM_T_IDX };
 #endif
+#endif
 
+#if JVET_AC0054_GLCCCM
+      int satdCccmFlagList[CCCM_NUM_MODES];
+#endif
+        
 #if JVET_AC0147_CCCM_NO_SUBSAMPLING
       int64_t satdCccmSortedCost[2][CCCM_NUM_MODES];
       int satdCccmModeList[2][CCCM_NUM_MODES];
@@ -2948,6 +2965,9 @@ void IntraSearch::estIntraPredChromaQT( CodingUnit &cu, Partitioner &partitioner
         satdCccmSortedCost[1][i] = LLONG_MAX; // for the mode not pre-select by SATD, do RDO by default, so set the initial value 0.
         satdCccmModeList[0][i] = chromaCandCccmModes[i];
         satdCccmModeList[1][i] = chromaCandCccmModes[i];
+#if JVET_AC0054_GLCCCM
+        satdCccmFlagList[i] = i < (CCCM_NUM_MODES / 2) ? 1 : 2; // 1: cccm, 2: glCccm
+#endif
       }
       int64_t bestCccmCost[2] = { LLONG_MAX, LLONG_MAX};
 
@@ -2975,6 +2995,12 @@ void IntraSearch::estIntraPredChromaQT( CodingUnit &cu, Partitioner &partitioner
 
         for (int idx = 0; idx < CCCM_NUM_MODES; idx++)
         {
+#if JVET_AC0054_GLCCCM
+          if (sub && idx >= CCCM_NUM_MODES / 2)
+          {
+            continue;
+          }
+#endif
           int mode = chromaCandCccmModes[idx];
           if (idx == 0)
           {
@@ -3008,6 +3034,34 @@ void IntraSearch::estIntraPredChromaQT( CodingUnit &cu, Partitioner &partitioner
             pu.cccmFlag = 3;
           }
 #endif
+            
+#if JVET_AC0054_GLCCCM
+          if (idx < CCCM_NUM_MODES / 2)
+          {
+            pu.glCccmFlag = 0;
+          }
+          else
+          {
+            pu.glCccmFlag = 1;
+#if MMLM
+            isCCCMEnabled = idx == 6 ? isCccmFullEnabled
+            : idx == 7 ? isCccmLeftEnabled
+            : idx == 8 ? isCccmTopEnabled
+            : idx == 9 ? isMultiCccmFullEnabled
+            : idx == 10 ? isMultiCccmLeftEnabled : isMultiCccmTopEnabled;
+            pu.cccmFlag =  idx == 6 ? 1
+            : idx == 7 ? 2
+            : idx == 8 ? 3
+            : idx == 9 ? 1
+            : idx == 10 ? 2 : 3;
+#else
+            isCCCMEnabled = idx == 3 ? isCccmFullEnabled
+            : idx == 4 ? isCccmLeftEnabled : isCccmTopEnabled;
+            pu.cccmFlag =   idx == 3 ? 1
+            : idx == 4 ? 2 : 3;
+#endif
+         }
+#endif
 
           if (isCCCMEnabled)
           {
@@ -3068,12 +3122,19 @@ void IntraSearch::estIntraPredChromaQT( CodingUnit &cu, Partitioner &partitioner
           }
         }
       }
+#if JVET_AC0054_GLCCCM
+      int tempGlCccmFlag = 0;
+#endif
       int tempCccmIdx = 0;
       int64_t tempCccmCost = 0;
+#if JVET_AC0054_GLCCCM
+      for (int i = 1; i < CCCM_NUM_MODES; i++)
+#else
 #if MMLM
       for (int i = 1; i < 4; i++)
 #else
       for (int i = 1; i < 3; i++)
+#endif
 #endif
       {
         for (int j = i + 1; j < CCCM_NUM_MODES; j++)
@@ -3087,6 +3148,11 @@ void IntraSearch::estIntraPredChromaQT( CodingUnit &cu, Partitioner &partitioner
             tempCccmCost = satdCccmSortedCost[0][i];
             satdCccmSortedCost[0][i] = satdCccmSortedCost[0][j];
             satdCccmSortedCost[0][j] = tempCccmCost;
+#if JVET_AC0054_GLCCCM
+            tempGlCccmFlag = satdCccmFlagList[i];
+            satdCccmFlagList[i] = satdCccmFlagList[j];
+            satdCccmFlagList[j] = tempGlCccmFlag;
+#endif
           }
         }
       }
@@ -3094,10 +3160,26 @@ void IntraSearch::estIntraPredChromaQT( CodingUnit &cu, Partitioner &partitioner
 #if MMLM
       bool isCccmModeEnabledInRdo[2][MMLM_T_IDX + 1] = { false };
       isCccmModeEnabledInRdo[0][satdCccmModeList[0][0]] = true;
+#if JVET_AC0054_GLCCCM
+      bool isGlCccmModeEnabledInRdo[MMLM_T_IDX + 1] = { false };
+      if (satdCccmFlagList[0] == 2)
+      {
+        isCccmModeEnabledInRdo[0][satdCccmModeList[0][0]] = false;
+        isGlCccmModeEnabledInRdo[satdCccmModeList[0][0]] = true;
+      }
+#endif
       for (int i = 1; i < 4; i++)
 #else
       bool isCccmModeEnabledInRdo[MDLM_T_IDX + 1] = { false };
       isCccmModeEnabledInRdo[satdCccmModeList[0]] = true;
+#if JVET_AC0054_GLCCCM
+      bool isGlCccmModeEnabledInRdo[MDLM_T_IDX + 1] = { false };
+      if (satdCccmFlagList[0] == 2)
+      {
+        isCccmModeEnabledInRdo[0][satdCccmModeList[0][0]] = false;
+        isGlCccmModeEnabledInRdo[satdCccmModeList[0][0]] = true;
+      }
+#endif
       for (int i = 1; i < 3; i++)
 #endif
       {
@@ -3105,7 +3187,18 @@ void IntraSearch::estIntraPredChromaQT( CodingUnit &cu, Partitioner &partitioner
         {
           break;
         }
+#if JVET_AC0054_GLCCCM
+        if (satdCccmFlagList[i] == 2)
+        {
+          isGlCccmModeEnabledInRdo[satdCccmModeList[0][i]] = true;
+        }
+        else
+        {
+          isCccmModeEnabledInRdo[0][satdCccmModeList[0][i]] = true;
+        }
+#else
         isCccmModeEnabledInRdo[0][satdCccmModeList[0][i]] = true;
+#endif
       }
 
       if (pu.cu->slice->getSPS()->getUseCccm() == 2)
@@ -3157,7 +3250,11 @@ void IntraSearch::estIntraPredChromaQT( CodingUnit &cu, Partitioner &partitioner
         {
           if (satdCccmSortedCost[1][i] >= CCCM_NO_SUB_WEIGHT * bestCccmCost[1])
           {
+#if JVET_AC0054_GLCCCM
+            if (satdCccmSortedCost[1][i - 1] > bestCccmCost[0] && satdCccmFlagList[0] != 2)
+#else
             if (satdCccmSortedCost[1][i - 1] > bestCccmCost[0])
+#endif
             {
               bestCccmCost[0] = satdCccmSortedCost[1][i - 1];
             }
@@ -3177,6 +3274,9 @@ void IntraSearch::estIntraPredChromaQT( CodingUnit &cu, Partitioner &partitioner
       }
       pu.cccmFlag = 0;
       pu.cccmNoSubFlag = 0;
+#if JVET_AC0054_GLCCCM
+      pu.glCccmFlag = 0;
+#endif
 #else
       int64_t satdCccmSortedCost[CCCM_NUM_MODES];
       int satdCccmModeList[CCCM_NUM_MODES];
@@ -3370,7 +3470,11 @@ void IntraSearch::estIntraPredChromaQT( CodingUnit &cu, Partitioner &partitioner
 #if JVET_AC0147_CCCM_NO_SUBSAMPLING
       if (pu.cu->slice->getSPS()->getUseCccm() == 2)
       {
+#if JVET_AC0054_GLCCCM
+        if (satdSortedCost[uiMaxMode - 1 - reducedModeNumber] > bestCccmCost[0] && satdCccmFlagList[uiMaxMode - 1 - reducedModeNumber] != 2)
+#else
         if (satdSortedCost[uiMaxMode - 1 - reducedModeNumber] > bestCccmCost[0])
+#endif
         {
           modeIsEnable[satdModeList[uiMaxMode - 1 - reducedModeNumber]] = 0; // disable the last reducedModeNumber modes
         }
@@ -3378,7 +3482,11 @@ void IntraSearch::estIntraPredChromaQT( CodingUnit &cu, Partitioner &partitioner
         {
           for (int i = 3; i > 0; i--)
           {
+#if JVET_AC0054_GLCCCM
+            if ((satdCccmSortedCost[0][i] > satdSortedCost[uiMaxMode - 1 - reducedModeNumber]) && (isCccmModeEnabledInRdo[0][satdCccmModeList[0][i]]) && satdCccmFlagList[uiMaxMode - 1 - reducedModeNumber] != 2)
+#else
             if ((satdCccmSortedCost[0][i] > satdSortedCost[uiMaxMode - 1 - reducedModeNumber]) && (isCccmModeEnabledInRdo[0][satdCccmModeList[0][i]]))
+#endif
             {
               isCccmModeEnabledInRdo[0][satdCccmModeList[0][i]] = false;
               break;
@@ -3960,15 +4068,57 @@ void IntraSearch::estIntraPredChromaQT( CodingUnit &cu, Partitioner &partitioner
           pu.cccmFlag = 3;
         }
 #endif
-#if JVET_AC0147_CCCM_NO_SUBSAMPLING
-        if (!isCccmModeEnabledInRdo[0][chromaIntraModeInCCCM] && !isCccmModeEnabledInRdo[1][chromaIntraModeInCCCM])
+          
+#if JVET_AC0054_GLCCCM
+        pu.glCccmFlag = 0;
+        if (uiMode >= CCCM_NUM_MODES / 2)
+        {
+          pu.glCccmFlag = 1;
+#if MMLM
+          chromaIntraModeInCCCM = uiMode == 6 ? LM_CHROMA_IDX
+          : uiMode == 7 ? MDLM_L_IDX
+          : uiMode == 8 ? MDLM_T_IDX
+          : uiMode == 9 ? MMLM_CHROMA_IDX
+          : uiMode == 10 ? MMLM_L_IDX : MMLM_T_IDX;
+          isCCCMEnabled = uiMode == 6 ? isCccmFullEnabled
+          : uiMode == 7 ? isCccmLeftEnabled
+          : uiMode == 8 ? isCccmTopEnabled
+          : uiMode == 9 ? isMultiCccmFullEnabled
+          : uiMode == 10 ? isMultiCccmLeftEnabled : isMultiCccmTopEnabled;
+          pu.cccmFlag =   uiMode == 6 ? 1
+          : uiMode == 7 ? 2
+          : uiMode == 8 ? 3
+          : uiMode == 9 ? 1
+          : uiMode == 10 ? 2 : 3;
 #else
-        if (!isCccmModeEnabledInRdo[chromaIntraModeInCCCM])
+          chromaIntraModeInCCCM = uiMode == 3 ? LM_CHROMA_IDX
+          : uiMode == 4 ? MDLM_L_IDX : MDLM_T_IDX;
+          isCCCMEnabled = uiMode == 3 ? isCccmFullEnabled
+          : uiMode == 4 ? isCccmLeftEnabled : isCccmTopEnabled;
+          pu.cccmFlag  =  uiMode == 3 ? 1
+          : uiMode == 4 ? 2 : 3;
 #endif
+          if (!isGlCccmModeEnabledInRdo[chromaIntraModeInCCCM])
+          {
+            continue;
+          }
+        }
+        else
         {
-          continue;
+#endif // JVET_AC0054_GLCCCM
+        
+#if JVET_AC0147_CCCM_NO_SUBSAMPLING
+          if (!isCccmModeEnabledInRdo[0][chromaIntraModeInCCCM] && !isCccmModeEnabledInRdo[1][chromaIntraModeInCCCM])
+#else
+          if (!isCccmModeEnabledInRdo[chromaIntraModeInCCCM])
+#endif
+          {
+            continue;
+          }
+#if JVET_AC0054_GLCCCM
         }
-
+#endif
+            
         if (isCCCMEnabled)
         {
 #else
@@ -3990,11 +4140,25 @@ void IntraSearch::estIntraPredChromaQT( CodingUnit &cu, Partitioner &partitioner
 #if JVET_AC0147_CCCM_NO_SUBSAMPLING
           for (int sub = 0; sub < pu.cu->slice->getSPS()->getUseCccm(); sub++)
           {
-            pu.cccmNoSubFlag = sub;
-            if (!isCccmModeEnabledInRdo[sub][chromaIntraModeInCCCM])
-            {
-              continue;
-            }
+              pu.cccmNoSubFlag = sub;
+#if JVET_AC0054_GLCCCM
+              if (sub && ((uiMode >= CCCM_NUM_MODES / 2) || pu.glCccmFlag))
+              {
+                continue;
+              }
+              else
+              {
+                if (!isCccmModeEnabledInRdo[sub][chromaIntraModeInCCCM])
+                {
+                  continue;
+                }
+              }
+#else // else of JVET_AC0054_GLCCCM
+              if (!isCccmModeEnabledInRdo[sub][chromaIntraModeInCCCM])
+              {
+                continue;
+              }
+#endif // end of JVET_AC0054_GLCCCM
 #endif
 
           // Original RD check code replicated from above
@@ -4076,7 +4240,10 @@ void IntraSearch::estIntraPredChromaQT( CodingUnit &cu, Partitioner &partitioner
             cccmModeBest    = pu.cccmFlag;
 #if JVET_AA0126_GLM
             bestGlmIdc      = pu.glmIdc;
-#endif 
+#endif
+#if JVET_AC0054_GLCCCM
+            glCccmBest      = pu.glCccmFlag;
+#endif
 #if JVET_AC0147_CCCM_NO_SUBSAMPLING 
             cccmNoSubBest  = pu.cccmNoSubFlag;
             }
@@ -4123,6 +4290,9 @@ void IntraSearch::estIntraPredChromaQT( CodingUnit &cu, Partitioner &partitioner
 #if JVET_AC0147_CCCM_NO_SUBSAMPLING 
     pu.cccmNoSubFlag   = cccmNoSubBest;
 #endif
+#if JVET_AC0054_GLCCCM
+    pu.glCccmFlag = glCccmBest;
+#endif
 #endif
 #if JVET_Z0050_DIMD_CHROMA_FUSION
     pu.isChromaFusion = isChromaFusion;