| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193 |
- // Copyright (C) 2009-2021, Panagiotis Christopoulos Charitos and contributors.
- // All rights reserved.
- // Code licensed under the BSD License.
- // http://www.anki3d.org/LICENSE
- #include <AnKi/Core/NativeWindowAndroid.h>
- #include <AnKi/Core/App.h>
- #include <AnKi/Util/Logger.h>
- #include <AnKi/Util/Array.h>
- #include <AnKi/Util/StdTypes.h>
- #include <AnKi/Core/Counters.h>
- namespace anki
- {
- static void loopUntilWindowIsReady(android_app& app)
- {
- while(app.window == nullptr)
- {
- int ident;
- int events;
- android_poll_source* source;
- const U timeoutMs = 5;
- while((ident = ALooper_pollAll(timeoutMs, NULL, &events, (void**)&source)) >= 0)
- {
- if(source != NULL)
- {
- source->process(&app, source);
- }
- }
- }
- }
- void NativeWindowImpl::create(NativeWindowInitInfo& init)
- {
- Array<EGLint, 256> attribs;
- U attr = 0;
- EGLint configsCount;
- EGLint format;
- EGLConfig config;
- ANKI_CORE_LOGI("Creating native window");
- ANKI_ASSERT(gAndroidApp);
- android_app& andApp = *gAndroidApp;
- loopUntilWindowIsReady(andApp);
- // EGL init
- //
- display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
- if(display == EGL_NO_DISPLAY)
- {
- throw ANKI_EXCEPTION("Failed to create display");
- }
- int major, minor;
- if(eglInitialize(display, &major, &minor) == EGL_FALSE)
- {
- throw ANKI_EXCEPTION("Failed to initialize EGL");
- }
- //
- // EGL config
- //
- attribs[attr++] = EGL_SURFACE_TYPE;
- attribs[attr++] = EGL_WINDOW_BIT;
- attribs[attr++] = EGL_RENDERABLE_TYPE;
- attribs[attr++] = EGL_OPENGL_ES2_BIT;
- if(init.samplesCount > 1)
- {
- attribs[attr++] = EGL_SAMPLES;
- attribs[attr++] = init.samplesCount;
- }
- attribs[attr++] = EGL_RED_SIZE;
- attribs[attr++] = init.rgbaBits[0];
- attribs[attr++] = EGL_GREEN_SIZE;
- attribs[attr++] = init.rgbaBits[1];
- attribs[attr++] = EGL_BLUE_SIZE;
- attribs[attr++] = init.rgbaBits[2];
- attribs[attr++] = EGL_ALPHA_SIZE;
- attribs[attr++] = init.rgbaBits[3];
- attribs[attr++] = EGL_DEPTH_SIZE;
- attribs[attr++] = init.depthBits;
- attribs[attr++] = EGL_STENCIL_SIZE;
- attribs[attr++] = init.stencilBits;
- attribs[attr++] = EGL_NONE;
- if(eglChooseConfig(display, &attribs[0], &config, 1, &configsCount) == EGL_FALSE)
- {
- throw ANKI_EXCEPTION("Failed to query required EGL configs");
- }
- if(configsCount == 0)
- {
- throw ANKI_EXCEPTION("No matching EGL configs found");
- }
- eglGetConfigAttrib(display, config, EGL_NATIVE_VISUAL_ID, &format);
- ANKI_ASSERT(andApp.window);
- ANativeWindow_setBuffersGeometry(andApp.window, 0, 0, format);
- // Surface
- //
- surface = eglCreateWindowSurface(display, config, andApp.window, NULL);
- if(surface == EGL_NO_SURFACE)
- {
- throw ANKI_EXCEPTION("Cannot create surface");
- }
- // Context
- //
- EGLint ctxAttribs[] = {EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE};
- context = eglCreateContext(display, config, EGL_NO_CONTEXT, ctxAttribs);
- if(context == EGL_NO_CONTEXT)
- {
- throw ANKI_EXCEPTION("Cannot create context");
- }
- if(eglMakeCurrent(display, surface, surface, context) == EGL_FALSE)
- {
- throw ANKI_EXCEPTION("Cannot make the context current");
- }
- // Query width and height
- //
- EGLint w, h;
- eglQuerySurface(display, surface, EGL_WIDTH, &w);
- eglQuerySurface(display, surface, EGL_HEIGHT, &h);
- init.width = w;
- init.height = h;
- }
- void NativeWindowImpl::destroy()
- {
- if(display != EGL_NO_DISPLAY)
- {
- eglMakeCurrent(display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
- if(context != EGL_NO_CONTEXT)
- {
- eglDestroyContext(display, context);
- }
- if(surface != EGL_NO_SURFACE)
- {
- eglDestroySurface(display, surface);
- }
- eglTerminate(display);
- }
- }
- NativeWindow::~NativeWindow()
- {
- }
- void NativeWindow::init(NativeWindowInitInfo& initializer)
- {
- impl.reset(new NativeWindowImpl);
- impl->create(initializer);
- // Set the size after because the create may have changed it to something
- // more nice
- width = initializer.width;
- height = initializer.height;
- }
- void NativeWindow::destroy()
- {
- impl.reset();
- }
- void NativeWindow::swapBuffers()
- {
- ANKI_COUNTER_START_TIMER(SWAP_BUFFERS_TIME);
- ANKI_ASSERT(isCreated());
- if(eglSwapBuffers(impl->display, impl->surface) == EGL_FALSE)
- {
- throw ANKI_EXCEPTION("eglSwapBuffers() failed");
- }
- ANKI_COUNTER_STOP_TIMER_INC(SWAP_BUFFERS_TIME);
- }
- } // end namespace anki
|