22 jevois::Component(instance), itsProgramChanged(false), itsQuadVertexBuffer(0), itsDisplay(EGL_NO_DISPLAY),
23 itsConfig(0), itsContext(0), itsSurface(0), itsFramebufferId(0), itsRenderbufferId(0),
24 itsRenderWidth(0), itsRenderHeight(0), itsRenderType(0)
28 void FilterGPU::initDisplay()
31 GL_CHECK(itsDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY));
32 if (itsDisplay == EGL_NO_DISPLAY)
LFATAL(
"Could not get an OpenGL display");
37 LINFO(
"Initialized OpenGL-ES with EGL v" << major <<
'.' << minor);
41 static EGLint
const cfg_attr[] =
42 { EGL_SURFACE_TYPE, EGL_WINDOW_BIT, EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, EGL_NONE };
43 GL_CHECK_BOOL(eglChooseConfig(itsDisplay, cfg_attr, &itsConfig, 1, &num_config));
44 if (num_config < 1)
LFATAL(
"Could not find a suitable OpenGL config");
47 GL_CHECK(itsSurface = eglCreatePbufferSurface(itsDisplay, itsConfig, NULL));
53 static EGLint
const ctx_attr[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE };
54 GL_CHECK(itsContext = eglCreateContext(itsDisplay, itsConfig, EGL_NO_CONTEXT, ctx_attr));
55 if (itsContext == EGL_NO_CONTEXT)
LFATAL(
"Failed to create OpenGL context");
58 GL_CHECK(eglMakeCurrent(itsDisplay, itsSurface, itsSurface, itsContext));
65 itsProgram.reset(); itsSrcTex.reset();
67 if (itsRenderbufferId) glDeleteRenderbuffers(1, &itsRenderbufferId);
68 if (itsFramebufferId) glDeleteFramebuffers(1, &itsFramebufferId);
70 glDeleteBuffers(1, &itsQuadVertexBuffer);
73 eglMakeCurrent(itsDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
74 if (itsSurface) eglDestroySurface(itsDisplay, itsSurface);
75 eglDestroyContext(itsDisplay, itsContext);
76 eglTerminate(itsDisplay);
84 std::lock_guard<std::mutex> _(itsMutex);
87 itsProgramChanged =
true;
88 itsProgramParams.clear();
94 std::lock_guard<std::mutex> _(itsMutex);
95 itsProgramParams[
name] = { F2, { val1, val2 } };
96 itsProgramChanged =
true;
102 std::lock_guard<std::mutex> _(itsMutex);
103 itsProgramParams[
name] = { F1, { val, 0.0F } };
104 itsProgramChanged =
true;
110 std::lock_guard<std::mutex> _(itsMutex);
112 itsProgramChanged =
true;
118 std::lock_guard<std::mutex> _(itsMutex);
119 itsProgramParams[
name] = { I2, {
float(val), 0.0F } };
120 itsProgramChanged =
true;
130 if (itsDisplay == EGL_NO_DISPLAY) initDisplay();
132 if (src.type() != CV_8UC1 && src.type() != CV_8UC4)
LFATAL(
"Source pixel format must be CV_8UC1 or CV_8UC4");
133 if (dst.type() != CV_8UC2 && dst.type() != CV_8UC4)
LFATAL(
"Dest pixel format must be CV_8UC2 or CV_8UC4");
134 GLuint
const srcformat = (src.channels() == 4 ? GL_RGBA : GL_LUMINANCE);
135 GLuint
const dstformat = (dst.channels() == 4 ? GL_RGBA4 : GL_RGB565);
138 if (!itsSrcTex || itsSrcTex->Width != src.cols || itsSrcTex->Height != src.rows || itsSrcTex->Format != srcformat)
140 itsSrcTex.reset(
new GPUtexture(src.cols, src.rows, srcformat,
false));
141 LINFO(
"Input texture " << itsSrcTex->Width <<
'x' << itsSrcTex->Height <<
' ' <<
142 (srcformat == GL_RGBA ?
"RGBA" :
"LUMINANCE") <<
" ready.");
146 if (itsRenderbufferId == 0 ||
int(itsRenderWidth) != dst.cols ||
int(itsRenderHeight) != dst.rows ||
147 itsRenderType != dst.type())
149 if (itsRenderbufferId) glDeleteRenderbuffers(1, &itsRenderbufferId);
150 if (itsFramebufferId) glDeleteFramebuffers(1, &itsFramebufferId);
152 GL_CHECK(glGenFramebuffers(1, &itsFramebufferId));
153 GL_CHECK(glBindFramebuffer(GL_FRAMEBUFFER, itsFramebufferId));
155 GL_CHECK(glGenRenderbuffers(1, &itsRenderbufferId));
156 GL_CHECK(glBindRenderbuffer(GL_RENDERBUFFER, itsRenderbufferId));
157 GL_CHECK(glRenderbufferStorage(GL_RENDERBUFFER, dstformat, dst.cols, dst.rows));
158 GL_CHECK(glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, itsRenderbufferId));
160 if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
161 LFATAL(
"Framebuffer creation failed");
163 itsRenderWidth = dst.cols; itsRenderHeight = dst.rows; itsRenderType = dst.type();
164 LINFO(
"Render buffer " << itsRenderWidth <<
'x' << itsRenderHeight <<
' ' <<
165 (dst.channels() == 2 ?
"RGB565" :
"RGBA") <<
" ready.");
169 if (itsQuadVertexBuffer == 0)
172 static GLfloat
const qv[] =
173 { 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f };
175 GL_CHECK(glGenBuffers(1, &itsQuadVertexBuffer));
176 glBindBuffer(GL_ARRAY_BUFFER, itsQuadVertexBuffer);
177 glBufferData(GL_ARRAY_BUFFER,
sizeof(qv), qv, GL_STATIC_DRAW);
178 GL_CHECK(glBindBuffer(GL_ARRAY_BUFFER, 0));
182 glClearColor(0.15f, 0.25f, 0.35f, 1.0f);
183 glClear(GL_COLOR_BUFFER_BIT);
186 itsSrcTex->setPixels(src.data);
189 GL_CHECK(glBindFramebuffer(GL_FRAMEBUFFER, itsFramebufferId));
190 GL_CHECK(glViewport(0, 0, itsRenderWidth, itsRenderHeight));
193 if (itsProgramChanged)
195 std::lock_guard<std::mutex> _(itsMutex);
201 itsProgram.reset(
new GPUprogram(itsVshader.c_str(), itsFshader.c_str()));
202 itsProgramChanged =
false;
205 glUseProgram(itsProgram->id());
208 GLuint i = itsProgram->id();
209 for (
auto const & p : itsProgramParams)
211 char const * n = p.first.c_str();
212 float const * v = &p.second.val[0];
213 switch (p.second.type)
215 case F2:
GL_CHECK(glUniform2f(glGetUniformLocation(i, n), v[0], v[1]));
break;
216 case F1:
GL_CHECK(glUniform1f(glGetUniformLocation(i, n), v[0]));
break;
217 case I2:
GL_CHECK(glUniform2i(glGetUniformLocation(i, n),
int(v[0]),
int(v[1])));
break;
218 case I1:
GL_CHECK(glUniform1i(glGetUniformLocation(i, n),
int(v[0])));
break;
219 default:
LFATAL(
"Unsupported GPU program parameter type " << p.second.type);
224 if (!itsProgram)
LFATAL(
"You need to set a program before processing frames");
227 glUniform2f(glGetUniformLocation(itsProgram->id(),
"texelsize"), 1.0f / dst.cols, 1.0f / dst.rows);
228 glUniform1i(glGetUniformLocation(itsProgram->id(),
"tex"), 0);
231 GL_CHECK(glBindBuffer(GL_ARRAY_BUFFER, itsQuadVertexBuffer));
232 GL_CHECK(glActiveTexture(GL_TEXTURE0));
233 GL_CHECK(glBindTexture(GL_TEXTURE_2D, itsSrcTex->Id));
235 GLuint loc = glGetAttribLocation(itsProgram->id(),
"vertex");
236 GL_CHECK(glVertexAttribPointer(loc, 4, GL_FLOAT, 0, 16, 0));
237 GL_CHECK(glEnableVertexAttribArray(loc));
238 GL_CHECK(glDrawArrays(GL_TRIANGLE_STRIP, 0, 4));
241 GL_CHECK(glBindFramebuffer(GL_FRAMEBUFFER, itsFramebufferId));
242 if (dstformat == GL_RGBA4)
GL_CHECK(glReadPixels(0, 0, dst.cols, dst.rows, GL_RGBA, GL_UNSIGNED_BYTE, dst.data));
243 else GL_CHECK(glReadPixels(0, 0, dst.cols, dst.rows, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, dst.data));
244 GL_CHECK(glBindFramebuffer(GL_FRAMEBUFFER, 0));