23 jevois::Component(instance), itsProgramChanged(false), itsQuadVertexBuffer(0), itsDisplay(EGL_NO_DISPLAY),
24 itsConfig(0), itsContext(0), itsSurface(0), itsFramebufferId(0), itsRenderbufferId(0),
25 itsRenderWidth(0), itsRenderHeight(0), itsRenderType(0)
29 void FilterGPU::initDisplay()
32 GL_CHECK(itsDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY));
33 if (itsDisplay == EGL_NO_DISPLAY)
LFATAL(
"Could not get an OpenGL display");
38 LINFO(
"Initialized OpenGL-ES with EGL v" << major <<
'.' << minor);
42 static EGLint
const cfg_attr[] =
43 { EGL_SURFACE_TYPE, EGL_WINDOW_BIT, EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, EGL_NONE };
44 GL_CHECK_BOOL(eglChooseConfig(itsDisplay, cfg_attr, &itsConfig, 1, &num_config));
45 if (num_config < 1)
LFATAL(
"Could not find a suitable OpenGL config");
48 GL_CHECK(itsSurface = eglCreatePbufferSurface(itsDisplay, itsConfig, NULL));
54 static EGLint
const ctx_attr[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE };
55 GL_CHECK(itsContext = eglCreateContext(itsDisplay, itsConfig, EGL_NO_CONTEXT, ctx_attr));
56 if (itsContext == EGL_NO_CONTEXT)
LFATAL(
"Failed to create OpenGL context");
59 GL_CHECK(eglMakeCurrent(itsDisplay, itsSurface, itsSurface, itsContext));
66 itsProgram.reset(); itsSrcTex.reset();
68 if (itsRenderbufferId) glDeleteRenderbuffers(1, &itsRenderbufferId);
69 if (itsFramebufferId) glDeleteFramebuffers(1, &itsFramebufferId);
71 glDeleteBuffers(1, &itsQuadVertexBuffer);
74 eglMakeCurrent(itsDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
75 if (itsSurface) eglDestroySurface(itsDisplay, itsSurface);
76 eglDestroyContext(itsDisplay, itsContext);
77 eglTerminate(itsDisplay);
85 std::lock_guard<std::mutex> _(itsMutex);
88 itsProgramChanged =
true;
89 itsProgramParams.clear();
95 std::lock_guard<std::mutex> _(itsMutex);
96 itsProgramParams[
name] = { F2, { val1, val2 } };
97 itsProgramChanged =
true;
103 std::lock_guard<std::mutex> _(itsMutex);
104 itsProgramParams[
name] = { F1, { val, 0.0F } };
105 itsProgramChanged =
true;
111 std::lock_guard<std::mutex> _(itsMutex);
113 itsProgramChanged =
true;
119 std::lock_guard<std::mutex> _(itsMutex);
120 itsProgramParams[
name] = { I2, {
float(val), 0.0F } };
121 itsProgramChanged =
true;
131 if (itsDisplay == EGL_NO_DISPLAY) initDisplay();
133 if (src.type() != CV_8UC1 && src.type() != CV_8UC4)
LFATAL(
"Source pixel format must be CV_8UC1 or CV_8UC4");
134 if (dst.type() != CV_8UC2 && dst.type() != CV_8UC4)
LFATAL(
"Dest pixel format must be CV_8UC2 or CV_8UC4");
135 GLuint
const srcformat = (src.channels() == 4 ? GL_RGBA : GL_LUMINANCE);
136 GLuint
const dstformat = (dst.channels() == 4 ? GL_RGBA4 : GL_RGB565);
139 if (!itsSrcTex || itsSrcTex->Width != src.cols || itsSrcTex->Height != src.rows || itsSrcTex->Format != srcformat)
141 itsSrcTex.reset(
new GPUtexture(src.cols, src.rows, srcformat,
false));
142 LINFO(
"Input texture " << itsSrcTex->Width <<
'x' << itsSrcTex->Height <<
' ' <<
143 (srcformat == GL_RGBA ?
"RGBA" :
"LUMINANCE") <<
" ready.");
147 if (itsRenderbufferId == 0 || itsRenderWidth != dst.cols || itsRenderHeight != dst.rows ||
148 itsRenderType != dst.type())
150 if (itsRenderbufferId) glDeleteRenderbuffers(1, &itsRenderbufferId);
151 if (itsFramebufferId) glDeleteFramebuffers(1, &itsFramebufferId);
153 GL_CHECK(glGenFramebuffers(1, &itsFramebufferId));
154 GL_CHECK(glBindFramebuffer(GL_FRAMEBUFFER, itsFramebufferId));
156 GL_CHECK(glGenRenderbuffers(1, &itsRenderbufferId));
157 GL_CHECK(glBindRenderbuffer(GL_RENDERBUFFER, itsRenderbufferId));
158 GL_CHECK(glRenderbufferStorage(GL_RENDERBUFFER, dstformat, dst.cols, dst.rows));
159 GL_CHECK(glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, itsRenderbufferId));
161 if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
162 LFATAL(
"Framebuffer creation failed");
164 itsRenderWidth = dst.cols; itsRenderHeight = dst.rows; itsRenderType = dst.type();
165 LINFO(
"Render buffer " << itsRenderWidth <<
'x' << itsRenderHeight <<
' ' <<
166 (dst.channels() == 2 ?
"RGB565" :
"RGBA") <<
" ready.");
170 if (itsQuadVertexBuffer == 0)
173 static GLfloat
const qv[] =
174 { 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 };
176 GL_CHECK(glGenBuffers(1, &itsQuadVertexBuffer));
177 glBindBuffer(GL_ARRAY_BUFFER, itsQuadVertexBuffer);
178 glBufferData(GL_ARRAY_BUFFER,
sizeof(qv), qv, GL_STATIC_DRAW);
179 GL_CHECK(glBindBuffer(GL_ARRAY_BUFFER, 0));
183 glClearColor(0.15f, 0.25f, 0.35f, 1.0f);
184 glClear(GL_COLOR_BUFFER_BIT);
187 itsSrcTex->setPixels(src.data);
190 GL_CHECK(glBindFramebuffer(GL_FRAMEBUFFER, itsFramebufferId));
191 GL_CHECK(glViewport(0, 0, itsRenderWidth, itsRenderHeight));
194 if (itsProgramChanged)
196 std::lock_guard<std::mutex> _(itsMutex);
202 itsProgram.reset(
new GPUprogram(itsVshader.c_str(), itsFshader.c_str()));
203 itsProgramChanged =
false;
206 glUseProgram(itsProgram->id());
209 GLuint i = itsProgram->id();
210 for (
auto const & p : itsProgramParams)
212 char const * n = p.first.c_str();
213 float const * v = &p.second.val[0];
214 switch (p.second.type)
216 case F2:
GL_CHECK(glUniform2f(glGetUniformLocation(i, n), v[0], v[1]));
break;
217 case F1:
GL_CHECK(glUniform1f(glGetUniformLocation(i, n), v[0]));
break;
218 case I2:
GL_CHECK(glUniform2i(glGetUniformLocation(i, n),
int(v[0]),
int(v[1])));
break;
219 case I1:
GL_CHECK(glUniform1i(glGetUniformLocation(i, n),
int(v[0])));
break;
220 default:
LFATAL(
"Unsupported GPU program parameter type " << p.second.type);
225 if (!itsProgram)
LFATAL(
"You need to set a program before processing frames");
228 glUniform2f(glGetUniformLocation(itsProgram->id(),
"texelsize"), 1.0f / dst.cols, 1.0f / dst.rows);
229 glUniform1i(glGetUniformLocation(itsProgram->id(),
"tex"), 0);
232 GL_CHECK(glBindBuffer(GL_ARRAY_BUFFER, itsQuadVertexBuffer));
233 GL_CHECK(glActiveTexture(GL_TEXTURE0));
234 GL_CHECK(glBindTexture(GL_TEXTURE_2D, itsSrcTex->Id));
236 GLuint loc = glGetAttribLocation(itsProgram->id(),
"vertex");
237 GL_CHECK(glVertexAttribPointer(loc, 4, GL_FLOAT, 0, 16, 0));
238 GL_CHECK(glEnableVertexAttribArray(loc));
239 GL_CHECK(glDrawArrays(GL_TRIANGLE_STRIP, 0, 4));
242 GL_CHECK(glBindFramebuffer(GL_FRAMEBUFFER, itsFramebufferId));
243 if (dstformat == GL_RGBA4)
GL_CHECK(glReadPixels(0, 0, dst.cols, dst.rows, GL_RGBA, GL_UNSIGNED_BYTE, dst.data));
244 else GL_CHECK(glReadPixels(0, 0, dst.cols, dst.rows, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, dst.data));
245 GL_CHECK(glBindFramebuffer(GL_FRAMEBUFFER, 0));