2011-01-07 21 views
17

Ho passato un po 'di tempo a esaminare le funzionalità di accelerazione hardware di Java e sono ancora un po' confuso poiché nessuno dei siti che ho trovato online ha risposto direttamente e chiaramente ad alcune delle domande che ho. Quindi ecco le domande che ho per l'accelerazione hardware in Java:Accelerazione hardware Java

1) In Eclipse versione 3.6.0, con l'aggiornamento Java più recente per Mac OS X (1.6u10 penso), l'accelerazione hardware è abilitata di default? Ho letto da qualche parte che

someCanvas.getGraphicsConfiguration().getBufferCapabilities().isPageFlipping() 

si suppone per dare un'indicazione di se o non l'accelerazione hardware è attivata, e miei rapporti di programma indietro vero quando questo viene eseguito sul mio esempio Tela principale per disegnare a. Se la mia accelerazione hardware non è abilitata ora, o per impostazione predefinita, cosa dovrei fare per abilitarlo?

2) Ho visto un paio di articoli qua e là sulla differenza tra un BufferedImage e VolatileImage, dicendo principalmente che VolatileImage è l'immagine accelerata dall'hardware e viene memorizzata in VRAM per operazioni di copia-da veloce. Tuttavia, ho anche trovato alcuni casi in cui si dice che BufferedImage sia anch'esso accelerato dall'hardware. L'hardware BufferedImage è accelerato anche nel mio ambiente? Quale sarebbe il vantaggio dell'utilizzo di VolatileImage se entrambi i tipi sono hardware accelerati? Il mio principale presupposto per il vantaggio di avere un VolatileImage nel caso in cui entrambi abbiano accelerazione è che VolatileImage è in grado di rilevare quando la sua VRAM è stata scaricata. Ma se BufferedImage supporta ora anche l'accelerazione, non avrebbe lo stesso tipo di rilevamento integrato, appena nascosto dall'utente, nel caso in cui la memoria venga scaricata?

3) C'è qualche vantaggio di utilizzare

someGraphicsConfiguration.getCompatibleImage/getCompatibleVolatileImage() 

al contrario di

ImageIO.read() 

In un tutorial ho letto per alcuni concetti generali sulla configurazione della finestra di rendering correttamente (tutorial) usa il metodo getCompatibleImage, che credo restituisca una BufferedImage, per ottenere le immagini "accelerate dall'hardware" per il disegno veloce, che si lega alla domanda 2 se è accelerata dall'hardware.

4) Questa è una minore accelerazione hardware, ma è qualcosa di cui sono stato curioso: devo ordinare quali elementi grafici vengono disegnati? So che quando si usa OpenGL tramite C/C++ è meglio assicurarsi che lo stesso grafico sia disegnato in tutti i punti in cui deve essere disegnato contemporaneamente per ridurre il numero di volte che la trama corrente deve essere cambiata. Da quello che ho letto, sembra che Java si prenderà cura di questo per me e si assicurerà che le cose vengano disegnate nel modo migliore, ma, ancora una volta, nulla ha mai detto chiaramente nulla del genere.

5) Quali classi AWT/Swing supportano l'accelerazione hardware e quali dovrebbero essere utilizzate? Attualmente sto usando una classe che estende JFrame per creare una finestra e aggiungendo una tela ad essa da cui creo una BufferStrategy. Questa è una buona pratica o c'è qualche altro modo in cui dovrei implementarla?

Grazie mille per il vostro tempo e spero di aver fornito chiare domande e informazioni sufficienti per rispondere alle mie numerose domande.

risposta

16

1) L'accelerazione hardware non è mai stata abilitata per impostazione predefinita e, a mia conoscenza, non è ancora stata modificata. Per attivare l'accelerazione del rendering passare questo arg (-Dsun.java2d.opengl = true) all'avvio del programma Java all'avvio del programma o impostarlo prima di utilizzare qualsiasi libreria di rendering. System.setProperty("sun.java2d.opengl", "true"); È un parametro facoltativo.

2) Sì BufferedImage incapsula alcuni dei dettagli della gestione memoria volatile perché, quando il BufferdImage viene accelerata una copia di esso è memorizzato in V-Ram come VolatileImage.

Il vantaggio di un BufferedImage è finchè non si scherzi con i pixel in esso contenuti, semplicemente copiandole come una chiamata a graphics.drawImage(), poi il BufferedImage sarà accelerato dopo un certo numero non specificato di copie e sarà gestire il VolatileImage per te.

L'aspetto negativo di un BufferedImage è se si sta facendo l'editing di immagini, cambiando i pixel nella BufferedImage, in alcuni casi si darà al tentativo di accelerarlo, a quel punto, se siete alla ricerca di resa performante per l'editing voi è necessario prendere in considerazione la gestione del proprio VolatileImage. Non so quali operazioni fanno sì che BufferedImage si arrenda nel tentativo di accelerare il rendering per te.

3) Il vantaggio di usare il createCompatibleImage()/createCompatibleVolatileImage() è che ImageIO.read() non fa alcuna conversione a un'immagine di modello dei dati di default supportato. Quindi, se si importa un PNG, lo rappresenterà nel formato creato dal lettore PNG. Ciò significa che ogni volta che viene reso da un GraphicsDevice deve prima essere convertito in un modello di dati immagine compatibile.

