ToolRotate - Android 화면 방향 회전의 근원

8012 단어
이 글 은 개원 프로젝트 에 대한 것 이다.http://code.google.com/p/flying-on-android/중 ToolRotate. cpp 의 보충 설명 입 니 다.
이 프로그램 은 안 드 로 이 드 플랫폼 의 OpenGL 라 이브 러 리 에 나타 난 bug 에서 비롯 되 었 습 니 다. 우리 의 보드 화면 해상 도 는 800 * 600 이 고 프로그램 이 세로 화면 상태 일 때 (600 * 800) 화면의 가로줄 에 톱날 이 나타 납 니 다.'설정' 과 같은 목록 이 있 는 프로그램 을 열 때 목록 사이 의 구분자 사이 에 양쪽 보다 아래로 픽 셀 이 잘못 되 어 있 는 것 을 볼 수 있 습 니 다.
 
Layer. cpp 의 mTextures 는 길이 가 2 인 Texture 배열 입 니 다. 두 Texture 의 데 이 터 는 사실 두 개의 Graphic Buffer 로 각각 앞 배경 buffer 를 대표 합 니 다.그 릴 때 OpenGL 을 사용 하여 프론트 데스크 톱 Texture 를 화면 에 렌 더 링 합 니 다.Texture 의 너비 가 각각 600 * 800 이면 화면 에 톱날 이 나타 납 니 다 (이것 은 Layer. cpp 의 onDraw 방법 에서 렌 더 링 할 Texture 의 width / height 값 을 인쇄 하여 확인 할 수 있 습 니 다).다른 사이즈 의 레이 어 는 아직 이 문 제 를 발견 하지 못 했다.예 를 들 어 제 판 위 에 상태 표시 줄 이라는 Layer 의 높이 는 25 이 고 입력 법 은 400 여 이 며 톱날 이 나타 나 지 않 았 습 니 다.
 
Texture 의 width / height 는 두 개의 int 32 일 뿐 입 니 다.t 속성.안에 있 는 Graphic Buffer 데 이 터 는 void * 포인터 일 뿐 픽 셀 데 이 터 를 저장 하 는 메모 리 를 가리 키 고 있 습 니 다.OpenGL 은 width / height 의 지도 에 따라 Graphic Buffer 의 데 이 터 를 화면 에 렌 더 링 한 것 이다.
 
만약 에 하나의 앱 이 중력 방향 에 따라 화면 을 회전한다 면 절 차 는 다음 과 같다. 시스템 은 센서 의 출력 데 이 터 를 계산 하고 회전 이 필요 할 때 Surfaceflinger 층 의 API 를 사용 하여 Surface 를 회전한다. 구체 적 인 방법 은 ToolRotate. cpp 의 소스 코드 를 볼 수 있다.클 라 이언 트 엔 드 의 Surface 는 서버 엔 드 의 Layer 에 대응 하기 때문에 Surface 를 바 꾸 는 방법 은 Layer 에서 mTextures 가 대표 하 는 두 Texture 의 너비 입 니 다.Surface 너비 가 바 뀌 면 이 Surface 위 에 그 려 진 View 트 리 가 알려 집 니 다. Surface 의 새로운 너비 에 따라 onMeasure, onLayout, onDraw 를 다시 시작 합 니 다.
 
