2012-06-26 12 views
14

Nella mia applicazione sto usando estensivamente glTexImage2D. Copio un'immagine di un'immagine e la renderò come una texture, lo faccio spesso ad ogni clic del mouse. Lo do come array di byte per il rendering. La memoria viene mangiata e viene anche assegnata la memoria di scambio. È una perdita di memoria? o è dovuto al fatto che glTexImage2D contiene qualsiasi riferimento o qualsiasi altra cosa.come gestire la memoria con texture in opengl?

Edit:

//I allocate the memory once 
    GLuint texName; 
    texture_data = new GLubyte[width*height]; 

    // Each time user click I repeat the following code (this code in in callback) 
    // Before this code the texture_data is modified to reflect the changes 
    glGenTextures(3, &texname); 
    glBindTexture(GL_TEXTURE_2D, texname); 
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); 
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); 
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE,texture_data); 

Spero che il vostro vicino richieste e giù per la votazione si fermava ora!

+2

Il codice effettivo sarebbe utile per rintracciare questo problema. –

+0

@NicolBolas, ho inserito il codice, grazie per aver menzionato +1 – Shan

risposta

40

Supponendo che si stia generando una nuova trama con glGenTextures ogni volta che si chiama glTexImage2D, si spreca memoria e si perde se non si tiene traccia di tutte le trame generate. glTexImage2D acquisisce i dati di input e li archivia nella memoria della scheda video. Il nome della trama che si lega prima di chiamare glTexImage2D - quello che si genera con glGenTextures è un handle per quel blocco di memoria della scheda video.

Se la trama è grande e si sta allocando nuova memoria per archiviare più e più copie di esso ogni volta che la si utilizza, si esaurirà rapidamente la memoria. La soluzione è chiamare glTexImage2D una volta durante l'inizializzazione dell'applicazione e chiamare solo glBindTexture quando si desidera utilizzarlo. Se si desidera modificare la trama stessa quando si fa clic, chiamare solo glBindTexture e glTexImage2D. Se la tua nuova immagine ha le stesse dimensioni dell'immagine precedente, puoi chiamare glTexSubImage2D per dire a OpenGL di sovrascrivere i vecchi dati dell'immagine invece di eliminarli e caricarne uno nuovo.

UPDATE

In risposta al nuovo codice, sto aggiornando la mia risposta con una risposta più specifica. Hai a che fare con trame OpenGL in modo completamente sbagliato L'output di glGenTextures è un GLuint[] e non un String o char[]. Per ogni trama generata con glGenTextures, OpenGL restituisce un handle (come un numero intero senza segno) a una trama. Questo handle memorizza lo stato che gli viene dato con glTexParameteri e un pezzo di memoria sulla scheda grafica se gli dai dati con glTexImage[1/2/3]D. Spetta a te memorizzare l'handle e inviarlo nuovi dati quando si desidera aggiornarlo. Se si sovrascrive l'handle o si dimentica, i dati rimangono nella scheda grafica ma non è possibile accedervi. Sei anche dicendo OpenGL per generare 3 texture quando hai solo bisogno 1.

Visto che texture_data è di una dimensione fissa, è possibile aggiornare la texture con glTexSubImage2D invece di glTexImage2D. Qui è il codice modificato per evitare la perdita di memoria da questo problema:

texture_data = new GLubyte[width*height](); 
GLuint texname; //handle to a texture 
glGenTextures(1, &texname); //Gen a new texture and store the handle in texname 

//These settings stick with the texture that's bound. You only need to set them 
//once. 
glBindTexture(GL_TEXTURE_2D, texname); 
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); 
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); 
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 

//allocate memory on the graphics card for the texture. It's fine if 
//texture_data doesn't have any data in it, the texture will just appear black 
//until you update it. 
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, 
    GL_UNSIGNED_BYTE, texture_data); 

... 

//bind the texture again when you want to update it. 
glBindTexture(GL_TEXTURE_2D, texname); 
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, 0, GL_RGB, 
    GL_UNSIGNED_BYTE, texture_data); 

... 

//When you're done using the texture, delete it. This will set texname to 0 and 
//delete all of the graphics card memory associated with the texture. If you 
//don't call this method, the texture will stay in graphics card memory until you 
//close the application. 
glDeleteTextures(1, &texname); 
+0

Grazie mille, ho pubblicato il codice, quindi come puoi vedere che uso la stessa memoria basta cambiare il contenuto e fare sempre la stessa cosa. Quindi, secondo il tuo suggerimento nello snippet di codice precedente, devo solo chiamare "glGenTextures" una volta e poi chiamare sempre glBindTexture e glTexImage2D. Eviterà la perdita di memoria. Ho ragione? – Shan

+1

@Shan ha aggiornato la mia risposta con il codice e (si spera) una spiegazione sufficiente in modo da capire dove la perdita proviene dal codice e come risolverla. Usa il manuale OpenGL anche in futuro, è molto utile per spiegare esattamente cosa fanno i metodi OpenGL: http://www.opengl.org/sdk/docs/man/xhtml/glGenTextures.xml –

+0

grazie mille, Ottima risposta!, in realtà ho aggiornato il codice, è stato incasinato, il tipo è GLuint per texname. Solo una query, ho più di una texture, come glTexSubImage2D saprebbe quale sto aggiornando? o è dovuto alla chiamata a glBindTexture. – Shan

Problemi correlati