В настоящее время я пытаюсь получить снимок из 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 остановит свою работу, что будет очень дорого.