Hello,

I am trying to create Qt Vulkan window on Android. I use QWindow as application main window. Without vulkan it works just great. When trying to add vulkan rendering, I encountered the following problem. How to obtain ANativeWindow pointer needed for vkCreateAndroidSurfaceKHR()? QWindow::winId() does seem to return anything useful on android (in fact it always return value 1 in Qt 5.8 I use).

Googling I found some JNI black magic to get ANativeWindow:

Qt Code:
  1. ANativeWindow* awindow = nullptr;
  2. QPlatformNativeInterface *nativeInterface = QApplication::platformNativeInterface();
  3. // the JNI black magic to get ANativeWindow*
  4. jobject activity = (jobject)nativeInterface->nativeResourceForIntegration("QtActivity");
  5. QAndroidJniEnvironment *qjniEnv;
  6. JNIEnv * jniEnv;
  7. JavaVM * jvm = qjniEnv->javaVM();
  8. jvm->GetEnv(reinterpret_cast<void**>(&qjniEnv), JNI_VERSION_1_6);
  9. jvm->AttachCurrentThread(&jniEnv,NULL);
  10. jint r_id_content = QAndroidJniObject::getStaticField<jint>("android/R$id", "content");
  11. QAndroidJniObject view = ((QAndroidJniObject) activity).callObjectMethod("findViewById", "(I)Landroid/view/View;", r_id_content);
  12. if (view.isValid()) {
  13. QAndroidJniObject child1 = view.callObjectMethod("getChildAt", "(I)Landroid/view/View;", 0);
  14. if (child1.isValid()) {
  15. jint cnt = child1.callMethod<jint>("getChildCount");
  16. if (cnt > 0) {
  17. QAndroidJniObject child2 = child1.callObjectMethod("getChildAt", "(I)Landroid/view/View;", 0);
  18. if (child2.isValid()) {
  19. QAndroidJniObject sHolder = child2.callObjectMethod("getHolder","()Landroid/view/SurfaceHolder;");
  20. if (sHolder.isValid()) {
  21. QAndroidJniObject theSurface = sHolder.callObjectMethod("getSurface","()Landroid/view/Surface;");
  22. if (theSurface.isValid()) {
  23. awindow = ANativeWindow_fromSurface(jniEnv, theSurface.object());
  24. qDebug() <<"Got native window " << awindow;
  25. WId wid = winId();
  26. qDebug() << "winid returned " << wid;
  27. }
  28. }
  29. }
  30. }
  31. }
  32. }
  33. if (awindow != nullptr) {
  34. // and now try to create vulkan surface
  35. VkAndroidSurfaceCreateInfoKHR createInfo;
  36. createInfo.sType = VK_STRUCTURE_TYPE_ANDROID_SURFACE_CREATE_INFO_KHR;
  37. createInfo.pNext = nullptr;
  38. createInfo.flags = 0;
  39. createInfo.window = awindow;
  40. VkResult res = vkInstance->vkCreateAndroidSurfaceKHR(&createInfo, NULL, &m_surface);
  41. if (res != VK_SUCCESS) qDebug() << "Could not create Vulkan surface, err: " << res;
  42. else qDebug() << "Vulkan surface creaated!";
  43. }
To copy to clipboard, switch view to plain text mode 

Well, it partially works. When called during application startup, the code does not work, probably because the java views are not created yet (even when called in showEvent()). When called later when application is already running (I called it in keyPressEvent()), it finds the surface and ANativeWindow_fromSurface return something what seems to be sensible pointer. But when passed to vkCreateAndroidSurfaceKHR() I got error.

This is the application output I got:

Qt Code:
  1. D libVkWindow.so: ../VkWindow/vkwindow.cpp:440 (virtual void QVkWindow::keyPressEvent(QKeyEvent*)): Got native window 0x9ebf3808
  2. D libVkWindow.so: ../VkWindow/vkwindow.cpp:442 (virtual void QVkWindow::keyPressEvent(QKeyEvent*)): winid returned 1
  3. E vulkan : native_window_api_connect() failed: Invalid argument (-22)
  4. D libVkWindow.so: ../VkWindow/vkwindow.cpp:456 (virtual void QVkWindow::keyPressEvent(QKeyEvent*)): Could not create Vulkan surface, err: -3
To copy to clipboard, switch view to plain text mode 

I am not sure whether the reason for error is that returned ANativeWindow * is not correct or it is caused by the fact, that I am trying to create vulkan surface for window too late (application already paited into this window in QWindow::exposeEvent()). Anyway I am stuck and do not know how to obtain proper ANativeWindow * in time to initialize vulkan surface.

Does anybody know how it should be done correctly? Some simple example would be just great.

Thanks in advance