Android OpenGL текстуры, загруженные в фоновом потоке, перезаписываются - PullRequest
0 голосов
/ 26 июля 2011

Я загружаю текстуры в фоновом потоке, а затем отправляю растровое изображение в поток GL (через GLSurfaceView.queueEvent (...)), чтобы загрузить его на видеокарту.чтобы предотвратить сборку мусора после каждой загрузки изображения, я повторно использую одно растровое изображение со степенью двух измерений для отправки текстуры для открытия gl.

, и в этом проблема, иногда это растровое изображение перезаписывается, как рабочий поток и поток GLборются друг с другом.насколько я понимаю, невозможно получить блокировку в одном потоке (рабочий) и разблокировать его в другом потоке (GL).поэтому я пришел с таким решением (моя тема - HandlerThread):

public boolean handleMessage(Message msg) {
    switch(msg.what) {
        case MESSAGE_FROM_MAIN_THREAD:
            m_Lock.lock();
            loadTextureFromAssets(msg.obj.toString(), msg.arg1);
            break;

        case MESSAGE_FROM_GL_THREAD:
            m_Lock.unlock();
            break;
    }

    return true;
}

, где m_Lock - ReentrantLock.но это все еще не работает, и иногда текстура повторяется (или частично перезаписывается следующей).похоже, что разблокировки в порядке LIFO ...

есть идеи, кроме создания нового битового массива для каждой загруженной текстуры и создания GC?... это может быть решено почти во всех случаях с двумя битмапами для загрузки текстур и переключения между ними, но это не на 100% правильно.Я хотел бы решить эту проблему с правильной синхронизацией потоков.

1 Ответ

2 голосов
/ 28 июля 2011

итак, через день я понял это. Я использовал Семафор, изначально установленный на 1, и приобрел его до LoadTextureFromAssets(...) и выпустил его в конце Runnable, отправленного в GL для загрузки текстуры:

public boolean handleMessage(Message msg) {
    switch(msg.what) {
        case MESSAGE_FROM_MAIN_THREAD:
            try {
                m_Semaphore.acquire();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            loadTextureFromAssets(msg.obj.toString(), msg.arg1);

            break;

        case MESSAGE_FROM_GL_THREAD:
            // not needed for now
            break;

    }

    return true;
}

и метод загрузки:

// load the image from assests and then...
m_GLSurface.queueEvent(new Runnable() {
        public void run() {
                gl.glBindTexture(GL10.GL_TEXTURE_2D, m_TexId);

                gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_S, GL10.GL_CLAMP_TO_EDGE);
                gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_T, GL10.GL_CLAMP_TO_EDGE);
                gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER, GL10.GL_LINEAR);
                gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER, GL10.GL_NEAREST);

                if (gl instanceof GL11) {
                    // GL 1.1 has auto mip-map generation
                    gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER, GL10.GL_LINEAR_MIPMAP_LINEAR);
                    gl.glTexParameterf(GL11.GL_TEXTURE_2D, GL11.GL_GENERATE_MIPMAP, GL11.GL_TRUE);
                }

                GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, GL10.GL_RGBA, m_TexBitmap, 0);

                m_Semaphore.release();
            }
    });

это 100% правильный путь?

...