• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2013 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 //--------------------------------------------------------------------------------
18 // GLContext.cpp
19 //--------------------------------------------------------------------------------
20 //--------------------------------------------------------------------------------
21 // includes
22 //--------------------------------------------------------------------------------
23 #include <unistd.h>
24 #include "GLContext.h"
25 #include "gl3stub.h"
26 
27 namespace ndk_helper
28 {
29 
30 //--------------------------------------------------------------------------------
31 // eGLContext
32 //--------------------------------------------------------------------------------
33 
34 //--------------------------------------------------------------------------------
35 // Ctor
36 //--------------------------------------------------------------------------------
GLContext()37 GLContext::GLContext() :
38                 display_( EGL_NO_DISPLAY ),
39                 surface_( EGL_NO_SURFACE ),
40                 context_( EGL_NO_CONTEXT ),
41                 screen_width_( 0 ),
42                 screen_height_( 0 ),
43                 es3_supported_( false ),
44                 egl_context_initialized_( false ),
45                 gles_initialized_( false )
46 {
47 }
48 
InitGLES()49 void GLContext::InitGLES()
50 {
51     if( gles_initialized_ )
52         return;
53     //
54     //Initialize OpenGL ES 3 if available
55     //
56     const char* versionStr = (const char*) glGetString( GL_VERSION );
57     if( strstr( versionStr, "OpenGL ES 3." ) && gl3stubInit() )
58     {
59         es3_supported_ = true;
60         gl_version_ = 3.0f;
61     }
62     else
63     {
64         gl_version_ = 2.0f;
65     }
66 
67     gles_initialized_ = true;
68 }
69 
70 //--------------------------------------------------------------------------------
71 // Dtor
72 //--------------------------------------------------------------------------------
~GLContext()73 GLContext::~GLContext()
74 {
75     Terminate();
76 }
77 
Init(ANativeWindow * window)78 bool GLContext::Init( ANativeWindow* window )
79 {
80     if( egl_context_initialized_ )
81         return true;
82 
83     //
84     //Initialize EGL
85     //
86     window_ = window;
87     InitEGLSurface();
88     InitEGLContext();
89     InitGLES();
90 
91     egl_context_initialized_ = true;
92 
93     return true;
94 }
95 
InitEGLSurface()96 bool GLContext::InitEGLSurface()
97 {
98     display_ = eglGetDisplay( EGL_DEFAULT_DISPLAY );
99     eglInitialize( display_, 0, 0 );
100 
101     /*
102      * Here specify the attributes of the desired configuration.
103      * Below, we select an EGLConfig with at least 8 bits per color
104      * component compatible with on-screen windows
105      */
106     const EGLint attribs[] = { EGL_RENDERABLE_TYPE,
107             EGL_OPENGL_ES2_BIT, //Request opengl ES2.0
108             EGL_SURFACE_TYPE, EGL_WINDOW_BIT, EGL_BLUE_SIZE, 8, EGL_GREEN_SIZE, 8,
109             EGL_RED_SIZE, 8, EGL_DEPTH_SIZE, 24, EGL_NONE };
110     color_size_ = 8;
111     depth_size_ = 24;
112 
113     EGLint num_configs;
114     eglChooseConfig( display_, attribs, &config_, 1, &num_configs );
115 
116     if( !num_configs )
117     {
118         //Fall back to 16bit depth buffer
119         const EGLint attribs[] = { EGL_RENDERABLE_TYPE,
120                 EGL_OPENGL_ES2_BIT, //Request opengl ES2.0
121                 EGL_SURFACE_TYPE, EGL_WINDOW_BIT, EGL_BLUE_SIZE, 8, EGL_GREEN_SIZE, 8,
122                 EGL_RED_SIZE, 8, EGL_DEPTH_SIZE, 16, EGL_NONE };
123         eglChooseConfig( display_, attribs, &config_, 1, &num_configs );
124         depth_size_ = 16;
125     }
126 
127     if( !num_configs )
128     {
129         LOGW( "Unable to retrieve EGL config" );
130         return false;
131     }
132 
133     surface_ = eglCreateWindowSurface( display_, config_, window_, NULL );
134     eglQuerySurface( display_, surface_, EGL_WIDTH, &screen_width_ );
135     eglQuerySurface( display_, surface_, EGL_HEIGHT, &screen_height_ );
136 
137     /* EGL_NATIVE_VISUAL_ID is an attribute of the EGLConfig that is
138      * guaranteed to be accepted by ANativeWindow_setBuffersGeometry().
139      * As soon as we picked a EGLConfig, we can safely reconfigure the
140      * ANativeWindow buffers to match, using EGL_NATIVE_VISUAL_ID. */
141     EGLint format;
142     eglGetConfigAttrib( display_, config_, EGL_NATIVE_VISUAL_ID, &format );
143     ANativeWindow_setBuffersGeometry( window_, 0, 0, format );
144 
145     return true;
146 }
147 
InitEGLContext()148 bool GLContext::InitEGLContext()
149 {
150     const EGLint context_attribs[] = { EGL_CONTEXT_CLIENT_VERSION, 2, //Request opengl ES2.0
151             EGL_NONE };
152     context_ = eglCreateContext( display_, config_, NULL, context_attribs );
153 
154     if( eglMakeCurrent( display_, surface_, surface_, context_ ) == EGL_FALSE )
155     {
156         LOGW( "Unable to eglMakeCurrent" );
157         return false;
158     }
159 
160     context_valid_ = true;
161     return true;
162 }
163 
Swap()164 EGLint GLContext::Swap()
165 {
166     bool b = eglSwapBuffers( display_, surface_ );
167     if( !b )
168     {
169         EGLint err = eglGetError();
170         if( err == EGL_BAD_SURFACE )
171         {
172             //Recreate surface
173             InitEGLSurface();
174             return EGL_SUCCESS; //Still consider glContext is valid
175         }
176         else if( err == EGL_CONTEXT_LOST || err == EGL_BAD_CONTEXT )
177         {
178             //Context has been lost!!
179             context_valid_ = false;
180             Terminate();
181             InitEGLContext();
182         }
183         return err;
184     }
185     return EGL_SUCCESS;
186 }
187 
Terminate()188 void GLContext::Terminate()
189 {
190     if( display_ != EGL_NO_DISPLAY )
191     {
192         eglMakeCurrent( display_, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT );
193         if( context_ != EGL_NO_CONTEXT )
194         {
195             eglDestroyContext( display_, context_ );
196         }
197 
198         if( surface_ != EGL_NO_SURFACE )
199         {
200             eglDestroySurface( display_, surface_ );
201         }
202         eglTerminate( display_ );
203     }
204 
205     display_ = EGL_NO_DISPLAY;
206     context_ = EGL_NO_CONTEXT;
207     surface_ = EGL_NO_SURFACE;
208     context_valid_ = false;
209 
210 }
211 
Resume(ANativeWindow * window)212 EGLint GLContext::Resume( ANativeWindow* window )
213 {
214     if( egl_context_initialized_ == false )
215     {
216         Init( window );
217         return EGL_SUCCESS;
218     }
219 
220     int32_t original_widhth = screen_width_;
221     int32_t original_height = screen_height_;
222 
223     //Create surface
224     window_ = window;
225     surface_ = eglCreateWindowSurface( display_, config_, window_, NULL );
226     eglQuerySurface( display_, surface_, EGL_WIDTH, &screen_width_ );
227     eglQuerySurface( display_, surface_, EGL_HEIGHT, &screen_height_ );
228 
229     if( screen_width_ != original_widhth || screen_height_ != original_height )
230     {
231         //Screen resized
232         LOGI( "Screen resized" );
233     }
234 
235     if( eglMakeCurrent( display_, surface_, surface_, context_ ) == EGL_TRUE )
236         return EGL_SUCCESS;
237 
238     EGLint err = eglGetError();
239     LOGW( "Unable to eglMakeCurrent %d", err );
240 
241     if( err == EGL_CONTEXT_LOST )
242     {
243         //Recreate context
244         LOGI( "Re-creating egl context" );
245         InitEGLContext();
246     }
247     else
248     {
249         //Recreate surface
250         Terminate();
251         InitEGLSurface();
252         InitEGLContext();
253     }
254 
255     return err;
256 
257 }
258 
Suspend()259 void GLContext::Suspend()
260 {
261     if( surface_ != EGL_NO_SURFACE )
262     {
263         eglDestroySurface( display_, surface_ );
264         surface_ = EGL_NO_SURFACE;
265     }
266 }
267 
Invalidate()268 bool GLContext::Invalidate()
269 {
270     Terminate();
271 
272     egl_context_initialized_ = false;
273     return true;
274 }
275 
CheckExtension(const char * extension)276 bool GLContext::CheckExtension( const char* extension )
277 {
278     if( extension == NULL )
279         return false;
280 
281     std::string extensions = std::string( (char*) glGetString( GL_EXTENSIONS ) );
282     std::string str = std::string( extension );
283     str.append( " " );
284 
285     size_t pos = 0;
286     if( extensions.find( extension, pos ) != std::string::npos )
287     {
288         return true;
289     }
290 
291     return false;
292 }
293 
294 }   //namespace ndkHelper
295