public BMPAlloc Allocate(DynamicAtlasCore atlasManager)
        {
            int pageCount = m_Pages.Count;

            for (int pageIndex = 0; pageIndex < pageCount; pageIndex++)
            {
                var pageInfo = m_Pages[pageIndex];
                if (pageInfo.freeSlots == 0)
                {
                    continue;
                }

                int line    = pageIndex * m_PageHeight;
                int endLine = line + m_PageHeight;
                for (; line < endLine; line++)
                {
                    var allocBits = m_AllocMap[line];
                    if (allocBits == 0)
                    {
                        continue;
                    }
                    byte allocIndex = CountTrailingZeroes(allocBits);
                    m_AllocMap[line] = allocBits & (~(1U << allocIndex));
                    pageInfo.freeSlots--;
                    m_Pages[pageIndex] = pageInfo;
                    return(new BMPAlloc()
                    {
                        page = pageIndex, pageLine = (ushort)(line - pageIndex * m_PageHeight), bitIndex = allocIndex, ownedState = OwnedState.Owned
                    });
                } // For each line
            }     // For each page

            RectInt uvRect;

            if ((atlasManager == null) || !atlasManager.AllocateRect(kPageWidth * m_EntryWidth, m_PageHeight * m_EntryHeight, out uvRect))
            {
                return(BMPAlloc.Invalid);
            }

            m_AllocMap.Capacity += m_PageHeight;
            m_AllocMap.Add(0xFFFFFFFE); // Reserve first slot
            for (int i = 1; i < m_PageHeight; i++)
            {
                m_AllocMap.Add(0xFFFFFFFF);
            }

            m_Pages.Add(new Page()
            {
                x = (UInt16)uvRect.xMin, y = (UInt16)uvRect.yMin, freeSlots = kPageWidth * m_PageHeight - 1
            });
            return(new BMPAlloc()
            {
                page = m_Pages.Count - 1, ownedState = OwnedState.Owned
            });
        }
        void ReallyCreateAtlas()
        {
            m_Atlas = new DynamicAtlasCore(
                m_VertexTexturingEnabled ? RenderTextureFormat.ARGBFloat : RenderTextureFormat.ARGB32, // If no vertex texturing, only store opacity in ARGB32
                FilterMode.Point,                                                                      // Filtering is never needed for this texture
                Math.Max(pageWidth, pageHeight * 3),                                                   // Each transform row is stored vertically
                64);                                                                                   // Because we want predictable placement of first pages, 64 will fit all default allocs

            // The order of allocation from the atlas below is important. See the comment at the beginning of Construct().
            RectInt rcTransform, rcClipRect, rcOpacity, rcTextCoreSettings;

            m_Atlas.AllocateRect(pageWidth * m_TransformAllocator.entryWidth, pageHeight * m_TransformAllocator.entryHeight, out rcTransform);
            m_Atlas.AllocateRect(pageWidth * m_ClipRectAllocator.entryWidth, pageHeight * m_ClipRectAllocator.entryHeight, out rcClipRect);
            m_Atlas.AllocateRect(pageWidth * m_OpacityAllocator.entryWidth, pageHeight * m_OpacityAllocator.entryHeight, out rcOpacity);
            m_Atlas.AllocateRect(pageWidth * m_TextSettingsAllocator.entryWidth, pageHeight * m_TextSettingsAllocator.entryHeight, out rcTextCoreSettings);

            if (!AtlasRectMatchesPage(ref m_TransformAllocator, identityTransform, rcTransform))
            {
                throw new Exception("Atlas identity transform allocation failed unexpectedly");
            }

            if (!AtlasRectMatchesPage(ref m_ClipRectAllocator, infiniteClipRect, rcClipRect))
            {
                throw new Exception("Atlas infinite clip rect allocation failed unexpectedly");
            }

            if (!AtlasRectMatchesPage(ref m_OpacityAllocator, fullOpacity, rcOpacity))
            {
                throw new Exception("Atlas full opacity allocation failed unexpectedly");
            }

            if (!AtlasRectMatchesPage(ref m_TextSettingsAllocator, defaultTextCoreSettings, rcTextCoreSettings))
            {
                throw new Exception("Atlas text setting allocation failed unexpectedly");
            }

            var whiteTexel = UIRenderDevice.whiteTexel;

            if (m_VertexTexturingEnabled)
            {
                SetTransformValue(identityTransform, identityTransformValue);
                SetClipRectValue(infiniteClipRect, infiniteClipRectValue);
            }
            {
                SetOpacityValue(fullOpacity, fullOpacityValue.w);
                SetTextCoreSettingValue(defaultTextCoreSettings, defaultTextCoreSettingsValue);
            }

            m_AtlasReallyCreated = true;
        }
 public void Dispose()
 {
     if (m_Atlas != null)
     {
         m_Atlas.Dispose();
     }
     m_Atlas = null;
     if (m_ClipRects.IsCreated)
     {
         m_ClipRects.Dispose();
     }
     if (m_Transforms.IsCreated)
     {
         m_Transforms.Dispose();
     }
     m_AtlasReallyCreated = false;
 }