2011.7.18
/ framework / base / opengl / libagl 은 opengles 의 기본 소프트 구현 코드 에 속 하고 컴 파일 된 라 이브 러 리 는 libGLES 입 니 다.android. so / framework / base / opengl / libs 디 렉 터 리 아래 세 개의 디 렉 터 리 가 있 습 니 다: GLESCM 과 GLES 2 는 각각 OpenGLES1. x 와 2.0 의 인터페이스 다.EGL 은 OpenGL 을 불 러 올 때 마 운 트 는 설정 에 따라 제조 업 체 의 구현 인지 libagl 의 기본 구현 인지 선택 합 니 다.다음 코드 는 / frameworks / base / opengl / libs / EGL / Loader. cpp 에서 발췌 합 니 다.
Loader::Loader()
{
    char line[256];
    char tag[256];
    FILE* cfg = fopen("/system/lib/egl/egl.cfg", "r");
    if (cfg == NULL) {
        // default config
        LOGD("egl.cfg not found, using default config");
        gConfig.add( entry_t(0, 0, "android") );
    } else {
        while (fgets(line, 256, cfg)) {
            int dpy;
            int impl;
            if (sscanf(line, "%u %u %s", &dpy, &impl, tag) == 3) {
                //LOGD(">>> %u %u %s", dpy, impl, tag);
                gConfig.add( entry_t(dpy, impl, tag) );
            }
        }
        fclose(cfg);
    }
}
설정 파일 / system / lib / egl / egl. cfg 만 수정 하면 시스템 에 OpenGL 라 이브 러 리 를 맞 출 수 있 음 을 알 수 있 습 니 다.
2011.7.19
/ system / lib / egl / egl. cfg 파일 의 내용 은 다음 과 같 습 니 다. 0, 0, android 0, 1, xxx 중 0 은 소프트 가 사용 하 는. so 라 이브 러 리 입 니 다.1. 억지로 사용 하 는. so 라 이브 러 리 를 대표 합 니 다.구체 적 으로 다음 코드 를 참고 할 수 있 습 니 다.
    // get our driver loader
    Loader& loader(Loader::getInstance());
    
    // dynamically load all our EGL implementations for all displays
    // and retrieve the corresponding EGLDisplay
    // if that fails, don't use this driver.
    // TODO: currently we only deal with EGL_DEFAULT_DISPLAY
    egl_connection_t* cnx;
    egl_display_t* d = &gDisplay[0];

    cnx = &gEGLImpl[IMPL_SOFTWARE];
    if (cnx->dso == 0) {
        cnx->hooks[GLESv1_INDEX] = &gHooks[GLESv1_INDEX][IMPL_SOFTWARE];
        cnx->hooks[GLESv2_INDEX] = &gHooks[GLESv2_INDEX][IMPL_SOFTWARE];
        cnx->dso = loader.open(EGL_DEFAULT_DISPLAY, 0, cnx);
        if (cnx->dso) {
            EGLDisplay dpy = cnx->egl.eglGetDisplay(EGL_DEFAULT_DISPLAY);
            LOGE_IF(dpy==EGL_NO_DISPLAY, "No EGLDisplay for software EGL!");
            d->disp[IMPL_SOFTWARE].dpy = dpy; 
            if (dpy == EGL_NO_DISPLAY) {
                loader.close(cnx->dso);
                cnx->dso = NULL;
            }
        }
    }

    cnx = &gEGLImpl[IMPL_HARDWARE];
    if (cnx->dso == 0) {
        char value[PROPERTY_VALUE_MAX];
        property_get("debug.egl.hw", value, "1");
        if (atoi(value) != 0) {
            cnx->hooks[GLESv1_INDEX] = &gHooks[GLESv1_INDEX][IMPL_HARDWARE];
            cnx->hooks[GLESv2_INDEX] = &gHooks[GLESv2_INDEX][IMPL_HARDWARE];
            cnx->dso = loader.open(EGL_DEFAULT_DISPLAY, 1, cnx);
            if (cnx->dso) {
                EGLDisplay dpy = cnx->egl.eglGetDisplay(EGL_DEFAULT_DISPLAY);
                LOGE_IF(dpy==EGL_NO_DISPLAY, "No EGLDisplay for hardware EGL!");
                d->disp[IMPL_HARDWARE].dpy = dpy; 
                if (dpy == EGL_NO_DISPLAY) {
                    loader.close(cnx->dso);
                    cnx->dso = NULL;
                }
            }
        } else {
            LOGD("3D hardware acceleration is disabled");
        }
    }

    if (!gEGLImpl[IMPL_SOFTWARE].dso && !gEGLImpl[IMPL_HARDWARE].dso) {
        return EGL_FALSE;
    }

    return EGL_TRUE;
소프트 구현 라 이브 러 리 와 하드웨어 구현 라 이브 러 리 는 각각 gEGLImpl [IMPL SOFTWARE], gEGLImpl [IMPL HARDWARE] 에 넣 습 니 다.
2011.7.20
. so 라 이브 러 리 를 불 러 오 는 loader. open () 함 수 를 더 깊이 살 펴 보 세 요.이것 은 그것 의 핵심 코드 입 니 다.
        dso = load_driver("GLES", tag, cnx, EGL | GLESv1_CM | GLESv2);
        if (dso) {
            hnd = new driver_t(dso);
        } else {
            // Always load EGL first
            dso = load_driver("EGL", tag, cnx, EGL);
            if (dso) {
                hnd = new driver_t(dso);

                // TODO: make this more automated
                hnd->set( load_driver("GLESv1_CM", tag, cnx, GLESv1_CM), GLESv1_CM );

                hnd->set( load_driver("GLESv2", tag, cnx, GLESv2), GLESv2 );
            }
        }

