Tistory View
안드로이드의 최소버전(minSdkVersion)을 기준으로 네이티브 코드는 링크가 된다.[*1], 그러다 보니 이 minSdkVersion을 강제로 올려야 되는 상황이 발생한다. 만들고 있는 앱을 지원하지 않는 기능을 제외하고는 낮은 버전에서도 돌리고 싶은 데, 이 minSdkVersion값을 올려버리면 아예 지원하는 기기가 달라지기에 문제가 아닐 수 없다.
어쩔 수 없이 다른 방법을 사용해야 하는 데, 기기에 깔린 libGLESv3.so 파일을 읽어드려서 필요한 함수포인터를 알아 낼 수가 있다.
dlOpen을 이용하기
dlOpen함수를 사용하여 dlsym을 통하여 함수의 포인터를 구할 수도 있지만, 이 또한 문제가 발생할 수 있는 데, 기기의 제조사가 OpenGL ES 3.x용 libGLESv3.so파일을 만드는 과정에서 제조사에 따른 또다른 파일도 존재할 수도 있다.
문제가 없을 수도 있다. libGLESv3.so파일을 dlopen하면 관련 so파일이 따라 올 수 도 있기에.. 테스트를 안해봐서.. 할 계획도 없지만..
eglGetProcAddress
EGL에서는 이 것을 대신 해주는 eglGetProcAddress함수가 이미 존재한다. 일일이 dlOpen을 할 필요가 없이 바로 이 eglGetProcAddress함수를 통해서 함수의 포인터를 받아 버릴 수 있다. 이 것은 2.0에서도 동일하게 적용되기 때문에, 3.x와 2.0의 GLESv*파일을 따로 따로 dlOpen해서 확인할 필요도 없다. 이 eglGetProcAddress는 확장(Extension) 함수를 불러올 때도 사용할 수 있다.
주의점이 존재하는 데, eglGetProcAdress함수를 통하여 함수의 포인터가 null이 아닌 값이 돌려준다고 해도 이 함수를 제대로 지원한다는 뜻은 아니다. 꼭 GL_VERSION이나 GL_EXTENSION이나 EGL_EXTENSIONS에 있는지 확인해야만 한다. 실제로 확인하지 않고, 함수를 호출해보면, "지원하지 않는다"는 식의 Log를 출력하기도 한다(그나마 안 죽으면 다행이다)
예제
glMapBufferRange함수는 3.0이상에서 지원한다. 2.0에서는 존재하지 않는다.[*2],
이 함수는 3.0이상에서 지원하기 때문에 일단 현재의 OpenGL ES 버전이 3.0이상인지를 확인 해야 한다.
확인 후 3.0이상이면 이 glMapBufferRange함수를 사용하고, 이하인 경우 다른 방식으로 처리하는 코드로 작성하면 된다.
// 필요한 함수의 형태를 정의
typedef void* (*func_glMapBufferRange)(GLenum, GLintptr, GLsizeiptr, GLbitfield);
// 함수의 포인터를 저장
static func_glMapBufferRange f_glMapBufferRange = nullptr;
// GL ES 버전을 가지고 오는 함수..
static bool GetGLVersion( GLint* major, GLint* minor ) {
bool rc = false;
const char *version = (const char*)glGetString( GL_VERSION );
char szOpenGL[128];
char szES[128];
int majorV, minorV;
assert( version );
// sscanf쓰면 안되지만 귀찮아서 그냥 쓰겠다.
// 대소문자 문제가 있을 수 있는 데, 그 정도는 알아서..
if( 4 == sscanf( version, "%s %s %d.%d", szOpenGL, szES, &majorV, &minorV ) ) {
if( 0 == strcmp( szOpenGL, "OpenGL" ) && 0 == strcmp( szES, "ES" ) ) {
*major = majorV;
*minor = minorV;
rc = true;
}
}
return rc;
}
void 초기화() {
GLint glMajorVer, glMinorVer;
if( !GetGLVersion( &glMajorVer, &glMinorVer ) ) {
LOGE( TAG, "GLGetVersion Failure" );
return false;
}
// 3.0 이상인지를 확인 후 함수의 포인터를 땡겨 온다.
if( glMajorVer >= 3 ) {
f_glMapBufferRange = (func_glMapBufferRange) eglGetProcAddress("glMapBufferRange");
LOGD( TAG, "f_glMapBufferRange = %p", f_glMapBufferRange );
}
}
void 사용하는_함수() {
if( f_glMapBufferRange ) {
f_glMapBufferRange( GL_ARRAY_BUFFER, 0, 1024, GL_MAP_READ_BIT );
} else {
// extension을 사용하거나 다른 방식(fbo로 바인딩후 glReadPixels..)
LOGD( TAG, "glMapBufferRange Not support" );
}
}
위와 같은 방식으로 필요한 함수를 다 가져와서 사용하면 된다.
여기서 주의할 사항이 있는 데, 버전을 체크하는 코드를 정확히 잘 만들어야 한다.
예를 들어, 3.11[*3]버전에서 지원하고 3.2[*3]버전은 지원하지 않는다면, 이 상황에서 만약에 float으로 가져와 버전을 비교한다면 높은 버전과 낮은 버전이 뒤집할 수 있다. (3.11이 3.2보다 버전이 높은 것이다!)
또다른 예는 위의 코드처럼 int로 major와 minor를 구분해서 가지고 온 상황에서, 3.11이상에서 지원한다는 코드를 작성하려면 다음과 같이 작성해야 한다.
// 4이상이거나 3.11이상인 조건
if( major > 3 || (major == 3 && minor >= 11 ) ) {
// 그래 지원 한다. 함수 포인터를 땡겨 온다.
}
define 처리하기
include하지 않고, #define 값들을 사용하려면 다음과 같이 필요한 곳이 값들을 찾아서 일일이 넣어주어야 한다.
#ifndef GL_MAP_READ_BIT
#define GL_MAP_READ_BIT 0x0001
#endif
특히 2.0[GLESv2]과 링크하고 <GLES3/gl3.h>하지 않을 경우 좀 유용하다. 필자는 귀찮아서 그냥 <GLES3/gl3.h>를 inlcude해서 쓰기는 한다.
*1 : externalNativeBuild를 이용할 때는 minSdkVersion을 기준으로 된다.
-DANDROID_PLATFORM를 cc에 지정해 버리는 방법이 있기는 하다.
*2 : GL_OES_mapbuffer나 EXT_map_buffer_range확장을 지원한다면 거의 비슷하게 이용할 수 있다.
*3 : 3.11, 4.0버전은 현재 없다. 예를 사용된 것 뿐이다.
'Android Develop > OpenGLES' 카테고리의 다른 글
Android GPU로 계산하기 : ComputeShader #4 Texture다루기 (0) | 2021.07.02 |
---|---|
Android GPU로 계산하기 : ComputeShader #2 컴파일/기본예제 (0) | 2021.06.29 |
Android GPU로 계산하기 : ComputeShader #1 소개 (0) | 2021.06.26 |
OpenGL ES : (Texture or FBO) to (Texture or FBO) 복사 정리 (0) | 2021.06.21 |
Android OpenGL ES : 올바른 Framebuffer 사용법 (2) | 2021.06.21 |
- Total
- Today
- Yesterday
- 예금
- 금리
- Android
- 에어콘
- 에어컨
- 컴퓨트셰이더
- 적금
- 경제보복
- 안드로이드
- 텍스처
- choreographer
- 전기요금
- 애드센스
- 전기세
- 전기료
- 재태크
- ComputeShader
- 재테크
- 컴퓨트쉐이더
- 공유 컨텍스트
- 애드핏
- OpenGL ES
- texture
- TTS
- 티스토리
- 사용료
- gpgpu
- 블로그
- OpenGLes
- 아끼는 법
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | ||||||
2 | 3 | 4 | 5 | 6 | 7 | 8 |
9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 | 17 | 18 | 19 | 20 | 21 | 22 |
23 | 24 | 25 | 26 | 27 | 28 | 29 |
30 | 31 |