]> git.tdb.fi Git - libs/gui.git/blob - source/graphics/egl_android/glcontext.cpp
Use nullptr in place of 0 or NULL
[libs/gui.git] / source / graphics / egl_android / glcontext.cpp
1 #include "glcontext.h"
2 #include <vector>
3 #include <EGL/egl.h>
4 #include <GLES2/gl2.h>
5 #include <android/native_window.h>
6 #include "display.h"
7 #include "window_private.h"
8
9 using namespace std;
10
11 namespace Msp {
12 namespace Graphics {
13
14 struct GLContext::Private
15 {
16         EGLDisplay display = EGL_NO_DISPLAY;
17         EGLConfig config = EGL_NO_CONFIG;
18         EGLSurface surface = EGL_NO_SURFACE;
19         EGLContext context = EGL_NO_CONTEXT;
20
21         void attach(WindowHandle);
22         void detach();
23 };
24
25
26 void GLContext::platform_init(const GLOptions &opts)
27 {
28         EGLDisplay egl_display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
29         if(egl_display==EGL_NO_DISPLAY)
30                 throw runtime_error("no egl display");
31
32         if(!eglInitialize(egl_display, nullptr, nullptr))
33                 throw runtime_error("could not initialize egl");
34
35         vector<int> attribs;
36
37         attribs.push_back(EGL_COLOR_BUFFER_TYPE);
38         attribs.push_back(EGL_RGB_BUFFER);
39         attribs.push_back(EGL_RENDERABLE_TYPE);
40         attribs.push_back(EGL_OPENGL_ES2_BIT);
41         attribs.push_back(EGL_SURFACE_TYPE);
42         attribs.push_back(EGL_WINDOW_BIT);
43         attribs.push_back(EGL_DEPTH_SIZE);
44         attribs.push_back(1);
45
46         if(opts.alpha)
47         {
48                 attribs.push_back(EGL_ALPHA_SIZE);
49                 attribs.push_back(1);
50         }
51
52         if(opts.stencil)
53         {
54                 attribs.push_back(EGL_STENCIL_SIZE);
55                 attribs.push_back(1);
56         }
57
58         if(opts.multisample>0)
59         {
60                 attribs.push_back(EGL_SAMPLE_BUFFERS);
61                 attribs.push_back(1);
62                 attribs.push_back(EGL_SAMPLES);
63                 attribs.push_back(opts.multisample);
64         }
65
66         attribs.push_back(EGL_NONE);
67
68         EGLConfig config;
69         int num_configs;
70         if(!eglChooseConfig(egl_display, &attribs.front(), &config, 1, &num_configs))
71         {
72                 eglTerminate(egl_display);
73                 throw unsupported_gl_mode(opts);
74         }
75
76         priv = new Private;
77         priv->display = egl_display;
78         priv->config = config;
79
80         /* Must wait for the window to be available, because the calling code
81         expects GL to be usable after creation of the context. */
82         WindowHandle native_window;
83         const Window::Private &window_priv = window.get_private();
84         while(!(native_window = window_priv.window))
85                 display.tick();
86
87         int format;
88         eglGetConfigAttrib(priv->display, config, EGL_NATIVE_VISUAL_ID, &format);
89         ANativeWindow_setBuffersGeometry(native_window, 0, 0, format);
90
91         priv->surface = eglCreateWindowSurface(priv->display, config, native_window, nullptr);
92
93         eglBindAPI(EGL_OPENGL_ES_API);
94         int context_attribs[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE };
95         priv->context = eglCreateContext(priv->display, config, nullptr, context_attribs);
96
97         eglMakeCurrent(priv->display, priv->surface, priv->surface, priv->context);
98
99         window_priv.signal_window_acquired.connect(sigc::mem_fun(priv, &Private::attach));
100         window_priv.signal_window_lost.connect(sigc::mem_fun(priv, &Private::detach));
101 }
102
103 GLContext::~GLContext()
104 {
105         eglDestroyContext(priv->display, priv->context);
106         if(priv->surface!=EGL_NO_SURFACE)
107                 eglDestroySurface(priv->display, priv->surface);
108         eglTerminate(priv->display);
109         delete priv;
110 }
111
112 void GLContext::set_swap_interval(unsigned)
113 {
114         // TODO
115 }
116
117 void GLContext::swap_buffers()
118 {
119         eglSwapBuffers(priv->display, priv->surface);
120 }
121
122 void GLContext::window_resized(unsigned, unsigned)
123 { }
124
125
126 void GLContext::Private::attach(WindowHandle native_window)
127 {
128         surface = eglCreateWindowSurface(display, config, native_window, 0);
129         eglMakeCurrent(display, surface, surface, context);
130 }
131
132 void GLContext::Private::detach()
133 {
134         eglMakeCurrent(display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
135         eglDestroySurface(display, surface);
136 }
137
138 } // namespace Graphics
139 } // namespace Msp