libGLES 불 러 오기tag. so, 불 러 오 는 데 성공 하지 못 하면 세 개의 라 이브 러 리 를 순서대로 불 러 옵 니 다: libEGLxxx.so,libGLESv1_CM.so,libGLESv2.so。로 딩 라 이브 러 리 는 모두 사용 하 는 loaddriver 함수.이 함 수 는 / system / lib / egl / 디 렉 터 리 에서 불 러 올 라 이브 러 리 를 찾 은 다음 eglnames 와 glnames 두 배열 의 이름 목록 은 라 이브 러 리 에서 해당 함 수 를 검색 하고 검색 한 함수 지침 을 저장 합 니 다.
egl 의 함수 포인터 가 cnc - > egl 에 저 장 됩 니 다.GLESv 1 의 포인터 가 cnc - > hooks [GLESv 1 INDEX] - > gl 에 저 장 됩 니 다.GLESv 2 포인터 가 cnc - > hooks [GLESv 2 INDEX] - > gl 에 저 장 됩 니 다.
재 미 있 는 곳 이 하나 있 는데, 바로 eglnames,gl_names, cnx - > egl, cnx - > hooks [GLESv 1 INDEX] - > gl, cnx - > hooks [GLESv 2 INDEX] - > gl 이 몇 개의 구조 체 에 대한 정의:
#undef GL_ENTRY
#undef EGL_ENTRY
#define GL_ENTRY(_r, _api, ...) #_api,
#define EGL_ENTRY(_r, _api, ...) #_api,

char const * const gl_names[] = {
    #include "entries.in"
    NULL
};

char const * const egl_names[] = {
    #include "egl_entries.in"
    NULL
};

#undef GL_ENTRY
#undef EGL_ENTRY
#undef GL_ENTRY
#undef EGL_ENTRY
#define GL_ENTRY(_r, _api, ...) _r (*_api)(__VA_ARGS__);
#define EGL_ENTRY(_r, _api, ...) _r (*_api)(__VA_ARGS__);

struct egl_t {
    #include "EGL/egl_entries.in"
};

struct gl_hooks_t {
    struct gl_t {
        #include "entries.in"
    } gl;
    struct gl_ext_t {
        __eglMustCastToProperFunctionPointerType extensions[MAX_NUMBER_OF_GL_EXTENSIONS];
    } ext;
};
#undef GL_ENTRY
#undef EGL_ENTRY

먼저 매크로 를 정의 한 다음 함수 이름 을 매크로 형식 으로 파일 에 기록 합 니 다.그리고 코드 에 파일 을 포함 하고 마지막 으로 컴 파일 할 때 펼 칩 니 다.유연성 이 뛰어나다.
libagl 디 렉 터 리 는 OpenGLES 의 기본 소프트 구현 입 니 다.lib/GLES_CM 과 lib / GLES 2 두 디 렉 터 리 는 각각 1. x 와 2.0 의 실현 으로 모두 libagl 안의 실현 을 호출 했다.lib / EGL 디 렉 터 리 에 라 이브 러 리 함수 로 불 러 옵 니 다.만약 에 제 가 ABC 회사 라 고 가정 하면 저 는 libagl 라 이브 러 리 를 사용 하지 않 고 자신의 OpenGLES 를 실현 하여 자신의 하드웨어 가속 화 를 사 용 했 습 니 다.그럼 제 라 이브 러 리 는 libGLESv 1 입 니 다.CM_ABC.so,libGLESv2_ABC. so, 일부 OpenGLES 함수 가 시스템 구현 (소프트 구현) 을 이용 하려 면 설정 파일 을 이렇게 쓰 십시오.
0,0,android
0,1,ABC
내 자신의 실현 을 완전히 이용 하면 이렇게 쓴다.
0,1,ABC

좋은 웹페이지 즐겨찾기