QT에서 그래픽스 관련 안드로이드 개발팁
최근에 QT를 기반으로 회사에서
초음파 시스템을 모바일에서 렌더링되도록 옮기는 프로젝트를
side 프로젝트로 하고 있었습니다.
QT가 opengl을 이용해서 app을 개발하기 용이하고
gl을 이용한 rendering 성능도 탁월해서 해당 framework을 이용하여 개발 중 입니다.
QT가 opengl 을이용해서 개발할때 성능이 좋은 이유는
- single rendering context의 활용
- c++ native 개발
로 볼 수 있습니다.
cross platfrom 지원이 지원되지만 당연하지만 deploy시 이슈가 존재합니다.
크게 몇가지 이슈만 적어보겠습니다.
1. opengl es 2.0 context에서 rendering code를 작성해야 합니다.
android용으로 개발하려면 opengl es 2.0 의 api를 사용해서 개발하게 되야되는데,
QOpenGLFunctions 를 상속받으면 됩니다.
opengl es 2.0 은 생각보다 지원되지 않는api들이 많습니다.
대표적으로 VAO가 지원되지 않습니다.
따라서 index buffer를 여러번 bind해서 rendering해야 하는 수고로움이 존재합니다.
그리고 PBO또한 지원되지 않아서,
stream관련된 buffer update가 있다면 DMA를 이용한 이득을 얻을수 없습니다.
2. file stream의 경우 fstream 말고 QFile 같은 QT Class를 사용해야 합니다.
android에서 qt resource path를 인식하려면 QFile 을 이용해야 합니다.
fstream의 경우 INVALID_PATH error를 발생시킵니다.
3. android를 위한 전처리 코드 작업이 필요합니다.
QOpenGLFunctions 상속시 android와 desktop 에서 작업할 때 미묘하게 인자 값 사양이 다를 경우가 존재하여 전처리 코드가 필요한 경우가 있습니다.
그리고 android에서 디버깅을 위해서는 다음과 같은 코드를 집어 넣어서 qDebug 에 있는 stream을 hooking 하여 android log로 보낼 수 있습니다.
void myMessageHandler(
QtMsgType type,
const QMessageLogContext& context,
const QString& msg
) {
QString report=msg;
if (context.file && !QString(context.file).isEmpty()) {
report+=" in file ";
report+=QString(context.file);
report+=" line ";
report+=QString::number(context.line);
}
if (context.function && !QString(context.function).isEmpty()) {
report+=+" function ";
report+=QString(context.function);
}
const char*const local=report.toLocal8Bit().constData();
switch (type) {
case QtDebugMsg:
__android_log_write(ANDROID_LOG_DEBUG,applicationName,local);
break;
case QtInfoMsg:
__android_log_write(ANDROID_LOG_INFO,applicationName,local);
break;
case QtWarningMsg:
__android_log_write(ANDROID_LOG_WARN,applicationName,local);
break;
case QtCriticalMsg:
__android_log_write(ANDROID_LOG_ERROR,applicationName,local);
break;
case QtFatalMsg:
default:
__android_log_write(ANDROID_LOG_FATAL,applicationName,local);
abort();
}
}
...
int main(int argc, char *argv[])
{
...
qInstallMessageHandler(myMessageHandler);
...
}