Observação
O acesso a essa página exige autorização. Você pode tentar entrar ou alterar diretórios.
O acesso a essa página exige autorização. Você pode tentar alterar os diretórios.
Embora o Direct2D seja acelerado por hardware e seja destinado a alto desempenho, você deve usar os recursos corretamente para maximizar a taxa de transferência. As técnicas que mostramos aqui são derivadas do estudo de cenários comuns e podem não se aplicar a todos os cenários de aplicativo. Portanto, uma compreensão cuidadosa do comportamento do aplicativo e das metas de desempenho pode ajudar a alcançar os resultados desejados.
- Uso de recursos
- Restringir o uso da liberação
- bitmaps
- Usar bitmap lado a lado sobre tracejado
- Diretrizes gerais para renderizar conteúdo estático complexo
- Cache por primitiva usando realizações de geometria
- Renderização de geometria
- Desenho de texto com Direct2D
- Recortar uma forma arbitrária
- Interoperabilidade DXGI: evitar mudanças frequentes
- Conheça seu formato de pixel
- Complexidade de cena
- Melhorando o desempenho para aplicativos de impressão Direct2D
- Conclusão
Uso do recurso
Um recurso é uma alocação de algum tipo, seja em vídeo ou na memória do sistema. Bitmaps e pincéis são exemplos de recursos.
No Direct2D, os recursos podem ser criados em software e hardware. A criação e a exclusão de recursos no hardware são operações caras porque exigem muita sobrecarga para se comunicar com a placa de vídeo. Vamos ver como o Direct2D renderiza o conteúdo para um destino.
No Direct2D, todos os comandos de renderização são colocados entre uma chamada para BeginDraw e uma chamada para EndDraw. Essas chamadas são feitas em um destino de renderização. Você deve chamar o método BeginDraw antes de chamar operações de renderização. Depois de chamar BeginDraw , um contexto normalmente cria um lote de comandos de renderização, mas atrasa o processamento desses comandos até que uma dessas instruções seja verdadeira:
- EndDraw ocorreu. Quando EndDraw é chamado, ele faz com que todas as operações de desenho em lote sejam concluídas e retorna o status da operação.
- Você faz uma chamada explícita para Flush: o método Flush faz com que o lote seja processado e todos os comandos pendentes sejam emitidos.
- O buffer que contém os comandos de renderização está cheio. Se esse buffer ficar cheio antes que as duas condições anteriores sejam atendidas, os comandos de renderização são liberados.
Até que as primitivas sejam liberadas, o Direct2D mantém referências internas aos recursos correspondentes, como bitmaps e pincéis.
Reutilizar recursos
Como já mencionado, a criação e a exclusão de recursos são caras no hardware. Portanto, reutilize os recursos quando possível. Veja o exemplo de criação de bitmap no desenvolvimento de jogos. Normalmente, bitmaps que compõem uma cena em um jogo são criados ao mesmo tempo com todas as diferentes variações necessárias para renderização de quadro a quadro posterior. No momento da renderização e da nova renderização da cena real, esses bitmaps são reutilizados em vez de serem recriados.
Observação
Não é possível reutilizar recursos para a operação de redimensionamento da janela. Quando uma janela é redimensionada, alguns recursos dependentes de escala, como destinos de renderização compatíveis e, possivelmente, alguns recursos de camada devem ser recriados porque o conteúdo da janela precisa ser redesenhado. Isso pode ser importante para manter a qualidade geral da cena renderizada.
Restringir o uso da liberação
Como o método Flush faz com que os comandos de renderização em lote sejam processados, recomendamos que você não o use. Para a maioria dos cenários comuns, deixe o gerenciamento de recursos para Direct2D.
Bitmaps
Conforme mencionado anteriormente, a criação e a exclusão de recursos são operações muito caras no hardware. Um bitmap é um tipo de recurso que é usado com frequência. Criar bitmaps na placa de vídeo é caro. Reutilizá-los pode ajudar a tornar o aplicativo mais rápido.
Criar bitmaps grandes
As placas de vídeo normalmente têm um tamanho mínimo de alocação de memória. Se uma alocação for solicitada menor do que isso, um recurso desse tamanho mínimo será alocado e a memória excedente será desperdiçada e indisponível para outras coisas. Se você precisar de muitos bitmaps pequenos, uma técnica melhor será alocar um bitmap grande e armazenar todo o conteúdo de bitmap pequeno neste bitmap grande. Em seguida, subáreas do bitmap maior podem ser lidas onde os bitmaps menores são necessários. Geralmente, você deve incluir preenchimento (pixels pretos transparentes) entre os bitmaps pequenos para evitar qualquer interação entre as imagens menores durante as operações. Isso também é conhecido como um atlas e tem o benefício de reduzir a sobrecarga de criação de bitmap e o desperdício de memória de pequenas alocações de bitmap. Recomendamos manter a maioria dos bitmaps para pelo menos 64 KB e limitar o número de bitmaps menores que 4 KB.
Criar um atlas de bitmaps
Há alguns cenários comuns para os quais um atlas de bitmap pode servir muito bem. Os bitmaps pequenos podem ser armazenados dentro de um bitmap grande. Esses bitmaps pequenos podem ser retirados do bitmap maior quando você precisa deles especificando o retângulo de destino. Por exemplo, um aplicativo precisa desenhar vários ícones. Todos os bitmaps associados aos ícones podem ser carregados previamente em um grande bitmap. E, no momento da renderização, eles podem ser recuperados do bitmap grande.
Observação
Um bitmap Direct2D criado na memória de vídeo é limitado ao tamanho máximo de bitmap suportado pelo adaptador no qual ele é armazenado. Criar um bitmap maior do que isso pode resultar em um erro.
Observação
A partir do Windows 8, o Direct2D inclui um efeito Atlas que pode facilitar esse processo.
Criar bitmaps compartilhados
A criação de bitmaps compartilhados permite que chamadores avançados criem objetos bitmap Direct2D que são apoiados diretamente por um objeto existente, já compatíveis com o destino de renderização. Isso evita a criação de várias superfícies e ajuda a reduzir a sobrecarga de desempenho.
Observação
Os bitmaps compartilhados geralmente são limitados a destinos de software ou a destinos interoperáveis com DXGI. Use os métodos CreateBitmapFromDxgiSurface, CreateBitmapFromWicBitmap e CreateSharedBitmap para criar bitmaps compartilhados.
Cópia de bitmaps
Criar uma superfície DXGI é uma operação cara para reutilizar superfícies existentes quando possível. Mesmo no software, se um bitmap estiver principalmente na forma desejada, exceto por uma pequena parte, é melhor atualizar essa parte do que jogar todo o bitmap fora e recriar tudo. Embora você possa usar CreateCompatibleRenderTarget para obter os mesmos resultados, a renderização geralmente é uma operação muito mais cara do que copiar. Isso se deve ao fato de que, para melhorar a localidade do cache, o hardware não armazena um bitmap na mesma ordem de memória em que ele é endereçado. Em vez disso, o bitmap pode ter swizzling. O swizzling é oculto da CPU pelo driver (que é lento e usado apenas em componentes de baixo desempenho) ou pelo gerenciador de memória da GPU. Devido a restrições sobre como os dados são gravados em um destino de renderização ao renderizar, os destinos de renderização normalmente não têm swizzling ou tem swizzling de uma maneira menos ideal do que pode ser obtida se você souber que nunca precisa renderizar para a superfície. Portanto, os métodos CopyFrom* são fornecidos para copiar retângulos de uma origem para o bitmap Direct2D.
O CopyFrom pode ser usado em qualquer uma de suas três formas:
Usar bitmap lado a lado sobre tracejado
Renderizar uma linha tracejada é uma operação muito cara devido à alta qualidade e precisão do algoritmo subjacente. Para a maioria dos casos que não envolvem geometrias retilineares, o mesmo efeito pode ser gerado mais rapidamente usando bitmaps em mosaico.
Diretrizes gerais para renderizar conteúdo estático complexo
Armazene em cache o conteúdo se você renderizar o mesmo conteúdo frame a frame, especialmente quando a cena for complexa.
Há três técnicas de cache que você pode usar:
- Cache completo da cena usando um bitmap colorido.
- Cache por primitiva usando um bitmap A8 e o método FillOpacityMask.
- Cache por primitiva usando realizações de geometria.
Vamos examinar cada uma delas com mais detalhes.
Cache de cena completo usando um bitmap colorido
Ao renderizar conteúdo estático, em cenários como animação, crie outro bitmap de cor completa em vez de gravar diretamente no bitmap da tela. Salve o destino atual, defina o destino para o bitmap intermediário e renderize o conteúdo estático. Em seguida, volte para o bitmap de tela original e desenhe o bitmap intermediário nele.
Veja um exemplo:
// Create a bitmap.
m_d2dContext->CreateBitmap(size, nullptr, 0,
D2D1::BitmapProperties(
D2D1_BITMAP_OPTIONS_TARGET,
D2D1::PixelFormat(
DXGI_FORMAT_B8G8R8A8_UNORM,
D2D1_ALPHA_MODE_PREMULTIPLIED),
dpiX, dpiY),
&sceneBitmap);
// Preserve the pre-existing target.
ComPtr<ID2D1Image> oldTarget;
m_d2dContext->GetTarget(&oldTarget);
// Render static content to the sceneBitmap.
m_d2dContext->SetTarget(sceneBitmap.Get());
m_d2dContext->BeginDraw();
…
m_d2dContext->EndDraw();
// Render sceneBitmap to oldTarget.
m_d2dContext->SetTarget(oldTarget.Get());
m_d2dContext->DrawBitmap(sceneBitmap.Get());
Este exemplo utiliza bitmaps intermediários para cache e altera o bitmap ao qual o contexto do dispositivo está apontando durante a renderização. Isso evita a necessidade de criar um destino de renderização compatível para a mesma finalidade.
Cache por primitiva usando um bitmap A8 e o método FillOpacityMask
Quando a cena completa não é estática, mas contém elementos estáticos, como geometria ou texto, você pode usar uma técnica de cache por primitiva. Essa técnica preserva as características de suavização da forma primitiva que está sendo armazenada em cache e dá suporte à mudança dos tipos de pincel. Ele usa um bitmap A8 em que o A8 é uma espécie de formato de pixel que representa um canal alfa com 8 bits. A8 bitmaps são úteis para desenhar geometria/texto como uma máscara. Quando você deve manipular a opacidade do conteúdo estático, em vez de manipular o conteúdo em si, você pode traduzir, girar, distorcer ou dimensionar a opacidade da máscara.
Veja um exemplo:
// Create an opacity bitmap.
m_d2dContext->CreateBitmap(size, nullptr, 0,
D2D1::BitmapProperties(
D2D1_BITMAP_OPTIONS_TARGET,
D2D1::PixelFormat(
DXGI_FORMAT_A8_UNORM,
D2D1_ALPHA_MODE_PREMULTIPLIED),
dpiX, dpiY),
&opacityBitmap);
// Preserve the pre-existing target.
ComPtr<ID2D1Image> oldTarget;
m_d2dContext->GetTarget(&oldTarget);
// Render to the opacityBitmap.
m_d2dContext->SetTarget(opacityBitmap.Get());
m_d2dContext->BeginDraw();
…
m_d2dContext->EndDraw();
// Call the FillOpacityMask method
// Note: for this call to work correctly the anti alias mode must be D2D1_ANTIALIAS_MODE_ALIASED.
m_d2dContext->SetTarget(oldTarget.Get());
m_d2dContext->FillOpacityMask(
opacityBitmap.Get(),
m_contentBrush().Get(),
D2D1_OPACITY_MASK_CONTENT_GRAPHICS);
Cache por primitiva usando realizações de geometria
Outra técnica de cache por primitiva, chamada de realizações de geometria, proporciona maior flexibilidade no tratamento da geometria. Quando você quiser desenhar repetidamente geometrias com alias ou anti-alias, é mais rápido convertê-las em representações geométricas e desenhar repetidamente essas representações do que desenhar repetidamente as geometrias em si. As realizações de geometria também geralmente consomem menos memória do que máscaras de opacidade (especialmente para geometrias grandes) e são menos sensíveis às alterações na escala. Para obter mais informações, consulte a Visão geral de Realizações de Geometria.
Veja um exemplo:
// Compute a flattening tolerance based on the scales at which the realization will be used.
float flatteningTolerance = D2D1::ComputeFlatteningTolerance(...);
ComPtr<ID2D1GeometryRealization> geometryRealization;
// Create realization of the filled interior of the geometry.
m_d2dDeviceContext1->CreateFilledGeometryRealization(
geometry.Get(),
flatteningTolerance,
&geometryRealization
);
// In your app's rendering code, draw the geometry realization with a brush.
m_d2dDeviceContext1->BeginDraw();
m_d2dDeviceContext1->DrawGeometryRealization(
geometryRealization.Get(),
m_brush.Get()
);
m_d2dDeviceContext1->EndDraw();
Renderização de geometria
Usar uma primitiva de desenho específica em vez da geometria de desenho
Use chamadas primitivas de desenho mais específicas, como DrawRectangle em vez de chamadas DrawGeometry genéricas. Isso ocorre porque, com DrawRectangle, a geometria já é conhecida, portanto, a renderização é mais rápida.
Renderização de geometria estática
Em cenários em que a geometria é estática, use as técnicas de cache por primitiva explicadas acima. Máscaras de opacidade e realizações de geometria podem melhorar muito a velocidade de renderização de cenas que contêm geometria estática..
Usar um contexto de dispositivo multithread
Os aplicativos que esperam renderizar quantidades significativas de conteúdo geométrico complexo devem considerar especificar o sinalizador D2D1_DEVICE_CONTEXT_OPTIONS_ENABLE_MULTI_THREADED_OPTIMIZATIONS ao criar um contexto de dispositivo Direct2D . Quando esse sinalizador for especificado, o Direct2D distribuirá a renderização em todos os núcleos lógicos presentes no sistema, o que pode diminuir significativamente o tempo de renderização geral.
Observações:
- A partir do Windows 8.1, esse sinalizador afeta apenas a renderização de geometria do caminho. Ele não tem impacto em cenas que contêm apenas outros tipos primitivos (como texto, bitmaps ou realizações de geometria).
- Esse sinalizador também não tem impacto ao renderizar no software (ou seja, ao renderizar com um dispositivo WARP Direct3D). Para controlar o multithreading de software, os chamadores devem usar o sinalizador D3D11_CREATE_DEVICE_PREVENT_INTERNAL_THREADING_OPTIMIZATIONS ao criar um dispositivo WARP Direct3D.
- Especificar esse sinalizador pode aumentar o conjunto de trabalho de pico durante a renderização e também pode aumentar a contenção de thread em aplicativos que já aproveitam o processamento multithreaded.
Desenho de texto com Direct2D
A funcionalidade de renderização de texto Direct2D é oferecida em duas partes. A primeira parte, exposta como o método ID2D1RenderTarget::DrawText e ID2D1RenderTarget::DrawTextLayout, permite que um chamador passe uma cadeia de caracteres e parâmetros de formatação ou um objeto de layout de texto DWrite para suportar vários formatos. Isso deve ser adequado para a maioria dos chamadores. A segunda maneira de renderizar texto, exposta como o método ID2D1RenderTarget::D rawGlyphRun , fornece rasterização para clientes que já sabem a posição dos glifos que desejam renderizar. As duas regras gerais a seguir podem ajudar a melhorar o desempenho do texto ao desenhar no Direct2D.
DrawTextLayout versus DrawText
DrawText e DrawTextLayout permitem que um aplicativo renderize facilmente o texto formatado pela API DirectWrite. DrawTextLayout desenha um objeto DWriteTextLayout existente para o RenderTarget e DrawText constrói um layout DirectWrite para o chamador, com base nos parâmetros passados. Se o mesmo texto precisar ser renderizado várias vezes, use DrawTextLayout em vez de DrawText, porque DrawText cria um layout sempre que é chamado.
Escolhendo o modo de renderização de texto correto
Defina o modo antialias de texto para D2D1_TEXT_ANTIALIAS_MODE_GRAYSCALE explicitamente. A qualidade da renderização do texto em escala de cinza é comparável ao ClearType, mas é muito mais rápida.
Cache
Use o cache de bitmap por cena completa ou por primitiva, como ao desenhar outras primitivas.
Recortar uma forma arbitrária
A figura aqui mostra o resultado da aplicação de um clipe a uma imagem.

