Почему мы должны использовать только снимок GLSurfaceView в методе onDrawFrame? В противном случае будет получено черное пустое изображение

В настоящее время я пытаюсь получить снимок из GLSurfaceView на Android. Мой метод здесь - создать растровое изображение, которое показывает содержимое GLSurfaceView в реальном времени. Фактический алгоритм, который я использую:

Bitmap createBitmapFromView(int x, int y, int width, int height, GL10 gl) throws OutOfMemoryError{
    int buffer[] = new int[width * height];
    int source[] = new int[width * height];

    IntBuffer intBuffer = IntBuffer.wrap(buffer);
    intBuffer.position(0);

    try{
        gl.glReadPixels(x, y, width, height, GL10.GL_RGBA, GL10.GL_UNSIGNED_BYTE, intBuffer);

        int offset1, offset2;
        for(int i = 0; i < height; i++){
            offset1 = i * width;
            offset2 = (height - i - 1) * width;

            for(int j = 0; j < width; j++){
                int texturePixel = buffer[offset1 + j];

                int blue = (texturePixel >> 16) & 0xff;
                int red = (texturePixel << 16) & 0x00ff0000;
                int pixel = (texturePixel & 0xff00ff00) | red | blue;

                source[offset2 + j] = pixel;
            }
        }
    } catch(GLException e){
        return null;
    }

    return Bitmap.createBitmap(source, width, height, Bitmap.Config.ARGB_8888);
}

Однако, что касается использования этого метода, моя первоначальная идея состоит в том, чтобы сделать класс, расширенный от GLSurfaceView, для создания нового экземпляра GL10 для отображения. Сразу после создания поверхности я вызываю эту функцию выше в методе onSurfaceCreated. Затем я обнаружил, что каждый моментальный снимок на данный момент полностью пустой и имеет черный цвет, что похоже на то, что данные изображения никогда не проходят через этот GLSurfaceView.

После нескольких других тестов с разными местами использования алгоритма я случайно обнаружил, что только вы вызываете эту функцию внутри метода onDrawFrame. Поэтому я просто установил логический флаг в рендерере GLSurfaceView, чтобы отмечать, нужен ли нам моментальный снимок в данный момент. Поскольку GLSurfaceView будет продолжать вызывать функцию onDrawFrame для обновления, всякий раз, когда флаг установлен в истинное значение, я делаю снимок и устанавливаю флаг в значение false. Наконец-то это работает.

Таким образом, мой вопрос: почему мы должны вызывать метод только для того, чтобы он работал в «onDrawFrame», а не в любом месте, где можно получить экземпляр GL10? Кто-нибудь знает, в чем разница между разными местами для вызова метода моментального снимка?

Такое поведение связано с тем, как работают GPU и CPU. У графического процессора есть собственная выделенная память, в которой хранится кадровый буфер. Чтобы иметь возможность максимизировать производительность, по умолчанию ЦП не может читать выделенную память графического процессора. Чтение фреймбуфера из CPU приведет к тому, что GPU остановит свою работу, что будет очень дорого.

Zamrony P. Juhara 20.05.2018 23:08

Спасибо! Это действительно полезно.

ScrappyTony 05.06.2018 20:13
2
2
35
0

Другие вопросы по теме