Il
test sulla scheda video: quali funzioni sono supportate? |
Una
volta creati ed inizializzati gli oggetti principali della
libreria DirectX8, è altamente consigliabile eseguire
un test preliminare sulle potenzialità della scheda
video per verificarne la risoluzione.
Questo non solamente a scopo di permettere all'utente di modificare
il dettaglio grafico del programma ma anche e soprattutto
per capire se la scheda video utilizzata può supportare
alcuni accorgimenti che richiedono livelli di grafica più
avanzati.
Esiste una semplice gerarchia da ricordare quando si desidera
ottenere le impostazioni grafiche del proprio computer:
1. il numero e la tipologia di schede video disponibili;
2. il tipo di supporto alla scheda video: HAL (Hardware
Abstraction Layer) che non è altro che
un'interfaccia comune tra i molteplici tipi di schede video
presenti sul mercato e lo sviluppatore di un'applicazione
che usi le DirectX. Attraverso tale interfaccia, rappresentata
da un hardware di accelerazione grafica (niente di più
di una scheda acceleratrice 3D) viene infatti isolato il codice
in assembly, e reso in forma di API, in modo da essere utilizzato
comodamente dallo sviluppatore stesso, e REFERENCE
che è invece un driver software.
Come si può ben immaginare l'accelerazione hardware
è molto più peformante di quella software in
quanto ha caratteristiche supplementari rispetto a quest'ultima;
3. il tipo di risoluzione supportata.
Ma ancora prima di cominciare è possibile scaricare
il progetto relativo a questo articolo dal collegamento posto
in fondo alla pagina. Cominciamo col primo passo: la determinazione
del numero delle schede video presenti. E' d'obbligo per questo
tipo di operazione utilizzare il metodo GetAdapterCount
dell'oggetto Direct3D8 che nell'articolo precedente avevamo
chiamato D3D.
Inseriamo questo metodo insieme al resto del codice che vedremo
tra poco all'interno di una sottoprocedura che chiamiamo 'Test_Risoluzione',
così da rendere il listato più comprensibile:
Private
Sub
Test_Risoluzione()
.
.
.
End Sub |
Naturalmente
ci si deve ricordare di richiamare tale sottoprocedura dalla
routine Form_Load e in riferimento al codice che era stato
creato nell'articolo precedente, prima dell'istruzione End
Sub in modo che risulti in questo modo:
Private
Sub
Form_Load()
Inizializza
Test_risoluzione
End Sub |
Adesso
finalmente possiamo ottenere il numero delle schede presenti
sul PC ed il loro nome, visualizzando tali informazioni in
una finestra di messaggio.
Prima di far ciò bisogna dichiarare una variabile della
struttura D3DADAPTER_IDENTIFIER8, struttura composta
dai seguenti membri:
Type
D3DADAPTER_IDENTIFIER8
Description(0 To 511) As
Byte
DeviceId As Long
DeviceIdentifier As DXGUID
Driver(0 To 511) As
Byte
DriverVersionHighPart As Long
DriverVersionLowPart As Long
Revision As Long
SubSysId As Long
VendorId As Long
WHQLLevel As Long
End Type |
Nonostante
questa struttura non sia necessariamente da dichiarare nel
progetto, come tutte le altre viste finora, e quindi possa
sembrare inutile studiarla, è molto utile analizzarne
almeno i membri più utili in modo da comprendere più
velocemente alcuni passaggi che verranno affrontati in seguito.
Vediamo dunque il primo membro Description che non è
altro che una matrice di 511 caratteri che compongono il nome
della scheda video in questione. Come si vedrà in seguito
solitamente sono utilizzati sicuramente un numero inferiore
dei 511 caratteri disponibili.
DeviceId indica invece il tipo di un determinato chip set.
Driver indica il nome del produttore del driver in questione.
DriverVersion, DriverVersionLowPart e DriverVersionHighPart
identificano invece la versione del driver Microsoft Direct3D.
VendorId indica il produttore di un determinato chip
set.
Dim
Info_Scheda As D3DADAPTER_IDENTIFIER8
|
La
seconda variabile da dichiarare è quella di tipo String
che conterrà il testo da visualizzare nella finestra
di messaggio:
Ed
infine si può assegnare ad una seconda variabile denominata
'nSchede' il numero delle schede video presenti attraverso
il già citato metodo GetAdapterCount:
nSchede
= D3D.GetAdapterCount
|
Ora
con un semplice ciclo For...Next è possibile passare
in rassegna tutte le schede presenti (dalla prima che ha indice
0, all'ultima che ha indice nSchede-1) ed attraverso il metodo
GetAdapterIdentifier riferito sempre all'oggetto Direct3D8
ottenerne per ciascuna le caratteristiche rilevanti.
Non chiudiamo ancora il ciclo in quanto per ogni scheda si
dovranno compiere ulteriori operazioni:
For
i = 0 To nSchede - 1
D3D.GetAdapterIdentifier i, 0, Info_Scheda |
Il
metodo GetAdapterIdentifier ha infatti la seguente sintassi:
Direct3D8.GetAdapterIdentifier
Adapter, Flags, Identifier |
dove
il parametro Adapter indica con un numero ordinale
(in base 0, cioè 0 per la prima scheda, 1 per la seconda
e così via fino a nSchede-1 per l'ultima) la scheda
video di cui ottenere le informazioni. Nel caso si voglia
indicare la scheda video primaria è possibile indicare
la costante D3DADAPTER_DEFAULT.
Flags è un parametro tipicamente impostato su
0 (e l'esempio sopra non fa eccezione), mentre Identifier
è una variabile di tipo D3DADAPTER_IDENTIFIER8 alla
quale, al richiamo del metodo, vengono assegnate tutte le
informazioni sulla scheda.
Ed è proprio analizzando tale variabile elencando i
più importanti membri della struttura D3DADAPTER_IDENTIFIER8
che si possono ottenere il nome, il produttore e le altre
caratteristiche. Azzeriamo ad ogni passaggio del ciclo For
il contenuto della stringa di testo per dividere le informazioni
scheda per scheda:
e
con un secondo ciclo otteniamo i caratteri che compongono
il nome. Come già preannunciato il nome è elencato
in una lunga lista di caratteri (511) da convertire attraverso
la funzione Chr$. Non tutti i 511 caratteri sono in realtà
utilizzati (si potrebbe indicarne solo 15 su 511): la maggior
parte di essi sono infatti spazi (" ") ma per evitare
di troncare un nome a metà conviene sempre abbondare.
All'interno di questo ciclo con un procedimento simile recuperiamo
anche le informazioni sul nome del driver della scheda video:
For
ii = 0 To 511
Info = Info & Chr$(Info_Scheda.Description(ii)) Nome_Driver
= Nome_Driver & _ Chr$(Info_Scheda.Driver(ii))
Next ii
|
Adesso
non resta altro che aggiungere le altre informazioni alla
stringa Info indicando altri membri della struttura D3DADAPTER_IDENTIFIER8
come ad esempio VendorId e DeviceId non inseriti
nel ciclo mostrato sopra perchè non sono matrici di
caratteri come si nota dalla dichiarazione della struttura:
Info
= Replace(Info, Chr$(0), " ") & vbCrLf &
"Driver : " & _
Replace(Nome_Driver, Chr$(0), " ") & vbCrLf
& "DeviceId : " & _
Info_Scheda.DeviceId & vbCrLf & "VendorId
: " & Info_Scheda.VendorId
MsgBox Info
Next i |
Notare
l'utilizzo della funzione Replace che elimina gli spazi
vuoti dalla stringa del nome della scheda e del driver per
non ottenere una stringa lunghissima composta dai pochi caratteri
che compongono il nome e per il resto da " ".
Si otterrà così, in base alla propria scheda,
un messaggio del tipo mostrato dalle immagini sottostanti:
Terminata
la prima fase, quella del controllo delle proprietà
della scheda video si può passare alla seconda parte
del test ossia quali dispositivi (in special modo le schede
acceleratrici) sono supportati dalla scheda video.
Per far questo bisogna innanzitutto dichiarare una variabile
'Capacità_Scheda' del tipo D3DCAPS8, una struttura
davvero troppo lunga per essere analizzata all'interno di
questo articolo, ma sicuramente ripresa più avanti.
La dichiarazione della variabile, come il resto del codice
che si vedrà in seguito, può essere comodamente
inserito nella sottoprocedura Test_risoluzione:
Dim
Capacità_Scheda As
D3DCAPS8 |
Attraverso
il metodo GetDeviceCaps dell'oggetto Direct3D8 si andranno
adesso a recuperare le informazioni riguardanti il dispositivo
di supporto ad ogni scheda grafica e per questo sarà
necessario includerlo in un ciclo:
For
n = 0 To nSchede - 1
D3D.GetDeviceCaps n, D3DDEVTYPE_HAL, Capacità_Scheda |
Il
metodo ha infatti la seguente sintassi:
Direct3D8.GetDeviceCaps(Adapter
As Long, DeviceType As
CONST_D3DDEVTYPE, Caps _
As D3DCAPS8)
|
dove
Adapter è la scheda considerata, DeviceType
può essere rappresentato dai seguenti valori costanti:
D3DDEVTYPE_HAL (costante = 1): accelerazione hardware;
D3DDEVTYPE_REF (costante = 2): supporto di DirectX;
D3DDEVTYPE_SW (costante = 3) : accelerazione software
settata per l'utilizzo con le DirectX.
Caps invece è una variabile del tipo D3DCAPS8, una
variabile che verrà riempita con tutte le informazioni
(in base ai membri della struttura indicati) relative al dispositivo.
Ora è necessario introdurre due casi: primo la presenza
solo di accelerazione software (che generalmente è
sempre presente):
If
Err.Number = D3DERR_NOTAVAILABLE Then
MsgBox "Reference Rasterizer (REF)" |
in
questo caso se l'errore individuato è l'assenza dell'oggetto
della ricerca si avrà di conseguenza come minimo la
presenza di un supporto REF. In caso contrario verrà
confermata la presenza di un'accelerazione hardware:
Else
MsgBox "Hardware Acceleration (HAL) e Reference Rasterizer
(REF)"
End If
Next n |
Avviata
l'applicazione, dopo il messaggio relativo alla scheda video,
si dovrebbe ottenere un avviso di questo tipo:
Per
finire si può analizzare il terzo punto di questa discussione:
la risoluzione supportata dalla scheda video. Innanzitutto
bisogna dichiarare una variabile 'Risoluzione' del tipo D3DDISPLAYMODE,
struttura già analizzata nel primo articolo:
Dim
Risoluzione As D3DDISPLAYMODE
|
In
secondo luogo bisogna richiamare il metodo GetAdapterModeCount
per sapere quanti tipi di risoluzione sono supportate dalla
scheda video che si sta considerando. Siccome ancora una volta
consideriamo tutte le schede una per una, includiamo il metodo
in un ciclo For:
For
nn = 0 To nSchede - 1
nRisoluzioni = D3D.GetAdapterModeCount(nn) |
Infatti
il metodo ha la seguente sintassi:
Direct3D8.GetAdapterModeCount(Adapter
As Long) As
Long |
ossia
necessita l'indice della scheda e ritorna un valore che rappresenta
il numero delle risoluzioni supportate. Ora per ciascun tipo
di risoluzione si richiama il metodo EnumAdapterModes dell'oggetto
Direct3D8 allo scopo di elencare i tipi di risoluzione. La
sintassi richiesta è la seguente:
Direct3D8.EnumAdapterModes(Adapter
As Long, Mode As
Long, DisplayMode As
_ D3DDISPLAYMODE)
|
dove
Adapter è il solito indice della scheda video (anche
qui comunque può essere sostituito dalla costante D3DADAPTER_DEFAULT
relativa alla sola schede video primaria), Mode rappresenta
invece la modalità di visualizzazione da individuare
e DisplayMode è la variabile di tipo D3DDISPLAYMODE
alla quale verranno assegnate le informazioni che andremo
tra poco a leggere:
D3D.EnumAdapterModes
nn, nnn, Risoluzione |
dove
nn è l'indice della scheda, nnn è l'indice del
modo di visualizzazione e Risoluzione è la variabile
ancora vuota.
Per la risoluzione si dovrà tenere conto di due dei
quattro membri della struttura D3DDISPLAYMODE ossia Width
ed Height. Se per ogni scheda assegnamo tali valori
ad una variabile di testo che chiameremo 'Res' per poi visualizzarla
in una finestra di messaggio:
Res
= Res & nn & ": " & Risoluzione.Height
& " x " & _
Risoluzione.Width & vbCrLf
Next nnn
Next nn
MsgBox Res |
si
dovrebbe visualizzare un messaggio del tipo:
anche
se in realtà la disposizione della finestra sarà
tutta in verticale ed invece dei numeri progressivi si avrà
una serie di 0 ad mostrare l'indice della scheda.
Come mai compaiono 24 risoluzioni uguali a due a due, ad esempio
la 0 con la 12, la 1 con la 13 e così via?
Semplicemente perchè non si è ancora provveduto
a dividere le risoluzioni nelle due categorie possibili: a
16 bit (con 16,8 milioni di colori) ed a 32 bit (con 65536
colori) per pixel. Per questa ragione ci sarà una risoluzione
200x320 a 16 bit ed una 200x320 a 32 bit, una risoluzione
240x320 a 16 bit ed una 240x320 a 32 bit e così via.
Per capire quali di queste risoluzioni hanno una definizione
a 32 o a 16 bit, è necessario controllare il membro
Format della struttura D3DDISPLAYMODE, accennato solo
brevemente nell'ultimo articolo. Tale membro sta ad indicare
il formato di un'immagine ed è a sua volta una variabile
dell'enumerazione CONST_D3DFORMAT i cui membri rilevanti
sono i seguenti:
D3DFMT_X1R5G5B5
= 24 (&H18) : 16 bit per pixel dove 5 di essi sono riservati
a ciascun colore;
D3DFMT_R5G6B5
= 23 (&H17) : 16 bit per pixel che utilizzano un sistema
di colore del tipo RGB (Red Green Blue);
D3DFMT_X8R8G8B8
= 22 (&H16) : 32 bit per pixel RGB dove 8 di questi sono
riservati a ciascun colore;
D3DFMT_A8R8G8B8
= 21 (&H15) : 32 bit per pixel che compongono un sistema
di colore del tipo ARGB, simile all'RGB ma con un bit
aggiuntivo (Alpha) del valore compreso tra 0 e 1 che
determina la trasparenza dell'immagine.
E' quindi facile comprendere che nel primo e nel secondo caso
si avrà una definizione a 16 bit e negli ultimi due
a 32. Quindi possiamo inserire un bivio nel codice attraverso
l'istruzione If, al posto dell'ultimo blocco di codice appena
visto:
With
Risoluzione
If .Format = D3DFMT_X8R8G8B8
Or .Format = D3DFMT_A8R8G8B8
Then
Res = Res & vbCrLf & .Width & "x"
& .Height & " 32 bit"
End If
If .Format = D3DFMT_X1R5G5B5
Or .Format = D3DFMT_R5G6B5
Then
Res = Res & vbCrLf & .Width & "x"
& .Height & " 16 bit"
End If
End With
Next nnn
Next nn
MsgBox Res |
che
in pratica non è niente di più di una semplice
suddivisione in due sottoinsiemi in base al formato dell'immagine.
La finestra di messaggio dovrebbe quindi visualizzare il seguente
risultato:
Scarica
qui
l'esempio completo per questo articolo
» "Simple
DX8 Framework" (VC++)
di Robert Dunlop
» "Microsoft
DirectX 7 Developer FAQ" gruppo Microsoft
|