BufferedImage image = ImageIO.read (url); 
BufferedImage convertedImage = null; 
GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment(); 
GraphicsDevice gd = ge.getDefaultScreenDevice(); 
GraphicsConfiguration gc = gd.getDefaultConfiguration(); 
convertedImage = gc.createCompatibleImage (image.getWidth(), 
              image.getHeight(), 
              image.getTransparency()); 
Graphics2D g2d = convertedImage.createGraphics(); 
g2d.drawImage (image, 0, 0, image.getWidth(), image.getHeight(), null); 
g2d.dispose() 

Il processo di cui sopra permette di convertire un'immagine letto in con l'immagine io api ad un BufferedImage che ha un modello di dati immagine compatibile con il dispositivo dello schermo di default in modo che la conversione non ha bisogno di avere luogo, quando mai si è reso . I momenti in cui questo è più vantaggioso è quando si renderà l'immagine molto frequentemente.

4) Non è necessario eseguire uno sforzo per il rendering delle immagini in modo batch, poiché per la maggior parte Java tenterà di eseguire questa operazione automaticamente. Non c'è motivo per cui non puoi tentare di farlo, ma in generale è meglio profilare le tue applicazioni e confermare che c'è un collo di bottiglia nel codice di rendering dell'immagine prima di tentare di eseguire un'ottimizzazione delle prestazioni come questa. Il principale svantaggio è che è implementato in modo leggermente diverso in ogni JVM e quindi i miglioramenti potrebbero essere inutili.

5) Per quanto ne so, il design che è stato delineato è una delle migliori strategie disponibili quando si esegue il doppio buffering manualmente e si esegue attivamente il rendering di un'applicazione. http://docs.oracle.com/javase/7/docs/api/java/awt/image/BufferStrategy.html A questo link troverete una descrizione dello BufferStrategy.Nella descrizione mostra uno snippet di codice che è il modo consigliato di eseguire il rendering attivo con un oggetto BufferStrategy. Io uso questa particolare tecnica per il mio codice di rendering attivo. L'unica grande differenza è nel mio codice. come te, ho creato il BufferStrategy su un'istanza di Canvas che ho messo su un JFrame.

+0

C'è qualche ragione particolare per cui la maggior parte/tutti gli esempi usano una JFrame per memorizzare la tela? Da quello che ho capito, Swing è piuttosto terribile. Perché non dovresti usare una cornice? Ho un codice che fa proprio questo, e sembra che non sia più difficile creare un JFrame. Inoltre, come viene abilitata l'accelerazione hardware se non è predefinita? – Freezerburn

+0

@FreezerBurn Non so perché molti esempi usano JFrame vs Frame. Immagino che sia fatto con un JFrame perché è quello che è più comunemente conosciuto. Questa è solo una speculazione ma, direi che il rendering manuale in Java con solo un contenitore di primo livello (JFrame, Frame, ecc.) E una tela, c'è poca differenza tra quale si sceglie. Per attivare l'accelerazione del rendering passare questo arg (-Dsun.java2d.opengl = true) all'avvio del programma Java all'avvio del programma o impostarlo prima di utilizzare qualsiasi libreria di rendering. (System.setProperty ("sun.java2d.opengl", "true");) È un parametro facoltativo. – Zixradoom

+0

JFrame è Swing dove Frame/Canvas è AWT. Swing è la nuova libreria di componenti e AWT è la vecchia libreria deprecata. Swing utilizza componenti leggeri dove AWT è componenti nativi. JFrame ha preferito i componenti AWT precedenti. – chubbsondubs

2

A giudicare da alcuni older documentation, è possibile sapere su Sun JVM se l'accelerazione hardware è attiva o meno controllando la proprietà sun.java2d.opengl.

Sfortunatamente, non so se questo si applica a Apple JVM.

È possibile controllare se un individuo è un'immagine con accelerazione hardware utilizzando Image s' getCapabilities(GraphicsConfiguration).isAccelerated()

Detto tutto questo, tutta la documentazione che ho visto (compresi this one) implica che BufferedImage è non accelerazione hardware. Anche Swing è stato modificato per utilizzare lo VolatileImage s per il suo doppio buffering proprio per questo motivo.

+0

Dove trovo la proprietà sun.java2d.opengl? L'ho visto menzionato, ma non ho mai saputo dove controllarlo o metterlo per accertarmi che fosse abilitato su Mac/Eclipse. Inoltre: http://download.oracle.com/javase/1.5.0/docs/guide/2d/new_features.html dice che BufferedImages sono gestiti in 1.5.0 e sono memorizzati nella memoria video. – Freezerburn

+0

Vediamo ... Penso che sia 'System.getProperty (" sun.java2d.opengl ")' per ottenere il valore della proprietà. Per quanto riguarda 'BufferedImage', ha detto che può essere memorizzato nella cache della memoria video, ma non dice nulla sul fatto di manipolarlo al di là di questo. – Powerlord

+0

La stampa dell'output di getProperty mi dà "null" alla console. Da quanto ho capito su come funziona l'accelerazione in Java, BufferedImage potrebbe essere nella memoria video per consentire la copia veloce di VolatileImage? Suppongo che sarebbe il caso se utilizza la copia da video a video. – Freezerburn

Problemi correlati