26 #include <glm/glm.hpp>
27 #include <glm/gtc/type_ptr.hpp>
35 extern char const *
vert;
56 if (itsVertexArray) glDeleteVertexArrays(1, &itsVertexArray);
57 if (itsVertexBuffers[0]) glDeleteBuffers(2, itsVertexBuffers);
62 unsigned char const * data)
64 if (width == 0 || height == 0)
LFATAL(
"Cannot handle zero image width or height");
69 char const * frag_shader;
72 case V4L2_PIX_FMT_YUYV:
75 itsGLtextureWidth = width / 2; itsGLtextureFmt = GL_RGBA;
78 case V4L2_PIX_FMT_RGB32:
81 itsGLtextureWidth = width; itsGLtextureFmt = GL_RGBA;
84 case V4L2_PIX_FMT_GREY:
87 itsGLtextureWidth = width; itsGLtextureFmt = GL_LUMINANCE;
90 case V4L2_PIX_FMT_RGB24:
93 itsGLtextureWidth = width * 3; itsGLtextureFmt = GL_LUMINANCE;
96 case V4L2_PIX_FMT_BGR24:
97 case V4L2_PIX_FMT_SRGGB8:
98 case V4L2_PIX_FMT_RGB565:
99 case V4L2_PIX_FMT_MJPEG:
100 case V4L2_PIX_FMT_UYVY:
101 case V4L2_PIX_FMT_SBGGR16:
102 case V4L2_PIX_FMT_SGRBG16:
103 case V4L2_PIX_FMT_NV12:
104 case V4L2_PIX_FMT_YUV444:
113 itsLocation = glGetUniformLocation(itsProgram->id(),
"s_texture");
117 if (width != itsTextureWidth || height != itsTextureHeight || fmt != itsFormat || !itsTexture)
120 itsTexture.reset(
new jevois::GPUtexture(itsGLtextureWidth, height, itsGLtextureFmt,
false));
121 LDEBUG(
"Input texture for " << width <<
'x' << height <<
' ' <<
jevois::fccstr(fmt) <<
" ready.");
124 #ifdef JEVOIS_PLATFORM_PRO
125 if (itsTextureDmaBuf) itsTextureDmaBuf.reset();
129 itsTexture->setPixels(data);
132 itsTextureWidth = width; itsTextureHeight = height; itsFormat = fmt;
138 setInternal(img.
width, img.
height, img.
fmt,
static_cast<unsigned char const *
>(img.
buf->data()));
148 case CV_8UC4:
if (rgb) fmt = V4L2_PIX_FMT_RGB32;
else fmt = V4L2_PIX_FMT_BGR32;
break;
149 case CV_8UC3:
if (rgb) fmt = V4L2_PIX_FMT_RGB24;
else fmt = V4L2_PIX_FMT_BGR24;
break;
150 case CV_8UC2: fmt = V4L2_PIX_FMT_YUYV;
break;
151 case CV_8UC1: fmt = V4L2_PIX_FMT_GREY;
break;
152 default:
LFATAL(
"Unsupported OpenCV image format: " << img.type());
155 setInternal(img.cols, img.rows, fmt, img.data);
158 #ifdef JEVOIS_PLATFORM_PRO
163 int const dmafd = img.
buf->dmaFd();
166 if ((img.
width % 32) || dmafd < 0) { set(img);
return; }
171 case V4L2_PIX_FMT_YUYV:
172 case V4L2_PIX_FMT_RGB32:
173 case V4L2_PIX_FMT_RGB565:
174 case V4L2_PIX_FMT_BGR24:
175 case V4L2_PIX_FMT_RGB24:
176 case V4L2_PIX_FMT_UYVY:
177 setWithDmaBuf(img, dmafd, display);
189 int const dmafd = img.
buf->dmaFd();
192 if ((img.
width % 32) || dmafd < 0) { set(img);
return; }
197 case V4L2_PIX_FMT_YUYV:
198 case V4L2_PIX_FMT_RGB32:
199 case V4L2_PIX_FMT_RGB565:
200 case V4L2_PIX_FMT_BGR24:
201 case V4L2_PIX_FMT_RGB24:
202 case V4L2_PIX_FMT_UYVY:
203 setWithDmaBuf(img, dmafd, display);
214 if (img.
width == 0 || img.
height == 0)
LFATAL(
"Cannot handle zero image width or height");
217 if (img.
width != itsTextureWidth || img.
height != itsTextureHeight || img.
fmt != itsFormat ||
218 itsTexture || !itsTextureDmaBuf)
225 itsTextureWidth = img.
width; itsTextureHeight = img.
height;
232 itsLocation = glGetUniformLocation(itsProgram->id(),
"s_texture");
241 #else // JEVOIS_PLATFORM_PRO
259 #endif // JEVOIS_PLATFORM_PRO
263 glm::mat4
const & pvm)
265 if (itsTextureWidth == 0)
throw std::runtime_error(
"You must call set() before draw()");
269 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
273 glGetIntegerv(GL_VIEWPORT, viewport);
275 if (w == 0 ||
h == 0)
278 unsigned int winw = viewport[2], winh = viewport[3];
279 itsDrawWidth = itsTextureWidth; itsDrawHeight = itsTextureHeight;
281 x = (winw - itsDrawWidth) / 2; y = (winh - itsDrawHeight) / 2; w = itsDrawWidth;
h = itsDrawHeight;
286 int const yy = viewport[3] - y -
h;
289 if (itsDrawX != x || itsDrawY != y || itsDrawWidth != w || itsDrawHeight !=
h)
294 float const tx = x - 0.5 * viewport[2];
295 float const ty = yy - 0.5 * viewport[3];
296 float const bx = tx + w;
297 float const by = ty +
h;
302 GLfloat
const vertices[] = { tx, by, 0.0f, 0.0f, 0.0f,
303 tx, ty, 0.0f, 0.0f, 1.0f,
304 bx, ty, 0.0f, 1.0f, 1.0f,
305 bx, by, 0.0f, 1.0f, 0.0f };
306 static GLushort
const indices[] = { 0, 1, 2, 0, 2, 3 };
308 if (itsVertexArray) { glDeleteVertexArrays(1, &itsVertexArray); glDeleteBuffers(2, itsVertexBuffers); }
309 glGenVertexArrays(1, &itsVertexArray);
312 glBindVertexArray(itsVertexArray);
315 if (itsVertexBuffers[0]) glDeleteBuffers(2, itsVertexBuffers);
316 glGenBuffers(2, itsVertexBuffers);
319 glBindBuffer(GL_ARRAY_BUFFER, itsVertexBuffers[0]);
320 glBufferData(GL_ARRAY_BUFFER,
sizeof(vertices), vertices, GL_STATIC_DRAW);
323 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, itsVertexBuffers[1]);
324 glBufferData(GL_ELEMENT_ARRAY_BUFFER,
sizeof(indices), indices, GL_STATIC_DRAW);
327 glEnableVertexAttribArray(0);
328 glEnableVertexAttribArray(1);
331 GL_CHECK(glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 *
sizeof(GLfloat), 0));
334 GL_CHECK(glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 *
sizeof(GLfloat), (
void const *)(3 *
sizeof(GLfloat))));
337 glBindVertexArray(0);
340 itsDrawX = x; itsDrawY = y; itsDrawWidth = w; itsDrawHeight =
h;
343 if (!itsProgram)
throw std::runtime_error(
"You must call set() before draw()");
346 glUseProgram(itsProgram->id());
349 glBindVertexArray(itsVertexArray);
352 GL_CHECK(glActiveTexture(GL_TEXTURE0));
354 GL_CHECK(glBindTexture(GL_TEXTURE_2D, itsTexture->Id));
355 #ifdef JEVOIS_PLATFORM_PRO
356 else if (itsTextureDmaBuf)
357 GL_CHECK(glBindTexture(GL_TEXTURE_EXTERNAL_OES, itsTextureDmaBuf->Id));
359 else throw std::runtime_error(
"You must call set() before draw()");
362 glUniform1i(itsLocation, 0);
366 glUniform2f(glGetUniformLocation(itsProgram->id(),
"tdim"), GLfloat(itsTextureWidth), GLfloat(itsTextureHeight));
367 glUniformMatrix4fv(glGetUniformLocation(itsProgram->id(),
"pvm"), 1, GL_FALSE, glm::value_ptr(pvm));
371 glUniform1f(glGetUniformLocation(itsProgram->id(),
"twirlamount"), itsTwirl);
372 glUniform1f(glGetUniformLocation(itsProgram->id(),
"alpha"), itsAlpha);
379 glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, 0);
382 glBindVertexArray(0);
388 if (itsDrawWidth == 0)
throw std::runtime_error(
"Need to call set() then draw() first");
389 return ImVec2(itsDrawX + p.x * itsDrawWidth / itsTextureWidth, itsDrawY + p.y * itsDrawHeight / itsTextureHeight);
395 if (itsDrawWidth == 0)
throw std::runtime_error(
"Need to call set() then draw() first");
396 return ImVec2(p.x * itsDrawWidth / itsTextureWidth, p.y * itsDrawHeight / itsTextureHeight);
402 if (itsDrawWidth == 0)
throw std::runtime_error(
"Need to call set() then draw() first");
403 return ImVec2((p.x - itsDrawX) * itsTextureWidth / itsDrawWidth, (p.y - itsDrawY) * itsTextureHeight / itsDrawHeight);
409 if (itsDrawWidth == 0)
throw std::runtime_error(
"Need to call set() then draw() first");
410 return ImVec2(p.x * itsTextureWidth / itsDrawWidth, p.y * itsTextureHeight / itsDrawHeight);
417 if (itsTwirl == 0.0
F || t == 0.0
F) itsFormat = 0;