Você pode obter esse resultado usando camadas com uma máscara de geometria ou o método FillGeometry com um pincel de opacidade.
Aqui está um exemplo que usa uma camada:
// Call PushLayer() and pass in the clipping geometry.
m_d2dContext->PushLayer(
D2D1::LayerParameters(
boundsRect,
geometricMask));
Aqui está um exemplo que usa o método FillGeometry :
// Create an opacity bitmap and render content.
m_d2dContext->CreateBitmap(size, nullptr, 0,
D2D1::BitmapProperties(
D2D1_BITMAP_OPTIONS_TARGET,
D2D1::PixelFormat(
DXGI_FORMAT_A8_UNORM,
D2D1_ALPHA_MODE_PREMULTIPLIED),
dpiX, dpiY),
&opacityBitmap);
m_d2dContext->SetTarget(opacityBitmap.Get());
m_d2dContext->BeginDraw();
…
m_d2dContext->EndDraw();
// Create an opacity brush from the opacity bitmap.
m_d2dContext->CreateBitmapBrush(opacityBitmap.Get(),
D2D1::BitmapBrushProperties(),
D2D1::BrushProperties(),
&bitmapBrush);
// Call the FillGeometry method and pass in the clip geometry and the opacity brush
m_d2dContext->FillGeometry(
clipGeometry.Get(),
brush.Get(),
opacityBrush.Get());
Neste exemplo de código, quando você chama o método PushLayer, você não passa uma camada criada pelo aplicativo. O Direct2D cria uma camada para você. O Direct2D é capaz de gerenciar a alocação e a destruição desse recurso sem qualquer envolvimento do aplicativo. Isso permite que o Direct2D reutilize camadas internamente e aplique otimizações de gerenciamento de recursos.
No Windows 8, muitas otimizações foram feitas para o uso de camadas e recomendamos que você tente usar APIs de camada em vez de FillGeometry sempre que possível.
PushLayer no Windows 8
A interface ID2D1DeviceContext é derivada da interface ID2D1RenderTarget e é fundamental para exibir conteúdo direct2D no Windows 8, para obter mais informações sobre essa interface, consulte Dispositivos e Contextos do Dispositivo. Com a interface de contexto do dispositivo, você pode ignorar a chamada do método CreateLayer e passar NULL para o método ID2D1DeviceContext::P ushLayer . O Direct2D gerencia automaticamente o recurso de camada e pode compartilhar recursos entre camadas e grafos de efeito.
Recortes alinhados ao eixo
Se a região a ser recortada estiver alinhada ao eixo da superfície de desenho, em vez de arbitrária. Esse caso é adequado para usar um retângulo de recorte em vez de uma camada. O ganho de desempenho é maior para a geometria com alias do que para a geometria com suavização. Para obter mais informações sobre clipes alinhados ao eixo, consulte o tópico PushAxisAlignedClip .
Interoperabilidade DXGI: evitar trocas frequentes
O Direct2D pode interoperar perfeitamente com superfícies Direct3D. Isso é muito útil para criar aplicativos que renderizam uma mistura de conteúdo 2D e 3D. No entanto, cada troca entre o desenho de conteúdo Direct2D e Direct3D afeta o desempenho.
Ao renderizar em uma superfície DXGI, o Direct2D salva o estado dos dispositivos Direct3D durante a renderização e restaura-o quando a renderização é concluída. Sempre que um lote de renderização Direct2D é concluído, os custos de salvar e restaurar, assim como de liberar todas as operações 2D, são pagos; entretanto, o dispositivo Direct3D não é liberado. Portanto, para aumentar o desempenho, limite o número de opções de renderização entre Direct2D e Direct3D.
Conheça seu formato de pixel
Ao criar um destino de renderização, você pode usar a estrutura D2D1_PIXEL_FORMAT especificar o formato de pixel e o modo alfa usados pelo destino de renderização. Um canal alfa faz parte do formato de pixel que especifica o valor de cobertura ou as informações de opacidade. Se um destino de renderização não usar o canal alfa, ele deverá ser criado usando o modo alfa D2D1_ALPHA_MODE_IGNORE . Isso poupa o tempo gasto na renderização de um canal alfa que não é necessário.
Para obter mais informações sobre formatos de pixel e modos alfa, consulte formatos de pixel e modos alfa com suporte.
Complexidade de cena
Quando você analisa pontos críticos de desempenho em uma cena que será renderizada, saber se a cena está limitada pela taxa de preenchimento ou pelo número de vértices pode fornecer informações úteis.
- Taxa de preenchimento: a taxa de preenchimento refere-se ao número de pixels que uma placa gráfica pode renderizar e gravar na memória de vídeo por segundo.
- Limitação por Vértices: uma cena é limitada por vértices quando contém muita geometria complexa.
Entender a complexidade da cena
Você pode analisar a complexidade da cena alterando o tamanho do destino de renderização. Se os ganhos de desempenho estiverem visíveis para uma redução proporcional no tamanho do destino de renderização, o aplicativo está limitado pela taxa de preenchimento. Caso contrário, a complexidade da cena é o gargalo de desempenho.
Quando uma cena está limitada pela taxa de preenchimento, reduzir o tamanho do alvo de renderização pode melhorar o desempenho. Isso ocorre porque o número de pixels a serem renderizados será reduzido proporcionalmente com o tamanho do destino de renderização.
Quando uma cena estiver vinculada a vértices, reduza a complexidade da geometria. Mas lembre-se de que isso é feito às custas da qualidade da imagem. Portanto, uma decisão de compensação cuidadosa deve ser tomada entre a qualidade desejada e o desempenho necessário.
Melhorando o desempenho para aplicativos de impressão Direct2D
O Direct2D oferece compatibilidade com impressão. Você pode enviar os mesmos comandos de desenho Direct2D (na forma de listas de comandos Direct2D) para o controle de impressão Direct2D para impressão, se não souber para quais dispositivos você está desenhando ou como o desenho é traduzido para impressão.
Você pode ajustar ainda mais o uso do controle de impressão Direct2D e seus comandos de desenho Direct2D para fornecer resultados de impressão com melhor desempenho.
O controle de impressão Direct2D gera mensagens de depuração quando vê um padrão de código Direct2D que leva a uma menor qualidade de impressão ou desempenho (como padrões de código listados posteriormente neste tópico) para lembrá-lo de onde você pode evitar problemas de desempenho. Para ver essas mensagens de depuração, você precisa habilitar a Camada de Depuração do Direct2D em seu código. Consulte Mensagens de Depuração para obter instruções para habilitar a saída de mensagens de depuração.
Definir os valores de propriedade corretos ao criar o controle de impressão D2D
Há três propriedades que você pode definir ao criar o controle de impressão Direct2D . Duas dessas propriedades afetam como o controle de impressão Direct2D manipula determinados comandos Direct2D e, por sua vez, afetam o desempenho geral.
- Modo de Subconjunto de Fonte: o controle de impressão Direct2D subconjunta os recursos de fonte usados em cada página antes de enviá-la para impressão. Esse modo reduz o tamanho dos recursos de página necessários para impressão. Dependendo do uso da fonte na página, você pode escolher diferentes modos de subconjunto de fonte para obter o melhor desempenho.
- D2D1_PRINT_FONT_SUBSET_MODE_DEFAULT fornece o melhor desempenho de impressão na maioria dos casos. Quando definido para esse modo, o controle de impressão Direct2D usa uma estratégia heurística para decidir quando subconjuntar fontes.
- Para trabalhos de impressão curta com 1 ou 2 páginas, recomendamos D2D1_PRINT_FONT_SUBSET_MODE_EACHPAGE, em que o controle de impressão Direct2D sub-conjunta e insere os recursos de fonte em cada página e descarta esse subconjunto de fonte após a página ser impressa. Essa opção garante que cada página possa ser impressa imediatamente após ser gerada, mas aumenta ligeiramente o tamanho dos recursos de página necessários para impressão (com subconjuntos de fonte geralmente grandes).
- Para trabalhos de impressão com muitas páginas de textos e tamanhos de fonte pequenos (como 100 páginas de texto que usa uma única fonte), recomendamos D2D1_PRINT_FONT_SUBSET_MODE_NONE, em que o controle de impressão Direct2D não subconjunta recursos de fonte; Em vez disso, ele envia os recursos de fonte originais junto com a página que primeiro usa a fonte e reutiliza os recursos de fonte para páginas posteriores sem reenviar.
- DPI de rasterização: quando o controle de impressão Direct2D precisa rasterizar comandos Direct2D durante Direct2D-XPS conversão, ele usa esse DPI para rasterização. Em outras palavras, se a página não tiver nenhum conteúdo rasterizado, a configuração de qualquer DPI não alterará o desempenho e a qualidade. Dependendo do uso de rasterização na página, você pode escolher DPIs de rasterização diferentes para obter o melhor equilíbrio entre fidelidade e desempenho.
- 150 é o valor padrão se você não especificar um valor ao criar o controle de impressão Direct2D , que é o melhor equilíbrio de qualidade de impressão e desempenho de impressão na maioria dos casos.
- Valores de DPI mais altos geralmente resultam em melhor qualidade de impressão (como em mais detalhes preservados), mas menor desempenho devido aos bitmaps maiores gerados. Não recomendamos nenhum valor de DPI maior que 300, pois isso não introduzirá informações extras visualmente percebíveis pelos olhos humanos.
- A DPI mais baixa pode significar um melhor desempenho, mas também pode produzir uma qualidade menor.
Evite usar determinados padrões de desenho Direct2D
Há diferenças entre o que o Direct2D pode representar visualmente e o que o subsistema de impressão pode manter e transportar ao longo de todo o pipeline de impressão. O controle de impressão Direct2D faz a ponte entre essas lacunas, aproximando ou rasterizando primitivos Direct2D que o subsistema de impressão não dá suporte nativo. Essa aproximação geralmente resulta em menor fidelidade de impressão, menor desempenho de impressão ou ambos. Portanto, mesmo que um cliente possa usar os mesmos padrões de desenho para renderização de tela e impressão, ele não é ideal em todos os casos. É preferível evitar ao máximo usar esses primitivos e padrões Direct2D para o caminho de impressão, ou então realizar sua própria rasterização, onde você tenha controle total sobre a qualidade e o tamanho das imagens rasterizadas.
Aqui está uma lista de casos em que o desempenho e a qualidade da impressão não serão ideais e talvez você queira considerar a variação do caminho do código para um desempenho de impressão ideal.
- Evite usar qualquer modo de mistura primitiva diferente de D2D1_PRIMITIVE_BLEND_SOURCEOVER.
- Evite usar modos de composição ao desenhar uma imagem, exceto D2D1_COMPOSITE_MODE_SOURCE_OVER e D2D1_COMPOSITE_MODE_DESTINATION_OVER.
- Evite desenhar um arquivo meta GDI.
- Evite executar o push de um recurso de camada que copie o plano de fundo de origem (chamando PushLayer passando D2D1_LAYER_OPTIONS1_INITIALIZE_FROM_BACKGROUND para a struct D2D1_LAYER_PARAMETERS1).
- Evite criar o Pincel de Bitmap ou o Pincel de Imagem com D2D1_EXTEND_MODE_CLAMP. Recomendamos o uso de D2D1_EXTEND_MODE_MIRROR caso você não se importe com pixels fora dos limites da imagem (por exemplo, quando a imagem anexada ao pincel é maior do que a região de destino preenchida).
- Evite desenhar Bitmaps com Transformações de Perspectiva.
Desenhar texto de maneira direta e simples
O Direct2D tem várias otimizações ao renderizar textos a serem exibidos para melhor desempenho e/ou melhor qualidade visual. Mas nem todas as otimizações melhoram o desempenho e a qualidade da impressão, pois a impressão em papel geralmente está em um DPI muito maior, e a impressão não precisa acomodar cenários como animação. Portanto, recomendamos desenhar diretamente o texto ou glifos originais e evitar qualquer uma das otimizações a seguir ao criar a lista de comandos para impressão.
- Evite desenhar texto com o método FillOpacityMask .
- Evite desenhar texto no Modo Aliased.
Desenhar os bitmaps originais quando possível
Se o bitmap de destino for um JPEG, PNG, TIFF ou JPEG-XR, você pode criar um bitmap WIC de um arquivo de disco ou de um fluxo na memória e, em seguida, criar um bitmap Direct2D desse bitmap WIC usando ID2D1DeviceContext::CreateBitmapFromWicBitmap e, por fim, passar diretamente esse bitmap direct2D para o controle de impressão Direct2D sem manipulação adicional. Ao fazer isso, o controle de impressão Direct2D é capaz de reutilizar o fluxo de bitmap, o que geralmente leva a um melhor desempenho de impressão (ignorando a codificação e a decodificação de bitmap redundantes) e melhor qualidade de impressão (quando metadados, como perfis de cor, no bitmap serão preservados).
Desenhar o bitmap original fornece o seguinte benefício para aplicativos.
- Em geral, a impressão Direct2D preserva as informações originais (sem perda ou ruído) até o final do pipeline, especialmente quando os aplicativos não sabem (ou não querem saber) os detalhes do pipeline de impressão (como para qual impressora ele está imprimindo, qual DPI é a impressora de destino e assim por diante).
- Em muitos casos, atrasar a rasterização de bitmap significa melhor desempenho (como ao imprimir uma foto 96dpi em uma impressora 600dpi).
- Em determinados casos, passar as imagens originais é a única maneira de honrar a alta fidelidade (como perfis de cores inseridos).
No entanto, não é possível optar por essa otimização porque:
- Consultando informações da impressora e realizando a rasterização antecipada, você mesmo pode rasterizar o conteúdo com controle total da aparência final no papel.
- Em certos casos, a rasterização precoce pode realmente melhorar o desempenho de ponta a ponta de um aplicativo (como imprimir fotos do tamanho de carteiras).
- Em determinados casos, a transferência dos bitmaps originais exige uma alteração significativa na arquitetura de código existente (como o carregamento diferido de imagem e os caminhos de atualização de recursos encontrados em determinados aplicativos).
Conclusão
Embora o Direct2D seja acelerado por hardware e seja destinado a alto desempenho, você deve usar os recursos corretamente para maximizar a taxa de transferência. As técnicas que examinamos aqui são derivadas do estudo de cenários comuns e podem não se aplicar a todos os cenários de aplicativo.