JeVois  1.21
JeVois Smart Embedded Machine Vision Toolkit
Share this page:
Loading...
Searching...
No Matches
VideoDisplayBackend.C
Go to the documentation of this file.
1// ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2//
3// JeVois Smart Embedded Machine Vision Toolkit - Copyright (C) 2020 by Laurent Itti, the University of Southern
4// California (USC), and iLab at USC. See http://iLab.usc.edu and http://jevois.org for information about this project.
5//
6// This file is part of the JeVois Smart Embedded Machine Vision Toolkit. This program is free software; you can
7// redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software
8// Foundation, version 2. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
9// without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
10// License for more details. You should have received a copy of the GNU General Public License along with this program;
11// if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
12//
13// Contact information: Laurent Itti - 3641 Watt Way, HNB-07A - Los Angeles, CA 90089-2520 - USA.
14// Tel: +1 213 740 3527 - itti@pollux.usc.edu - http://iLab.usc.edu - http://jevois.org
15// ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
16
17// Some of this code inspired by:
18// https://github.com/D3Engineering/410c_camera_support
19
20/* Copyright (c) 2017 D3 Engineering
21 * MIT License
22 *
23 * Permission is hereby granted, free of charge, to any person obtaining a copy
24 * of this software and associated documentation files (the "Software"), to deal
25 * in the Software without restriction, including without limitation the rights
26 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
27 * copies of the Software, and to permit persons to whom the Software is
28 * furnished to do so, subject to the following conditions:
29 *
30 * The above copyright notice and this permission notice shall be included in all
31 * copies or substantial portions of the Software.
32 *
33 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
34 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
35 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
36 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
37 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
38 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
39 * SOFTWARE. */
40
41#ifdef JEVOIS_PRO
42
44
45// ##############################################################################################################
48
49// ##############################################################################################################
51{
52 // It is better to call uninit() explicitly from the same thread that called init() and others, but just in case:
53 uninit();
54}
55
56// ##############################################################################################################
57void jevois::VideoDisplayBackend::init(unsigned short, unsigned short, EGLNativeWindowType win)
58{
59 if (itsDisplay) { LERROR("Display already initialized -- IGNORED"); return; }
60
61 // Get an EGL display connection:
62 itsDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);
63 if (itsDisplay == EGL_NO_DISPLAY) LFATAL("Could not get an OpenGL display");
64
65 // Initialize the EGL display connection:
66 EGLint major, minor;
67 GL_CHECK_BOOL(eglInitialize(itsDisplay, &major, &minor););
68 LINFO("Initialized EGL v" << major << '.' << minor);
69
70 // Query the EGL API. We need OpenGL-ES:
71 EGLenum const api = eglQueryAPI();
72 switch(api)
73 {
74 case EGL_OPENGL_API: LFATAL("EGL API is unsupported EGL_OPENGL_API"); break;
75 case EGL_OPENGL_ES_API: LINFO("EGL API is EGL_OPENGL_ES_API"); break;
76 case EGL_OPENVG_API: LFATAL("EGL API is unsupported EGL_OPENVG_API"); break;
77 case EGL_NONE: LFATAL("EGL API is unsupported EGL_NONE"); break;
78 default: LFATAL("EGL API is unknown");
79 }
80
81 // Get an appropriate EGL configuration:
82 static EGLint const cfg_attr[] =
83 {
84 EGL_SAMPLES, EGL_DONT_CARE, // 4
85 EGL_ALPHA_SIZE, 8,
86 EGL_RED_SIZE, 8,
87 EGL_GREEN_SIZE, 8,
88 EGL_BLUE_SIZE, 8,
89 EGL_BUFFER_SIZE, 32,
90 EGL_STENCIL_SIZE, 0,
91 EGL_RENDERABLE_TYPE, EGL_OPENGL_ES3_BIT_KHR,
92 EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
93 EGL_DEPTH_SIZE, 16,
94 EGL_CONFORMANT, EGL_OPENGL_ES2_BIT,
95 EGL_NONE
96 };
97
98 EGLint num_config;
99 GL_CHECK_BOOL(eglChooseConfig(itsDisplay, cfg_attr, nullptr, 0, &num_config));
100 LINFO("OpenGL configs available: " << num_config);
101 if (num_config < 1) LFATAL("Could not find a suitable OpenGL config");
102
103 EGLConfig * configs = new EGLConfig[num_config];
104 GL_CHECK_BOOL(eglChooseConfig(itsDisplay, cfg_attr, configs, num_config, &num_config));
105 bool gotit = false;
106 for (int i = 0; i < num_config; ++i)
107 {
108 EGLint val = 0;
109 std::string info;
110
111#define JEVOIS_EGL_INFO(x) GL_CHECK(eglGetConfigAttrib(itsDisplay, configs[i], x, &val)); \
112 info += std::string(#x) + '=' + std::to_string(val) + ", ";
113
114 JEVOIS_EGL_INFO(EGL_CONFIG_ID);
115 JEVOIS_EGL_INFO(EGL_RED_SIZE);
116 JEVOIS_EGL_INFO(EGL_GREEN_SIZE);
117 JEVOIS_EGL_INFO(EGL_BLUE_SIZE);
118 JEVOIS_EGL_INFO(EGL_ALPHA_SIZE);
119 JEVOIS_EGL_INFO(EGL_ALPHA_MASK_SIZE);
120 JEVOIS_EGL_INFO(EGL_DEPTH_SIZE);
121 JEVOIS_EGL_INFO(EGL_STENCIL_SIZE);
122 JEVOIS_EGL_INFO(EGL_SAMPLE_BUFFERS);
123 JEVOIS_EGL_INFO(EGL_SAMPLES);
124 JEVOIS_EGL_INFO(EGL_CONFIG_CAVEAT);
125
126 JEVOIS_EGL_INFO(EGL_MAX_PBUFFER_WIDTH);
127 JEVOIS_EGL_INFO(EGL_MAX_PBUFFER_HEIGHT);
128 JEVOIS_EGL_INFO(EGL_MAX_PBUFFER_PIXELS);
129 JEVOIS_EGL_INFO(EGL_NATIVE_RENDERABLE);
130 JEVOIS_EGL_INFO(EGL_NATIVE_VISUAL_ID);
131 JEVOIS_EGL_INFO(EGL_NATIVE_VISUAL_TYPE);
132 JEVOIS_EGL_INFO(EGL_SURFACE_TYPE);
133 JEVOIS_EGL_INFO(EGL_TRANSPARENT_TYPE);
134 JEVOIS_EGL_INFO(EGL_BIND_TO_TEXTURE_RGB);
135 JEVOIS_EGL_INFO(EGL_BIND_TO_TEXTURE_RGBA);
136 JEVOIS_EGL_INFO(EGL_MAX_SWAP_INTERVAL);
137 JEVOIS_EGL_INFO(EGL_MIN_SWAP_INTERVAL);
138 JEVOIS_EGL_INFO(EGL_CONFORMANT);
139
140 LINFO("EGL config " << i << ": " << info);
141
142#undef JEVOIS_EGL_INFO
143
144 GL_CHECK(eglGetConfigAttrib(itsDisplay, configs[i], EGL_RED_SIZE, &val));
145 if (val != 8) continue;
146 GL_CHECK(eglGetConfigAttrib(itsDisplay, configs[i], EGL_GREEN_SIZE, &val));
147 if (val != 8) continue;
148 GL_CHECK(eglGetConfigAttrib(itsDisplay, configs[i], EGL_BLUE_SIZE, &val));
149 if (val != 8) continue;
150 if (gotit == false)
151 {
152 LINFO("Using config " << i << " with 8-bit R,G,B.");
153 itsConfig = configs[i];
154 gotit = true;
155 //break;
156 }
157 }
158 delete [] configs;
159
160 if (gotit == false) LFATAL("Could not find a suitable OpenGL config");
161
162 // Create a native surface:
163 static EGLint const win_attr[] =
164 {
165 //EGL_RENDER_BUFFER, EGL_BACK_BUFFER,
166 EGL_NONE
167 };
168 GL_CHECK(itsSurface = eglCreateWindowSurface(itsDisplay, itsConfig, win, win_attr));
169 LINFO("OpenGL surface created ok.");
170
171 // Bind to OpenGL-ES API:
172 GL_CHECK_BOOL(eglBindAPI(EGL_OPENGL_ES_API));
173
174 LINFO("OpenGL-ES API bound ok.");
175
176 // Create an EGL rendering context:
177 static EGLint const ctx_attr[] =
178 {
179 EGL_CONTEXT_CLIENT_VERSION, 3,
180 EGL_CONTEXT_MAJOR_VERSION_KHR, 3,
181 EGL_CONTEXT_MINOR_VERSION_KHR, 2,
182 EGL_NONE
183 };
184
185 GL_CHECK(itsContext = eglCreateContext(itsDisplay, itsConfig, EGL_NO_CONTEXT, ctx_attr));
186 if (itsContext == EGL_NO_CONTEXT) LFATAL("Failed to create OpenGL context");
187 LINFO("OpenGL context ok");
188
189 // Bind the context to the surface:
190 GL_CHECK(eglMakeCurrent(itsDisplay, itsSurface, itsSurface, itsContext));
191
192 // Show OpenGL-ES version:
193 glGetIntegerv(GL_MAJOR_VERSION, &major);
194 glGetIntegerv(GL_MINOR_VERSION, &minor);
195 LINFO(glGetString(GL_VERSION) <<' '<< glGetString(GL_VENDOR) << " (" << glGetString(GL_RENDERER) <<
196 ") GL_VER=" << major << '.' << minor);
197 LINFO("OpenGL extensions: " << glGetString(GL_EXTENSIONS));
198
199 // Synchronize buffer swapping to vsync for tear-free display:
200 GL_CHECK_BOOL(eglSwapInterval(itsDisplay, 0));
201
202 // Enable blending, used for RGBA textures that have transparency:
203 glEnable(GL_BLEND);
204 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
205}
206
207// ##############################################################################################################
209{
210 if (itsDisplay != EGL_NO_DISPLAY)
211 {
212 eglBindAPI(EGL_OPENGL_ES_API);
213 eglMakeCurrent(itsDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, itsContext);
214 eglMakeCurrent(itsDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
215 if (itsSurface) { eglDestroySurface(itsDisplay, itsSurface); itsSurface = 0; }
216 eglDestroyContext(itsDisplay, itsContext); itsContext = EGL_NO_CONTEXT;
217 eglTerminate(itsDisplay); itsDisplay = EGL_NO_DISPLAY;
218 itsConfig = 0;
219 }
220}
221
222// ##############################################################################################################
224{
225 // Check if display window has been resized by user:
226 unsigned short w, h; getWindowSize(w, h);
227
228 if (w == 0) LFATAL("Need to call init() first");
229
230 // Set the viewport and clear the display:
231 glViewport(0, 0, w, h);
232 glClear(GL_COLOR_BUFFER_BIT);
233}
234
235// ##############################################################################################################
237{
238 // Display the frame after render is complete at the next vertical sync. This is drawn on our EGL surface:
239 GL_CHECK_BOOL(eglSwapBuffers(itsDisplay, itsSurface));
240}
241
242// ##############################################################################################################
243void jevois::VideoDisplayBackend::getWindowSize(unsigned short & w, unsigned short & h) const
244{
245 if (itsSurface)
246 {
247 EGLint ww, hh;
248 GL_CHECK(eglQuerySurface(itsDisplay, itsSurface, EGL_WIDTH, &ww));
249 GL_CHECK(eglQuerySurface(itsDisplay, itsSurface, EGL_HEIGHT, &hh));
250 w = ww; h = hh;
251 }
252 else
253 {
254 w = 0; h = 0;
255 }
256}
257
258// ##############################################################################################################
260{ return itsDisplay; }
261
262#endif // JEVOIS_PRO
int h
Definition GUIhelper.C:2491
#define GL_CHECK(stmt)
Simple macro to check for OpenGL errors.
Definition OpenGL.H:77
#define GL_CHECK_BOOL(stmt)
Simple macro to check for OpenGL errors when a boolean result is expected.
Definition OpenGL.H:81
#define JEVOIS_EGL_INFO(x)
virtual void newFrame()
Start a new frame and clear the window/framebuffer.
virtual void uninit()
Un-initialize the underlying engine, close windows, etc.
virtual void render()
Render the VideoDisplay graphics.
EGLDisplay getDisplay() const
Access our display.
virtual ~VideoDisplayBackend()
Virtual destructor for safe inheritance, free resources.
virtual void init(unsigned short w, unsigned short h, bool fullscreen=false)=0
Initialize the underlying engine that will process events, create windows, etc.
virtual void getWindowSize(unsigned short &w, unsigned short &h) const
#define LFATAL(msg)
Convenience macro for users to print out console or syslog messages, FATAL level.
Definition Log.H:230
#define LERROR(msg)
Convenience macro for users to print out console or syslog messages, ERROR level.
Definition Log.H:211
#define LINFO(msg)
Convenience macro for users to print out console or syslog messages, INFO level.
Definition Log.H:194