O padrão VGA, SuperVGAs e outras considerações

No final dos anos 80 a IBM lançou o PS/2 (Professional System/2). Era “profissional”, ao invés de “Pessoal” (Personal Conputer) e possuia alguns recursos “avançados”, em relação ao PC. A arquitetura do barramento era a MicroChannel, bem mais versátil que o ISA (Industry Standard Architecture e o circuito de vídeo era melhor… Ao invés do CGA (Color Graphics Adapter) e EGA (Enhenced Graphics Adapter), a IBM estendeu a última e chamou de VGA (Video Graphics Array).

O padrão VGA persiste até hoje, ainda disponível nas placas de vídeo mais modernas. E não poderia ser diferente, já que todas as BIOS têm que ter um terreno comum para trabalhar.

É interessante ver que a maioria das pessoas lida com vídeo como se fosse algo mágico que só pode ser usado via rotinas da BIOS (aliás, a maioria dos dispositivos parecem funcionar por “mágica”). Aqui, quero estender um pouco o que já escrevi no meu antigo “Curso de Assembly da RBT” e explicar as entranhas da VGA.

Anatomia de um sinal de vídeo composto:

Para entender o que uma placa de vídeo faz é necessário entender como o sinal de vídeo é criado… Abaixo temos um exemplo de sinal de vídeo “composto” para uma única linha do padrão de teste mais famoso do mundo:

Colo pattern 2
O padrão de teste gera uma onda característica.

O sinal é dito “composto” porque, num único sinal eletromagnético (transmitido por rádio) consegue-se montar uma imagem composta de quatro grandezas diferentes: Intensidade e as cores vermelha, verde e azul.

No exemplo do sinal, o pulso negativo, do lado esquerdo, é chamado de “pulso de sincronismo horizontal”. Este pulso faz com que o circuito de deflexão “puxe” o feixe de elétrons, do tubo de raios catódicos (CRT), para o início de uma linha, para a esquerda… Logo depois temos cerca de 9 ciclos de uma senoide de frequência de 4,43361875 MHz (PAL-M) ou 3.57954(54) MHz (NTSC) — o 54, entre parênteses é uma dizima periódica. Essa senoide é usada para sincronizar a fase dos circuitos de cor… Cores são calculadas como a diferença de modulação de fase da senóide de cada pixel em relação à fase deste sinal… Na figura acima, além das “cores” branca e preta, as demais são formadas pelo “nível de cinza” somado à senoide com fase específica para cada cor.

A cor branca é obtida quando o nível de sinal médio estiver em 100% e sem nenhuma portadora de cor. Se houver uma portadora de cor então o branco é somado a essa cor… O nível de preto é obtido um pouco acima do nível de referência zero. Isso porque zero é o nível do apagamento do feixe de elétrons, em preparação para um retraço. Embora o nível de apagamento seja um pouquinho mais negativo, para garantir que o feixe esteja realmente apagado!

Cada linha de um quadro segue esse padrão… Ao final de um quadro, acontecerá uma mudança no sinal de vídeo: Os pulsos de sincronismo horizontal ficarão mais frequentes (menos espaçados), depois maiores… Isso indica um sincronismo vertical, onde o feixe de elétrons é “levado” para o topo da tela novamente:

Sincronismo vertical entre quadros
Sincronismo vertical entre quadros

No diagrama acima podemos ver que o tempo de uma única linha, entre os pulsos de sincronismo horizontal, é de cerca de 63,5 μs. O tempo desses pulsos diminui pela metade na preparação para sincronismo vertical (pulsos de equalização). Seque-se pulsos com a mesma frequência, mas duração maior, e mais pulsos de equalização… Estamos agora no topo da tela, de novo….

É importante notar que um sinal de vídeo não é feito apenas de pixels. Aliás, não existem pixels num sinal de vídeo… O feixe de elétrons vai varrendo a linha e sendo modulado para excitar mais ou menos um dos emissores de luz na grade perto do observador. Os “pixels” existem nesta grade…

Aliás, é comum encontrar a sigla PEL, ao invés de “pixel”, na literatura especializada… Usarei PEL, daqui por diante. Outro termo muito usado é “scanline” ou “linha de varredura”. Basta lembrar que o feixe “varre a linha”…

No sinal, acima, o intervalo para cada PEL não é visível, mas, considerando que o intervalo de uma linha (1H) tem 63,5 μs, o período de um único ponto é bem menor. De fato, no padrão VGA, a frequência de clock que domina a geração dos PELs é, no mínimo, de 25 MHz. Essa frequência é chamada de dot clock. Toda temporização tem, como base, essa frequência (existem frequência alternativas para resoluções maiores, como 28 MHz — a SuperVGA, com resoluções ainda maiores e frequências de varredura vertical grandes [frames por segundo] usa dot clocks ainda maiores). Veremos adiante como isso é usado na controladora CRTC.

Resolução gráfica

Existem dois fatores que determinam a resolução gráfica de um modo de vídeo no padrão VGA: A polaridade dos sinais de sincronismo e a quantidade máxima de caracteres (sim! caracteres!) numa scanline.

As maiores resoluções verticais são obtidas com a polaridade negativa do sincronismo vertical (350 ou 480 linhas). A polaridade positiva nos dá 400 linhas… A seleção das duas maiores possíveis resoluções verticais é obtida de acordo com a polaridade dos pulsos de sincronismo horizontais… Se os pulsos forem também negativos, temos 480 linhas, caso contrário, 350.

Até então, vimos apenas a resolução vertical — com um detalhe: ambos os sinais de sincronismo com os pulsos “positivos” são proibidos! — E esse tipo de seleção só funciona se o monitor CRT for multisync. É o que todo monitor CRT VGA é! Mas, e quanto à resolução horizontal?

Lembre-se que apenas os pulsos de sincronismo precisam ser… eh… como direi?… sincronizados! CRTs são dispositivos analógicos que, em teoria, podem suportar qualquer resolução gráfica possível, com a restrição feita apenas pela máscara dos elementos emissores de fótons (que tem gente que insiste em chamar de fósforo!). A resolução vertical é fixada pelos sentidos dos pulsos de sincronismo, já a resolução horizontal depende somente dos registradores de controle horizontal do CRTC (citado abaixo). Em teoria uma placa VGA poderia mostrar uns 2000 PELs na horizontal. Na prática, no máximo, chega a 720.

VGA é composta de 4 controladores:

A especificação original do padrão VGA (e do padrão XGA) da IBM pode ser obtido aqui. Além dos livros de Richard Ferraro e Michael Abrash, este é o material de referência primordial para o entendimento do funcionamento desse circuito gráfico.

Existem, pelo menos, 4 chips dedicados numa placa VGA: Um que controla o monitor de vídeo (CRTC), um que controla a ordem com que os dados chegam ou saem da placa (Sequencer), um que controla a geração de cores (Attribute Controller) e outro que faz a interface entre o computador e as entranhas da placa (Graphics Controller):

  • CRTC: Literalmente CRT Controller. O objetivo dessa controladora é a geração dos sinais de sincronismo, apagamento do canhão de elétrons e a temporização dos pulsos de retraços horizontal e vertical. Ele não lida com o sinal “visível” da imagem. Isso fica à cargo das outras controladoras;
  • Sequencer: O sequenciador é a controladora que decodifica endereços de memória vindas do barramento do sistema e também mantém os contadores internos que “sequenciam” o acesso à memória de vídeo, interna, para a geração da imagem — falarei da diferença dessas duas memórias mais adiante;
  • Attribute Controller: Esta a controladora que lida com cores. Ela é quem mantém a paleta de cores (dentre as 262144 cores possíveis para a VGA). Ela também decodifica atributos nos modos alfanuméricos;
  • Graphics Controller: Essa controladora faz a interface com o barramento do sistema e as outras controladoras. É através desta controladora que informamos se estamos lidando com o modo gráfico ou alfanumérico, por exemplo.

Cada uma dessas controladoras é programada através de um par de potas de I/O: Uma que indica um registrador e outra onde um dado pode ser lido ou escrito.A única controladora que foge um pouco a esse padrão é a Attribute Controller, onde a mesma porta é usada para informar um registrador e, logo em seguida, estará disponível para escrita. Há uma outra porta diferente para leitura.

Existe um quinto circuito, essencial, chamado RAM DAC. Já falei sobre os DACs aqui antes, mas esse é diferente… Ele não só converte o nível de tensão na saída de vídeo, mas as fases do sinal de crominância de cada PEL. Claro, que isso só é feito no caso de saídas em vídeo composto (aquelas saídas RCA, quando há). Os sinais de sincronismo e R,G e B são separados no conector VGA, o que torna tudo um pouco mais simples.

Registradores não associados à controladoras:

O padrão VGA oferece 4 registradores para controle e obtenção de status genérico. O registrador Miscelaneous Output ligado à porta 0x3CC (leitura) e 0x3C2 (escrita) controla o sinal dos pulsos de sincronismo, seleciona o dot clock, habilita a decodificação dos endereços do frame buffer e se estamos trabalhando no modo monocromático ou colorido. Este é o primeiro e principal registrador genérico da VGA.

É bom notar que a porta 0x3C2 pode ser lida, mas neste caso ela fornece o conteúdo do registrador Input Status 0. Cujo único bit significativo é o 7, que indica se a placa está efetuando um retraço vertical ou não. Esse bit é bem útil, porque é mais interessante atualizar o frame buffer durante um retraço vertical por dois motivos:

  1. O circuito da placa de vídeo não vai colocar wait states no barramento para não competir com a tentativa de escrita do processador, durante um rertaço vertical;
  2. O retraço vertical é a etapa de sincronismo mais longa do que os retraços horizontais!

Fazer isso evita o efeito de flickering

Os outros registradores genéricos são reservados e não devem ser tocados (a não ser pela BIOS!).

CRTC e a temporização do sinal:

A controladora CRTC é a mais complicada das quatro e têm 25 registradores que precisam ser programados corretamente para a temporização certeira do sinal de vídeo. Estranhamente, não é apenas o sinal de vídeo que deve ser corretamente temporizado, mas também os intervalos usados para a geração de um “cursor”… O diagrama abaixo mostra um resumo do modelo usado pela controladora em relação aos sinais de temporização:

Temporização VGA
Temporização VGA

Todos dos ajustes horizontais são medidos em termos de caracteres, não em PELs. Em certos modos de vídeo um caracter é definido como tendo 8 PELs na horizontal, em outros, 9. Suspeito que a escolha por medir “por caracter” tenha sido feita dessa maneira para evitar o uso de muitos bits em cada um dos registradores. Repare, por exemplo, que o registrador Horizontal Total contém a quantidade de caracteres na linha, incluindo o tempo do retraço horizontal menos 5.

Os ajustes verticais são mais simples. São medidos em scanlines (ou, simplesmente, linhas). Em teoria, poderíamos ter resoluções de até 1024 linhas numa VGA já que esse registrador tem 10 bits de tamanho. Com tantos bits, não é possível usar um registrador só para conter o valor… É o caso, por exemplo, do registrador Vertical Total, que possui 8 bits, mas os dois bits superiores estão no registrador Overflow.

Do ponto de vista de um monitor de vídeo, o CRTC é a controladora mais crítica… Alguns velhos monitores CRT sobreaquecem se as frequências horizontal e vertical excederem certos valores e já vi casos de monitores pegando fogo, literalmente… Algumas placas de vídeo antigas também sofriam desse mal: Algum chip sobreaquecia e “puf”… Felizmente isso não acontece mais…

Sequencer:

O sequenciador controla a sequência de eventos (óbvio!), mantendo, inclusive, contagens para geração de caracteres e para divisão do dot clock (no caso de resoluções menores). Ele têm apenas 5 registradores.

O primeiro deles é importante quando estamos programando um novo modo de vídeo. Trata-se do registrador de reset do Sequencer. É importante que façamos um reset síncrono, o que zerará os contadores do sequenciador e o colocará num estado de “parado”.

Outro registrador do sequenciador importante é o Clocking Mode, que altera a semântica do dot clock. O bit 0, por exemplo, diz se estamos usando caracteres de 8 ou 9 pontos na horizontal (o que afeta os ajustes no CRTC).

Aqui também habilitamos ou não os “planos” da memória de vídeo usadas no novo modo de vídeo. Alguns modos usam um conjunto limitado de “planos”, outros usam todos eles… Como saber quais mapas devem ser usados? Existe outro registrador do sequenciador para isso: O Memory Mode…

Depois que as outras controladoras forem programadas podemos zerar o bit de reset e o sequenciador recomeçará a seguir o seu curso.

Attributes Controller:

A maioria dos registradores da controladora de atributos lida com cores. Os 16 primeiros registradores são índices para o mapa de cores das 16 cores iniciais (a maioria dos modos coloridos de vídeo da VGA são de 16 cores). Os demais lidam com a geração de cores… são apenas 5 registradores.

Graphics Controller:

O ajuste do modo de vídeo e a manipulação da memória do frame buffer versus memória de vídeo são feitas aqui. Temos apenas 9 registradores. Aqui podemos, além de outras coisas, selecionar quais “planos” serão alterados ou lidos, selecionar quais bits dos bytes desses planos serão alterados ou lidos, etc… Quando você pensa em lidar com a memória de vídeo (seja o frame buffer, seja a memória interna, pensa nessa controladora!).

O que são o Frame Buffer e memória de vídeo

Se você já mexeu com a “memória de vídeo”, gosta de pensar nela, em modo real, como localizada no endereço lógico 0xA000:0x0000 (no modo 320x200x256) ou 0xB800:0x0000 (no modo texto, colorido, de 80×25). No entanto, essa não é a memória de vídeo. Isso é o frame buffer.

A memória de vídeo encontra-se dentro da placa de vídeo e é acessada através do frame buffer. O padrão VGA possui 4 blocos de 64 KiB chamados “planos”, numerados de 0 a 3. No caso do modo de vídeo, texto, 80×25, três planos estão habilitados: O plano 0 contém os caracteres a serem desenhados na tela, o plano 1, os atributos de cada um desses caracteres e o plano 2 contém os bitmaps das fontes usadas no desenho. Todos os planos começam no endereço zero e, assim, nos planos 0 e 1, o endereço zero contém, respectivamente, o caracter no canto superior direito e seu atributo.

No frame buffer, acessível pelo processador, os planos 0 e 1 são mapeados de forma intercalada (num modo conhecido como Odd/Even ou, Par/Ímpar). Onde os endereços pares são mapeados para o plano 0 e os ímpares para o plano 1… No modo 80×25, o plano 2 não é acessível pelo frame buffer diretamente. Ele é preenchido pela BIOS antes do ajuste do modo para que o circuito da placa saiba como desenhar os caracteres.

Nos atributos de um caracter, o bit 3 é, normalmente, usado como “intensidade” da cor de frente, mas o controlador de atributos pode ser reprogramado para interpretá-lo como “mapa do bitmap da fonte”, do plano 2 (neste artigo mostro como obter o bitmap usado pela BIOS). Isso permite que, em modo texto, possamos embelezar um bocado nossas aplicações, como é o que acontece com o Norton Utilities 6, para MS-DOS:

Norton Utilities Control Center
Norton Utilities Control Center

Acredite, a tela acima está totalmente em modo texto! O que o utilitário fez foi criar alguns caracteres especiais no segundo bitmap disponível para o padrão VGA para “fazer de conta” que encontra-se num modo gráfico. Embora o modo texto seja evidente, o efeito final (com o botão de menu de janela e as bordas branquinhas) fica bem interessante.

Em outros modos, o mapeamento dos planos de vídeo em relação ao frame buffer é mais complicado. Num modo 640×480 de 16 cores, os 4 planos são mapeados para o frame buffer, um por vez. Cada byte do frame buffer é mapeado diretamente para 8 PELs, um bit por vez. Se cada plano possui um bit de um pixel, então cada bit de cada plano forma um PEL. Num único PEL o bit 0 estará no plano 0, o bit 1, no plano 1 e assim por diante.

Esse esquema planar permite que um modo de 640×480 com 16 cores, que ocuparia 150 KiB (640\cdot480\cdot\frac{1}{2} = 153600 PELs). Agora ocupa 38400 bytes por plano (\frac{640\cdot480}{8}=38400). Como o frame buffer é limitado a 128 KiB (de 0xA0000 até 0xBFFFF), esse esquema funciona muito bem, mesmo que seja complicado.

SuperVGAs

O “Super” de SuperVGAs tem a ver com a resolução máxima suportada pela placa de vídeo, bem como a quantidade máxima de cores dessas grandes resoluções. O padrão é derivado do XGA, da IBM, mas foi proposto pela VESA (Video Electronics Standard Association)… A VESA surgiu em 1988 por iniciativa da empresa japonesa NEC (Nippon Electric Company) que propôs a associação justamente para a criação do substituto para o padrão VGA.

Em 1991 surge a SuperVGA. Infelizmente, já que mais de 200 empresas participaram do grupo, hoje temos uma miríade de implementações que torna impossível chamar SuperVGA de “padrão”…

Em essência, o que o SuperVGA faz é estender alguns registradores dos controladores da VGA (para suportar mais cores e mais resolução gráfica) e implementar um esquema de “janelas” no uso do frame buffer para acesso à memória de vídeo. Por que? Ora, uma resolução gráfica de 800×600 com 65536 cores exige 2 bytes por cor e, portanto, o total de memória necessária para armazenar isso tudo é de quase 1 MiB! Lembre-se que o nosso frame buffer tem, no máximo, 128 KiB… Assim, a SuperVGA quebra a tela em janelas ou “faixas”.  No caso dessa resolução (800×600 com 64 Kcores), é provável que a tela seja dividida em 15 faixas de 40 linhas… Assim, se cada linha tem 1600 bytes de tamanho (800\cdot2), então 40 linhas ocuparão, aproximadamente, 64 KiB que, além de caber totalmente dentro da faixa do limite de 128 KiB imposta pelo frame buffer, permite até o uso de duas “páginas”!

Sempre que tivermos que desenhar um pixel dentro de uma faixa, pedimos a placa para trocar o mapeamento da “janela” no frame buffer e lidamos com a nova faixa. Dá um baixa trabalho, mas com o surgimento dos PCs de arquitetura de 32 bits (386) e com mais memória RAM, o padrão VESA evoluiu e permitiu a alocação de frame buffers fora da região do padrão VGA. A especificação da arquietura AGP (Advanced Graphics Port), por exemplo, sugere uma “abertura” de 1 MiB acima do limite de 15 MiB de RAM, didicada ao linear frame buffer. No exemplo acima, 800×600 com 64 Kcores,

Aceleradores 2D

A IBM, é claro, retrucou… Surge o acelerador gráfico 8514/A (datasheet aqui — mas, não se anime, ele é obsoleto!). Além de suportar o “padrão” SuperVGA ele oferece recursos de cópia de blocos diretamente da memória de vídeo (note bem, não do frame buffer!), chamado de bit block tranfer (BitBlt — se você já viu a GDI do Windows, já deve ter se perguntado muito o que essa “palavra” esquisita significa, huh?), a capacidade de preencher áreas por hardware e a de desenhar linhas do mesmo modo…BitBlt oferece o recurso primitivo de texture mapping, mas apenas de blocos retangulares alinhados com os eixos. Ao invés de “texturas” eles recebem o nome de sprites.

A partir dai, já que a padronização “virou bagunça”, começaram a surgir um monte de aceleradoras… Algumas empresas já existiam como a ATI, mas apareceram muitas outras: ALi, Trident, Matrox, Cirrus Logic, Chips & Tech, S3, SiS, Tseng etc etc…Cada uma com suas aceleradoras próprias e conjuntos de registradores diferentes.

O único material que encontrei sobre os diversos registradores de fabricantes diferentes está contido numa série de documentos texto, antigos, de 1995 (baixe-os aqui se estiver curioso).

GPUs

Claro que, hoje, a tendência é a substituição de todo o recurso gráfico compatível com a VGA pelas GPUs… Especialmente porque todos os recurso de aceleração 2D podem ser substituídos por shaders, se necessário. Ainda, texture mapping é real aqui, usar sprites é um caso especial. E, por fim, as GPUs modernas têm centenas (senão milhares) de “núcleos” de execução individuais…

Mas, é claro, são complicadas pra caramba de usar se você é um desenvolvedor de sistemas operacionais. Os fabricantes não costumam divulgar informações detalhadas (se é que divulgam alguma!) com explicações coerentes sobre os registradores e seus usos. Pelo menos a nVidia não o faz (e ganhou um merecido “fuck you!” de Linus Torvalds por isso!), mas a AMD (atual dona da ATI) e Intel divulgam, mesmo que pareça material para magia negra!

E ainda tem o problema que são daughter boards, ou seja, placas que são espetadas na placa mãe… Ou seja, a BIOS não tem como prever o que elas têm, por dentro. Enquanto isso, o padrão VGA estará conosco por muito tempo ainda…

O que eu espero que você entenda deste texto

Ora… claramente eu só fiz um overview sobre o funcionamento de uma placa de vídeo VGA e falei menos ainda sobre as SuperVGAs. O importante é que você saiba que nenhum recurso dessas placas existe à toa.

Alguns destaques para o começo de suas pesquisas já foram dados:

  • Em linhas gerais, a função de cada controladora;
  • Como a CRTC tem que ser manipulada;
  • Detalhes mínimos sobre o Sequencer;

O restante é mais simples (baixe a documentação e estude)…

Ahhhh… sim… um detalhe: É importante que, ao lidar com a placa VGA diretamente, as interrupções estejam desabilitadas!

Anúncios