55#include " impeller/typographer/backends/skia/typographer_context_skia.h"
66
77#include < cstddef>
8+ #include < memory>
89#include < numeric>
910#include < utility>
1011#include < vector>
1314#include " flutter/fml/trace_event.h"
1415#include " fml/closure.h"
1516
17+ #include " impeller/base/validation.h"
1618#include " impeller/core/allocator.h"
1719#include " impeller/core/buffer_view.h"
1820#include " impeller/core/formats.h"
@@ -400,11 +402,15 @@ std::shared_ptr<GlyphAtlas> TypographerContextSkia::CreateGlyphAtlas(
400402 // IF the current atlas size is as big as it can get, then "GC" and create an
401403 // atlas with only the required glyphs.
402404 bool blit_old_atlas = true ;
405+ std::shared_ptr<GlyphAtlas> new_atlas = last_atlas;
403406 if (atlas_context->GetAtlasSize ().height >= max_texture_height) {
404407 blit_old_atlas = false ;
405408 first_missing_index = 0 ;
406409 glyph_positions.clear ();
407410 height_adjustment = 0 ;
411+ new_atlas = std::make_shared<GlyphAtlas>(type);
412+ atlas_context->UpdateRectPacker (nullptr );
413+ atlas_context->UpdateGlyphAtlas (new_atlas, {0 , 0 }, 0 );
408414 }
409415
410416 // A new glyph atlas must be created.
@@ -415,7 +421,7 @@ std::shared_ptr<GlyphAtlas> TypographerContextSkia::CreateGlyphAtlas(
415421 max_texture_height //
416422 );
417423
418- atlas_context->UpdateGlyphAtlas (last_atlas , atlas_size, height_adjustment);
424+ atlas_context->UpdateGlyphAtlas (new_atlas , atlas_size, height_adjustment);
419425 if (atlas_size.IsEmpty ()) {
420426 return nullptr ;
421427 }
@@ -433,89 +439,68 @@ std::shared_ptr<GlyphAtlas> TypographerContextSkia::CreateGlyphAtlas(
433439 }
434440 descriptor.size = atlas_size;
435441 descriptor.storage_mode = StorageMode::kDevicePrivate ;
436- descriptor.usage = TextureUsage::kShaderRead | TextureUsage:: kRenderTarget ;
442+ descriptor.usage = TextureUsage::kShaderRead ;
437443 std::shared_ptr<Texture> new_texture =
438444 context.GetResourceAllocator ()->CreateTexture (descriptor);
439- new_texture->SetLabel (" GlyphAtlas" );
440-
441445 if (!new_texture) {
442446 return nullptr ;
443447 }
444448
445449 new_texture->SetLabel (" GlyphAtlas" );
446450
447451 std::shared_ptr<CommandBuffer> cmd_buffer = context.CreateCommandBuffer ();
448- std::shared_ptr<BlitPass> blit_pass;
452+ std::shared_ptr<BlitPass> blit_pass = cmd_buffer-> CreateBlitPass () ;
449453
450454 // The R8/A8 textures used for certain glyphs is not supported as color
451- // attachments in most graphics drivers. To be safe, just do a CPU clear
452- // for these.
453- if (type == GlyphAtlas::Type::kAlphaBitmap ) {
454- size_t byte_size =
455- new_texture->GetTextureDescriptor ().GetByteSizeOfBaseMipLevel ();
456- BufferView buffer_view =
457- host_buffer.Emplace (nullptr , byte_size, DefaultUniformAlignment ());
458-
459- ::memset (buffer_view.buffer->OnGetContents () + buffer_view.range.offset, 0,
460- byte_size);
461- buffer_view.buffer->Flush ();
462- blit_pass = cmd_buffer->CreateBlitPass ();
463- blit_pass->AddCopy (buffer_view, new_texture);
464- } else {
465- // In all other cases, we can use a render pass to clear to a transparent
466- // color.
467- ColorAttachment attachment;
468- attachment.clear_color = Color::BlackTransparent ();
469- attachment.load_action = LoadAction::kClear ;
470- attachment.store_action = StoreAction::kStore ;
471- attachment.texture = new_texture;
472-
473- RenderTarget render_target;
474- render_target.SetColorAttachment (attachment, 0u );
475-
476- auto render_pass = cmd_buffer->CreateRenderPass (render_target);
477- render_pass->EncodeCommands ();
478- blit_pass = cmd_buffer->CreateBlitPass ();
479- }
480- FML_DCHECK (!!blit_pass);
455+ // attachments in most graphics drivers. For other textures, most framebuffer
456+ // attachments have a much smaller size limit than the max texture size.
457+ size_t byte_size =
458+ new_texture->GetTextureDescriptor ().GetByteSizeOfBaseMipLevel ();
459+ BufferView buffer_view =
460+ host_buffer.Emplace (nullptr , byte_size, DefaultUniformAlignment ());
461+
462+ ::memset (buffer_view.buffer->OnGetContents () + buffer_view.range.offset, 0,
463+ byte_size);
464+ buffer_view.buffer->Flush ();
465+ blit_pass->AddCopy (buffer_view, new_texture);
481466
482467 fml::ScopedCleanupClosure closure ([&]() {
483468 blit_pass->EncodeCommands (context.GetResourceAllocator ());
484469 context.GetCommandQueue ()->Submit ({std::move (cmd_buffer)});
485470 });
486471
487472 // Blit the old texture to the top left of the new atlas.
488- if (last_atlas ->GetTexture () && blit_old_atlas) {
489- blit_pass->AddCopy (last_atlas ->GetTexture (), new_texture,
490- IRect::MakeSize (last_atlas ->GetTexture ()->GetSize ()),
473+ if (new_atlas ->GetTexture () && blit_old_atlas) {
474+ blit_pass->AddCopy (new_atlas ->GetTexture (), new_texture,
475+ IRect::MakeSize (new_atlas ->GetTexture ()->GetSize ()),
491476 {0 , 0 });
492477 }
493478
494479 // Now append all remaining glyphs. This should never have any missing data...
495- last_atlas ->SetTexture (std::move (new_texture));
480+ new_atlas ->SetTexture (std::move (new_texture));
496481
497482 // ---------------------------------------------------------------------------
498483 // Step 3a: Record the positions in the glyph atlas of the newly added
499484 // glyphs.
500485 // ---------------------------------------------------------------------------
501486 for (size_t i = first_missing_index; i < glyph_positions.size (); i++) {
502- last_atlas ->AddTypefaceGlyphPosition (new_glyphs[i], glyph_positions[i]);
487+ new_atlas ->AddTypefaceGlyphPosition (new_glyphs[i], glyph_positions[i]);
503488 }
504489
505490 // ---------------------------------------------------------------------------
506491 // Step 4a: Draw new font-glyph pairs into the a host buffer and encode
507492 // the uploads into the blit pass.
508493 // ---------------------------------------------------------------------------
509- if (!UpdateAtlasBitmap (*last_atlas , blit_pass, host_buffer,
510- last_atlas ->GetTexture (), new_glyphs,
494+ if (!UpdateAtlasBitmap (*new_atlas , blit_pass, host_buffer,
495+ new_atlas ->GetTexture (), new_glyphs,
511496 first_missing_index, new_glyphs.size ())) {
512497 return nullptr ;
513498 }
514499 // ---------------------------------------------------------------------------
515500 // Step 8b: Record the texture in the glyph atlas.
516501 // ---------------------------------------------------------------------------
517502
518- return last_atlas ;
503+ return new_atlas ;
519504}
520505
521506} // namespace impeller
0 commit comments