1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3 * The YUY2 shader code is based on face-responder. The code is under public domain:
4 * https://bitbucket.org/nateharward/face-responder/src/0c3b4b957039d9f4bf1da09b9471371942de2601/yuv42201_laplace.frag?at=master
5 *
6 * All other OpenGL code:
7 *
8 * Copyright 2018 Cisco Systems, Inc. and/or its affiliates. All rights reserved.
9 */
10
11 #include "capture.h"
12
13 #include <QtCore/QTextStream>
14 #include <QtCore/QCoreApplication>
15 #include <QtGui/QOpenGLContext>
16 #if QT_VERSION < 0x060000
17 #include <QtGui/QOpenGLPaintDevice>
18 #else
19 #include <QOpenGLPaintDevice>
20 #endif
21 #include <QtGui/QContextMenuEvent>
22 #include <QtGui/QKeyEvent>
23 #include <QtGui/QPainter>
24 #include <QtCore/QSocketNotifier>
25 #include <QtMath>
26 #include <QTimer>
27 #include <QApplication>
28
29 #include "v4l2-info.h"
30
initializeGL()31 void CaptureWin::initializeGL()
32 {
33 initializeOpenGLFunctions();
34 glDisable(GL_BLEND);
35 glDisable(GL_DEPTH_TEST);
36
37 // Check if the the GL_FRAMEBUFFER_SRGB feature is available.
38 // If it is, then the GPU can perform the SRGB transfer function
39 // for us.
40 GLint res = 0;
41 if (context()->hasExtension("GL_EXT_framebuffer_sRGB"))
42 glGetIntegerv(GL_FRAMEBUFFER_SRGB_CAPABLE_EXT, &res);
43 checkError("InitializeGL Part 1");
44
45 glPixelStorei(GL_UNPACK_SWAP_BYTES, GL_FALSE);
46 m_haveSwapBytes = glGetError() == GL_NO_ERROR;
47
48 if (m_verbose) {
49 printf("OpenGL %sdoes%s support GL_UNPACK_SWAP_BYTES\n",
50 context()->isOpenGLES() ? "ES " : "",
51 m_haveSwapBytes ? "" : " not");
52 }
53 if (m_uses_gl_red && glGetString(GL_VERSION)[0] < '3') {
54 fprintf(stderr, "The openGL implementation does not support GL_RED/GL_RG\n");
55 std::exit(EXIT_FAILURE);
56 }
57
58 QColor bg = QWidget::palette().color(QWidget::backgroundRole());
59 glClearColor(bg.red() / 255.0f,
60 bg.green() / 255.0f,
61 bg.blue() / 255.0f,
62 0.0f);
63 glClear(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
64 checkError("InitializeGL Part 2");
65 m_program = new QOpenGLShaderProgram(this);
66 m_updateShader = true;
67 }
68
69
paintGL()70 void CaptureWin::paintGL()
71 {
72 if (m_v4l_fmt.g_width() < 16 || m_v4l_fmt.g_frame_height() < 16)
73 return;
74
75 if (m_mode == AppModeV4L2) {
76 if (m_v4l_queue == NULL || m_nextIndex == -1)
77 return;
78
79 cv4l_buffer buf(*m_v4l_queue, m_curIndex);
80
81 m_fd->qbuf(buf);
82 for (unsigned i = 0; i < m_v4l_queue->g_num_planes(); i++) {
83 m_curData[i] = m_nextData[i];
84 m_curSize[i] = m_nextSize[i];
85 m_curIndex = m_nextIndex;
86 m_nextIndex = -1;
87 m_nextData[i] = 0;
88 m_nextSize[i] = 0;
89 }
90 }
91
92
93 if (m_curData[0] == NULL) {
94 // No data, just clear display
95 glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
96 glClear(GL_COLOR_BUFFER_BIT);
97 checkError("paintGL - no data");
98 return;
99 }
100
101 if (m_updateShader) {
102 m_updateShader = false;
103 if (!supportedFmt(m_v4l_fmt.g_pixelformat())) {
104 fprintf(stderr, "OpenGL ES unsupported format 0x%08x ('%s').\n",
105 m_v4l_fmt.g_pixelformat(), fcc2s(m_v4l_fmt.g_pixelformat()).c_str());
106
107 glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
108 glClear(GL_COLOR_BUFFER_BIT);
109 checkError("paintGL - no data");
110 return;
111 }
112
113 changeShader();
114 }
115
116 if (!supportedFmt(m_v4l_fmt.g_pixelformat()))
117 return;
118
119 switch (m_v4l_fmt.g_pixelformat()) {
120 case V4L2_PIX_FMT_YUYV:
121 case V4L2_PIX_FMT_YVYU:
122 case V4L2_PIX_FMT_UYVY:
123 case V4L2_PIX_FMT_VYUY:
124 render_YUY2(m_v4l_fmt.g_pixelformat());
125 break;
126
127 case V4L2_PIX_FMT_NV16:
128 case V4L2_PIX_FMT_NV61:
129 case V4L2_PIX_FMT_NV16M:
130 case V4L2_PIX_FMT_NV61M:
131 render_NV16(m_v4l_fmt.g_pixelformat());
132 break;
133
134 case V4L2_PIX_FMT_NV12:
135 case V4L2_PIX_FMT_NV21:
136 case V4L2_PIX_FMT_NV12M:
137 case V4L2_PIX_FMT_NV21M:
138 render_NV12(m_v4l_fmt.g_pixelformat());
139 break;
140
141 case V4L2_PIX_FMT_NV24:
142 case V4L2_PIX_FMT_NV42:
143 render_NV24(m_v4l_fmt.g_pixelformat());
144 break;
145
146 case V4L2_PIX_FMT_YUV422P:
147 case V4L2_PIX_FMT_YUV420:
148 case V4L2_PIX_FMT_YVU420:
149 case V4L2_PIX_FMT_YUV420M:
150 case V4L2_PIX_FMT_YVU420M:
151 case V4L2_PIX_FMT_YUV422M:
152 case V4L2_PIX_FMT_YVU422M:
153 case V4L2_PIX_FMT_YUV444M:
154 case V4L2_PIX_FMT_YVU444M:
155 render_YUV(m_v4l_fmt.g_pixelformat());
156 break;
157
158 case V4L2_PIX_FMT_YUV444:
159 case V4L2_PIX_FMT_YUV555:
160 case V4L2_PIX_FMT_YUV565:
161 case V4L2_PIX_FMT_YUV32:
162 case V4L2_PIX_FMT_AYUV32:
163 case V4L2_PIX_FMT_XYUV32:
164 case V4L2_PIX_FMT_VUYA32:
165 case V4L2_PIX_FMT_VUYX32:
166 case V4L2_PIX_FMT_YUVA32:
167 case V4L2_PIX_FMT_YUVX32:
168 render_YUV_packed(m_v4l_fmt.g_pixelformat());
169 break;
170
171 case V4L2_PIX_FMT_SBGGR8:
172 case V4L2_PIX_FMT_SGBRG8:
173 case V4L2_PIX_FMT_SGRBG8:
174 case V4L2_PIX_FMT_SRGGB8:
175 case V4L2_PIX_FMT_SBGGR10:
176 case V4L2_PIX_FMT_SGBRG10:
177 case V4L2_PIX_FMT_SGRBG10:
178 case V4L2_PIX_FMT_SRGGB10:
179 case V4L2_PIX_FMT_SBGGR12:
180 case V4L2_PIX_FMT_SGBRG12:
181 case V4L2_PIX_FMT_SGRBG12:
182 case V4L2_PIX_FMT_SRGGB12:
183 case V4L2_PIX_FMT_SBGGR16:
184 case V4L2_PIX_FMT_SGBRG16:
185 case V4L2_PIX_FMT_SGRBG16:
186 case V4L2_PIX_FMT_SRGGB16:
187 render_Bayer(m_v4l_fmt.g_pixelformat());
188 break;
189
190 case V4L2_PIX_FMT_GREY:
191 case V4L2_PIX_FMT_Y10:
192 case V4L2_PIX_FMT_Y12:
193 case V4L2_PIX_FMT_Y16:
194 case V4L2_PIX_FMT_Y16_BE:
195 case V4L2_PIX_FMT_Z16:
196 case V4L2_PIX_FMT_RGB332:
197 case V4L2_PIX_FMT_BGR666:
198 case V4L2_PIX_FMT_RGB555:
199 case V4L2_PIX_FMT_XRGB555:
200 case V4L2_PIX_FMT_ARGB555:
201 case V4L2_PIX_FMT_RGB555X:
202 case V4L2_PIX_FMT_XRGB555X:
203 case V4L2_PIX_FMT_ARGB555X:
204 case V4L2_PIX_FMT_RGBX555:
205 case V4L2_PIX_FMT_RGBA555:
206 case V4L2_PIX_FMT_XBGR555:
207 case V4L2_PIX_FMT_ABGR555:
208 case V4L2_PIX_FMT_BGRX555:
209 case V4L2_PIX_FMT_BGRA555:
210 case V4L2_PIX_FMT_RGB444:
211 case V4L2_PIX_FMT_XRGB444:
212 case V4L2_PIX_FMT_ARGB444:
213 case V4L2_PIX_FMT_XBGR444:
214 case V4L2_PIX_FMT_ABGR444:
215 case V4L2_PIX_FMT_RGBX444:
216 case V4L2_PIX_FMT_RGBA444:
217 case V4L2_PIX_FMT_BGRX444:
218 case V4L2_PIX_FMT_BGRA444:
219 case V4L2_PIX_FMT_RGB565:
220 case V4L2_PIX_FMT_RGB565X:
221 case V4L2_PIX_FMT_RGB24:
222 case V4L2_PIX_FMT_BGR24:
223 case V4L2_PIX_FMT_RGB32:
224 case V4L2_PIX_FMT_BGR32:
225 case V4L2_PIX_FMT_XRGB32:
226 case V4L2_PIX_FMT_XBGR32:
227 case V4L2_PIX_FMT_ARGB32:
228 case V4L2_PIX_FMT_ABGR32:
229 case V4L2_PIX_FMT_RGBX32:
230 case V4L2_PIX_FMT_BGRX32:
231 case V4L2_PIX_FMT_RGBA32:
232 case V4L2_PIX_FMT_BGRA32:
233 case V4L2_PIX_FMT_HSV24:
234 case V4L2_PIX_FMT_HSV32:
235 default:
236 render_RGB(m_v4l_fmt.g_pixelformat());
237 break;
238 }
239
240 static unsigned long long tot_t;
241 static unsigned cnt;
242 GLuint query;
243 QSize s = correctAspect(m_viewSize);
244 bool scale = m_scrollArea->widgetResizable();
245
246 glViewport(scale ? (size().width() - s.width()) / 2 : 0,
247 scale ? (size().height() - s.height()) / 2 : 0,
248 s.width(), s.height());
249
250 if (m_reportTimings) {
251 glGenQueries(1, &query);
252 glBeginQuery(GL_TIME_ELAPSED, query);
253 }
254
255 GLuint VertexArrayID;
256 glGenVertexArrays(1, &VertexArrayID);
257 glBindVertexArray(VertexArrayID);
258
259 // Define Quad surface to draw to, vertices sequenced for GL_TRIANGLE_FAN
260 // Adjusting these will make the screen to draw to smaller or larger
261 const GLfloat quadVertex[] = {
262 -1.0f, -1.0f, // Left Bottom
263 +1.0f, -1.0f, // Right Bottom
264 +1.0f, +1.0f, // Rigth Top
265 -1.0f, +1.0f // Left Top
266 };
267
268 // Normalized texture coords to be aligned to draw quad corners, same sequence but 0,0 is Left Top
269 const GLuint texCoords[] = {
270 0, 1,
271 1, 1,
272 1, 0,
273 0, 0
274 };
275
276 GLuint vertexbuffer;
277 glGenBuffers(1, &vertexbuffer);
278 glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);
279 glBufferData(GL_ARRAY_BUFFER, sizeof(quadVertex), quadVertex, GL_STATIC_DRAW);
280
281 GLuint uvbuffer;
282 glGenBuffers(1, &uvbuffer);
283 glBindBuffer(GL_ARRAY_BUFFER, uvbuffer);
284 glBufferData(GL_ARRAY_BUFFER, sizeof(texCoords), texCoords, GL_STATIC_DRAW);
285
286 // Attach Quad positions to vertex shader "position" attribute (location = 0)
287 glEnableVertexAttribArray(0);
288 glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);
289 glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, (void*)0);
290
291 // Attach texture corner positions to vertex shader "texCoord" attribute (location = 1)
292 glEnableVertexAttribArray(1);
293 glBindBuffer(GL_ARRAY_BUFFER, uvbuffer);
294 glVertexAttribPointer(1, 2, GL_UNSIGNED_INT, GL_FALSE, 0, (void*)0);
295
296 // Draw quad with texture
297 glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
298
299 // Disable attrib arrays
300 glDisableVertexAttribArray(0);
301 glDisableVertexAttribArray(1);
302 glBindBuffer(GL_ARRAY_BUFFER, 0);
303 glDeleteBuffers(1, &vertexbuffer);
304
305 checkError("paintGL");
306
307 if (m_reportTimings) {
308 glEndQuery(GL_TIME_ELAPSED);
309 GLuint t;
310 glGetQueryObjectuiv(query, GL_QUERY_RESULT, &t);
311 glDeleteQueries(1, &query);
312
313 cnt++;
314 tot_t += t;
315 unsigned ave = tot_t / cnt;
316 printf("Average render time: %09u ns, frame %d render time: %09u ns\n",
317 ave, cnt, t);
318 }
319 }
320
321 static const char *prog =
322 #include "v4l2-convert.h"
323 ;
324
325 struct define {
326 const char *name;
327 unsigned id;
328 };
329
330 #define DEF(c) { .name = #c, .id = c }
331
332 static const struct define defines[] = {
333 DEF(V4L2_PIX_FMT_YUYV),
334 DEF(V4L2_PIX_FMT_YVYU),
335 DEF(V4L2_PIX_FMT_UYVY),
336 DEF(V4L2_PIX_FMT_VYUY),
337 DEF(V4L2_PIX_FMT_YUV422P),
338 DEF(V4L2_PIX_FMT_YVU420),
339 DEF(V4L2_PIX_FMT_YUV420),
340 DEF(V4L2_PIX_FMT_NV12),
341 DEF(V4L2_PIX_FMT_NV21),
342 DEF(V4L2_PIX_FMT_NV16),
343 DEF(V4L2_PIX_FMT_NV61),
344 DEF(V4L2_PIX_FMT_NV24),
345 DEF(V4L2_PIX_FMT_NV42),
346 DEF(V4L2_PIX_FMT_NV16M),
347 DEF(V4L2_PIX_FMT_NV61M),
348 DEF(V4L2_PIX_FMT_YVU420M),
349 DEF(V4L2_PIX_FMT_YUV420M),
350 DEF(V4L2_PIX_FMT_YVU422M),
351 DEF(V4L2_PIX_FMT_YUV422M),
352 DEF(V4L2_PIX_FMT_YVU444M),
353 DEF(V4L2_PIX_FMT_YUV444M),
354 DEF(V4L2_PIX_FMT_NV12M),
355 DEF(V4L2_PIX_FMT_NV21M),
356 DEF(V4L2_PIX_FMT_YUV444),
357 DEF(V4L2_PIX_FMT_YUV555),
358 DEF(V4L2_PIX_FMT_YUV565),
359 DEF(V4L2_PIX_FMT_YUV32),
360 DEF(V4L2_PIX_FMT_AYUV32),
361 DEF(V4L2_PIX_FMT_XYUV32),
362 DEF(V4L2_PIX_FMT_VUYA32),
363 DEF(V4L2_PIX_FMT_VUYX32),
364 DEF(V4L2_PIX_FMT_YUVA32),
365 DEF(V4L2_PIX_FMT_YUVX32),
366 DEF(V4L2_PIX_FMT_RGB32),
367 DEF(V4L2_PIX_FMT_XRGB32),
368 DEF(V4L2_PIX_FMT_ARGB32),
369 DEF(V4L2_PIX_FMT_RGBX32),
370 DEF(V4L2_PIX_FMT_RGBA32),
371 DEF(V4L2_PIX_FMT_BGR32),
372 DEF(V4L2_PIX_FMT_XBGR32),
373 DEF(V4L2_PIX_FMT_ABGR32),
374 DEF(V4L2_PIX_FMT_BGRX32),
375 DEF(V4L2_PIX_FMT_BGRA32),
376 DEF(V4L2_PIX_FMT_RGB24),
377 DEF(V4L2_PIX_FMT_BGR24),
378 DEF(V4L2_PIX_FMT_RGB565),
379 DEF(V4L2_PIX_FMT_RGB565X),
380 DEF(V4L2_PIX_FMT_RGB444),
381 DEF(V4L2_PIX_FMT_XRGB444),
382 DEF(V4L2_PIX_FMT_ARGB444),
383 DEF(V4L2_PIX_FMT_XBGR444),
384 DEF(V4L2_PIX_FMT_ABGR444),
385 DEF(V4L2_PIX_FMT_RGBX444),
386 DEF(V4L2_PIX_FMT_RGBA444),
387 DEF(V4L2_PIX_FMT_BGRX444),
388 DEF(V4L2_PIX_FMT_BGRA444),
389 DEF(V4L2_PIX_FMT_RGB555),
390 DEF(V4L2_PIX_FMT_XRGB555),
391 DEF(V4L2_PIX_FMT_ARGB555),
392 DEF(V4L2_PIX_FMT_RGB555X),
393 DEF(V4L2_PIX_FMT_XRGB555X),
394 DEF(V4L2_PIX_FMT_ARGB555X),
395 DEF(V4L2_PIX_FMT_RGBX555),
396 DEF(V4L2_PIX_FMT_RGBA555),
397 DEF(V4L2_PIX_FMT_XBGR555),
398 DEF(V4L2_PIX_FMT_ABGR555),
399 DEF(V4L2_PIX_FMT_BGRX555),
400 DEF(V4L2_PIX_FMT_BGRA555),
401 DEF(V4L2_PIX_FMT_RGB332),
402 DEF(V4L2_PIX_FMT_BGR666),
403 DEF(V4L2_PIX_FMT_SBGGR8),
404 DEF(V4L2_PIX_FMT_SGBRG8),
405 DEF(V4L2_PIX_FMT_SGRBG8),
406 DEF(V4L2_PIX_FMT_SRGGB8),
407 DEF(V4L2_PIX_FMT_SBGGR10),
408 DEF(V4L2_PIX_FMT_SGBRG10),
409 DEF(V4L2_PIX_FMT_SGRBG10),
410 DEF(V4L2_PIX_FMT_SRGGB10),
411 DEF(V4L2_PIX_FMT_SBGGR12),
412 DEF(V4L2_PIX_FMT_SGBRG12),
413 DEF(V4L2_PIX_FMT_SGRBG12),
414 DEF(V4L2_PIX_FMT_SRGGB12),
415 DEF(V4L2_PIX_FMT_SBGGR16),
416 DEF(V4L2_PIX_FMT_SGBRG16),
417 DEF(V4L2_PIX_FMT_SGRBG16),
418 DEF(V4L2_PIX_FMT_SRGGB16),
419 DEF(V4L2_PIX_FMT_HSV24),
420 DEF(V4L2_PIX_FMT_HSV32),
421 DEF(V4L2_PIX_FMT_GREY),
422 DEF(V4L2_PIX_FMT_Y10),
423 DEF(V4L2_PIX_FMT_Y12),
424 DEF(V4L2_PIX_FMT_Y16),
425 DEF(V4L2_PIX_FMT_Y16_BE),
426 DEF(V4L2_PIX_FMT_Z16),
427
428 DEF(V4L2_FIELD_ANY),
429 DEF(V4L2_FIELD_NONE),
430 DEF(V4L2_FIELD_TOP),
431 DEF(V4L2_FIELD_BOTTOM),
432 DEF(V4L2_FIELD_INTERLACED),
433 DEF(V4L2_FIELD_SEQ_TB),
434 DEF(V4L2_FIELD_SEQ_BT),
435 DEF(V4L2_FIELD_ALTERNATE),
436 DEF(V4L2_FIELD_INTERLACED_TB),
437 DEF(V4L2_FIELD_INTERLACED_BT),
438
439 DEF(V4L2_COLORSPACE_DEFAULT),
440 DEF(V4L2_COLORSPACE_SMPTE170M),
441 DEF(V4L2_COLORSPACE_SMPTE240M),
442 DEF(V4L2_COLORSPACE_REC709),
443 DEF(V4L2_COLORSPACE_470_SYSTEM_M),
444 DEF(V4L2_COLORSPACE_470_SYSTEM_BG),
445 DEF(V4L2_COLORSPACE_SRGB),
446 DEF(V4L2_COLORSPACE_OPRGB),
447 DEF(V4L2_COLORSPACE_BT2020),
448 DEF(V4L2_COLORSPACE_RAW),
449 DEF(V4L2_COLORSPACE_DCI_P3),
450
451 DEF(V4L2_XFER_FUNC_DEFAULT),
452 DEF(V4L2_XFER_FUNC_709),
453 DEF(V4L2_XFER_FUNC_SRGB),
454 DEF(V4L2_XFER_FUNC_OPRGB),
455 DEF(V4L2_XFER_FUNC_SMPTE240M),
456 DEF(V4L2_XFER_FUNC_NONE),
457 DEF(V4L2_XFER_FUNC_DCI_P3),
458 DEF(V4L2_XFER_FUNC_SMPTE2084),
459
460 DEF(V4L2_YCBCR_ENC_DEFAULT),
461 DEF(V4L2_YCBCR_ENC_601),
462 DEF(V4L2_YCBCR_ENC_709),
463 DEF(V4L2_YCBCR_ENC_XV601),
464 DEF(V4L2_YCBCR_ENC_XV709),
465 DEF(V4L2_YCBCR_ENC_BT2020),
466 DEF(V4L2_YCBCR_ENC_BT2020_CONST_LUM),
467 DEF(V4L2_YCBCR_ENC_SMPTE240M),
468 DEF(V4L2_HSV_ENC_180),
469 DEF(V4L2_HSV_ENC_256),
470
471 DEF(V4L2_QUANTIZATION_DEFAULT),
472 DEF(V4L2_QUANTIZATION_FULL_RANGE),
473 DEF(V4L2_QUANTIZATION_LIM_RANGE),
474 { NULL, 0 }
475 };
476
changeShader()477 void CaptureWin::changeShader()
478 {
479 if (m_screenTextureCount)
480 glDeleteTextures(m_screenTextureCount, m_screenTexture);
481 m_program->removeAllShaders();
482 checkError("Render settings.\n");
483
484 QString code;
485
486 if (context()->isOpenGLES())
487 code = "#version 300 es\n"
488 "precision mediump float;\n";
489 else
490 code = "#version 330\n";
491 code += QString(
492 "const float tex_w = %1.0;\n"
493 "const float tex_h = %2.0;\n"
494 "#define FIELD %3\n"
495 "#define IS_RGB %4\n"
496 "#define PIXFMT %5u\n"
497 "#define COLSP %6\n"
498 "#define XFERFUNC %7\n"
499 "#define YCBCRENC %8\n"
500 "#define QUANT %9\n\n"
501 "#define IS_HSV %10\n"
502 "#define HSVENC %11\n")
503 .arg(m_v4l_fmt.g_width())
504 .arg(m_v4l_fmt.g_height())
505 .arg(m_v4l_fmt.g_field())
506 .arg(m_is_rgb)
507 .arg(m_v4l_fmt.g_pixelformat())
508 .arg(m_v4l_fmt.g_colorspace())
509 .arg(m_accepts_srgb ? V4L2_XFER_FUNC_NONE : m_v4l_fmt.g_xfer_func())
510 .arg(m_v4l_fmt.g_ycbcr_enc())
511 .arg(m_v4l_fmt.g_quantization())
512 .arg(m_is_hsv)
513 .arg(m_v4l_fmt.g_hsv_enc());
514
515 for (unsigned i = 0; defines[i].name; i++)
516 code += QString("#define ") + defines[i].name + " " + QString("%1").arg(defines[i].id) + "u\n";
517 code += "#line 1\n";
518
519 code += prog;
520
521 bool src_ok = m_program->addShaderFromSourceCode(
522 QOpenGLShader::Fragment, code);
523
524 if (!src_ok) {
525 fprintf(stderr, "OpenGL Error: fragment shader compilation failed.\n");
526 std::exit(EXIT_FAILURE);
527 }
528
529 // Mandatory vertex shader replaces fixed pipeline in GLES 2.0. In this case just a feedthrough shader.
530 QString vertexShaderSrc;
531
532 if (context()->isOpenGLES())
533 vertexShaderSrc = "#version 300 es\n"
534 "precision mediump float;\n";
535 else
536 vertexShaderSrc = "#version 330\n";
537
538 vertexShaderSrc +=
539 "layout(location = 0) in vec2 position;\n"
540 "layout(location = 1) in vec2 texCoord;\n"
541 "out vec2 vs_TexCoord;\n"
542 "void main() {\n"
543 " gl_Position = vec4(position, 0.0, 1.0);\n"
544 " vs_TexCoord = texCoord;\n"
545 "}\n";
546
547 src_ok = m_program->addShaderFromSourceCode(
548 QOpenGLShader::Vertex, vertexShaderSrc);
549
550 if (!src_ok) {
551 fprintf(stderr, "OpenGL Error: vertex shader compilation failed.\n");
552 std::exit(EXIT_FAILURE);
553 }
554
555 if (!m_program->bind()) {
556 fprintf(stderr, "OpenGL Error: shader bind failed.\n");
557 std::exit(EXIT_FAILURE);
558 }
559
560 GLint loc = m_program->uniformLocation("uvtex");
561
562 if (loc >= 0)
563 m_program->setUniformValue(loc, 1);
564 loc = m_program->uniformLocation("utex");
565 if (loc >= 0)
566 m_program->setUniformValue(loc, 1);
567 loc = m_program->uniformLocation("vtex");
568 if (loc >= 0)
569 m_program->setUniformValue(loc, 2);
570
571 switch (m_v4l_fmt.g_pixelformat()) {
572 case V4L2_PIX_FMT_YUYV:
573 case V4L2_PIX_FMT_YVYU:
574 case V4L2_PIX_FMT_UYVY:
575 case V4L2_PIX_FMT_VYUY:
576 shader_YUY2();
577 break;
578
579 case V4L2_PIX_FMT_NV16:
580 case V4L2_PIX_FMT_NV61:
581 case V4L2_PIX_FMT_NV16M:
582 case V4L2_PIX_FMT_NV61M:
583 shader_NV16();
584 break;
585
586 case V4L2_PIX_FMT_NV12:
587 case V4L2_PIX_FMT_NV21:
588 case V4L2_PIX_FMT_NV12M:
589 case V4L2_PIX_FMT_NV21M:
590 shader_NV12();
591 break;
592
593 case V4L2_PIX_FMT_NV24:
594 case V4L2_PIX_FMT_NV42:
595 shader_NV24();
596 break;
597
598 case V4L2_PIX_FMT_YUV444:
599 case V4L2_PIX_FMT_YUV555:
600 case V4L2_PIX_FMT_YUV565:
601 case V4L2_PIX_FMT_YUV32:
602 case V4L2_PIX_FMT_AYUV32:
603 case V4L2_PIX_FMT_XYUV32:
604 case V4L2_PIX_FMT_VUYA32:
605 case V4L2_PIX_FMT_VUYX32:
606 case V4L2_PIX_FMT_YUVA32:
607 case V4L2_PIX_FMT_YUVX32:
608 shader_YUV_packed();
609 break;
610
611 case V4L2_PIX_FMT_YUV422P:
612 case V4L2_PIX_FMT_YUV420:
613 case V4L2_PIX_FMT_YVU420:
614 case V4L2_PIX_FMT_YUV420M:
615 case V4L2_PIX_FMT_YVU420M:
616 case V4L2_PIX_FMT_YUV422M:
617 case V4L2_PIX_FMT_YVU422M:
618 case V4L2_PIX_FMT_YUV444M:
619 case V4L2_PIX_FMT_YVU444M:
620 shader_YUV();
621 break;
622
623 case V4L2_PIX_FMT_SBGGR8:
624 case V4L2_PIX_FMT_SGBRG8:
625 case V4L2_PIX_FMT_SGRBG8:
626 case V4L2_PIX_FMT_SRGGB8:
627 case V4L2_PIX_FMT_SBGGR10:
628 case V4L2_PIX_FMT_SGBRG10:
629 case V4L2_PIX_FMT_SGRBG10:
630 case V4L2_PIX_FMT_SRGGB10:
631 case V4L2_PIX_FMT_SBGGR12:
632 case V4L2_PIX_FMT_SGBRG12:
633 case V4L2_PIX_FMT_SGRBG12:
634 case V4L2_PIX_FMT_SRGGB12:
635 case V4L2_PIX_FMT_SBGGR16:
636 case V4L2_PIX_FMT_SGBRG16:
637 case V4L2_PIX_FMT_SGRBG16:
638 case V4L2_PIX_FMT_SRGGB16:
639 shader_Bayer();
640 break;
641
642 case V4L2_PIX_FMT_RGB332:
643 case V4L2_PIX_FMT_BGR666:
644 case V4L2_PIX_FMT_RGB444:
645 case V4L2_PIX_FMT_XRGB444:
646 case V4L2_PIX_FMT_ARGB444:
647 case V4L2_PIX_FMT_XBGR444:
648 case V4L2_PIX_FMT_ABGR444:
649 case V4L2_PIX_FMT_RGBX444:
650 case V4L2_PIX_FMT_RGBA444:
651 case V4L2_PIX_FMT_BGRX444:
652 case V4L2_PIX_FMT_BGRA444:
653 case V4L2_PIX_FMT_RGB555:
654 case V4L2_PIX_FMT_XRGB555:
655 case V4L2_PIX_FMT_ARGB555:
656 case V4L2_PIX_FMT_RGB555X:
657 case V4L2_PIX_FMT_XRGB555X:
658 case V4L2_PIX_FMT_ARGB555X:
659 case V4L2_PIX_FMT_RGBX555:
660 case V4L2_PIX_FMT_RGBA555:
661 case V4L2_PIX_FMT_XBGR555:
662 case V4L2_PIX_FMT_ABGR555:
663 case V4L2_PIX_FMT_BGRX555:
664 case V4L2_PIX_FMT_BGRA555:
665 case V4L2_PIX_FMT_RGB565:
666 case V4L2_PIX_FMT_RGB565X:
667 case V4L2_PIX_FMT_RGB24:
668 case V4L2_PIX_FMT_BGR24:
669 case V4L2_PIX_FMT_RGB32:
670 case V4L2_PIX_FMT_BGR32:
671 case V4L2_PIX_FMT_XRGB32:
672 case V4L2_PIX_FMT_XBGR32:
673 case V4L2_PIX_FMT_ARGB32:
674 case V4L2_PIX_FMT_ABGR32:
675 case V4L2_PIX_FMT_RGBX32:
676 case V4L2_PIX_FMT_BGRX32:
677 case V4L2_PIX_FMT_RGBA32:
678 case V4L2_PIX_FMT_BGRA32:
679 case V4L2_PIX_FMT_GREY:
680 case V4L2_PIX_FMT_Y10:
681 case V4L2_PIX_FMT_Y12:
682 case V4L2_PIX_FMT_Y16:
683 case V4L2_PIX_FMT_Y16_BE:
684 case V4L2_PIX_FMT_Z16:
685 case V4L2_PIX_FMT_HSV24:
686 case V4L2_PIX_FMT_HSV32:
687 default:
688 shader_RGB();
689 break;
690 }
691 }
692
shader_YUV()693 void CaptureWin::shader_YUV()
694 {
695 unsigned vdiv = 2, hdiv = 2;
696
697 switch (m_v4l_fmt.g_pixelformat()) {
698 case V4L2_PIX_FMT_YUV422P:
699 case V4L2_PIX_FMT_YUV422M:
700 case V4L2_PIX_FMT_YVU422M:
701 vdiv = 1;
702 break;
703 case V4L2_PIX_FMT_YUV444M:
704 case V4L2_PIX_FMT_YVU444M:
705 vdiv = hdiv = 1;
706 break;
707 }
708
709 m_screenTextureCount = 3;
710 glGenTextures(m_screenTextureCount, m_screenTexture);
711
712 glActiveTexture(GL_TEXTURE0);
713 configureTexture(0);
714 glTexImage2D(GL_TEXTURE_2D, 0, GL_R8, m_v4l_fmt.g_width(), m_v4l_fmt.g_height(), 0,
715 GL_RED, GL_UNSIGNED_BYTE, NULL);
716 checkError("YUV shader texture 0");
717
718 glActiveTexture(GL_TEXTURE1);
719 configureTexture(1);
720 glTexImage2D(GL_TEXTURE_2D, 0, GL_R8, m_v4l_fmt.g_width() / hdiv, m_v4l_fmt.g_height() / vdiv, 0,
721 GL_RED, GL_UNSIGNED_BYTE, NULL);
722 checkError("YUV shader texture 1");
723
724 glActiveTexture(GL_TEXTURE2);
725 configureTexture(2);
726 glTexImage2D(GL_TEXTURE_2D, 0, GL_R8, m_v4l_fmt.g_width() / hdiv, m_v4l_fmt.g_height() / vdiv, 0,
727 GL_RED, GL_UNSIGNED_BYTE, NULL);
728 checkError("YUV shader texture 2");
729 }
730
shader_NV12()731 void CaptureWin::shader_NV12()
732 {
733 m_screenTextureCount = 2;
734 glGenTextures(m_screenTextureCount, m_screenTexture);
735
736 glActiveTexture(GL_TEXTURE0);
737 configureTexture(0);
738 glTexImage2D(GL_TEXTURE_2D, 0, GL_R8, m_v4l_fmt.g_width(), m_v4l_fmt.g_height(), 0,
739 GL_RED, GL_UNSIGNED_BYTE, NULL);
740 checkError("NV12 shader texture 0");
741
742 glActiveTexture(GL_TEXTURE1);
743 configureTexture(1);
744 glTexImage2D(GL_TEXTURE_2D, 0, GL_R8, m_v4l_fmt.g_width(), m_v4l_fmt.g_height() / 2, 0,
745 GL_RED, GL_UNSIGNED_BYTE, NULL);
746 checkError("NV12 shader texture 1");
747 }
748
shader_NV24()749 void CaptureWin::shader_NV24()
750 {
751 m_screenTextureCount = 2;
752 glGenTextures(m_screenTextureCount, m_screenTexture);
753
754 glActiveTexture(GL_TEXTURE0);
755 configureTexture(0);
756 glTexImage2D(GL_TEXTURE_2D, 0, GL_R8, m_v4l_fmt.g_width(), m_v4l_fmt.g_height(), 0,
757 GL_RED, GL_UNSIGNED_BYTE, NULL);
758 checkError("NV24 shader texture 0");
759
760 glActiveTexture(GL_TEXTURE1);
761 configureTexture(1);
762 glTexImage2D(GL_TEXTURE_2D, 0, GL_RG8, m_v4l_fmt.g_width(), m_v4l_fmt.g_height(), 0,
763 GL_RG, GL_UNSIGNED_BYTE, NULL);
764 checkError("NV24 shader texture 1");
765 }
766
shader_NV16()767 void CaptureWin::shader_NV16()
768 {
769 m_screenTextureCount = 2;
770 glGenTextures(m_screenTextureCount, m_screenTexture);
771
772 glActiveTexture(GL_TEXTURE0);
773 configureTexture(0);
774 glTexImage2D(GL_TEXTURE_2D, 0, GL_R8, m_v4l_fmt.g_width(), m_v4l_fmt.g_height(), 0,
775 GL_RED, GL_UNSIGNED_BYTE, NULL);
776 checkError("NV16 shader texture 0");
777
778 glActiveTexture(GL_TEXTURE1);
779 configureTexture(1);
780 glTexImage2D(GL_TEXTURE_2D, 0, GL_R8, m_v4l_fmt.g_width(), m_v4l_fmt.g_height(), 0,
781 GL_RED, GL_UNSIGNED_BYTE, NULL);
782 checkError("NV16 shader texture 1");
783 }
784
shader_YUY2()785 void CaptureWin::shader_YUY2()
786 {
787 m_screenTextureCount = 1;
788 glGenTextures(m_screenTextureCount, m_screenTexture);
789 configureTexture(0);
790 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, m_v4l_fmt.g_width() / 2, m_v4l_fmt.g_height(), 0,
791 GL_RGBA, GL_UNSIGNED_BYTE, NULL);
792
793 checkError("YUY2 shader");
794 }
795
shader_RGB()796 void CaptureWin::shader_RGB()
797 {
798 m_screenTextureCount = 1;
799 glGenTextures(m_screenTextureCount, m_screenTexture);
800 glActiveTexture(GL_TEXTURE0);
801 configureTexture(0);
802
803 GLint internalFmt = m_accepts_srgb ? GL_SRGB8_ALPHA8 : GL_RGBA8;
804
805 switch (m_v4l_fmt.g_pixelformat()) {
806 case V4L2_PIX_FMT_RGB555:
807 case V4L2_PIX_FMT_XRGB555:
808 case V4L2_PIX_FMT_ARGB555:
809 glTexImage2D(GL_TEXTURE_2D, 0, internalFmt, m_v4l_fmt.g_width(), m_v4l_fmt.g_height(), 0,
810 GL_BGRA, GL_UNSIGNED_SHORT_1_5_5_5_REV, NULL);
811 break;
812
813 case V4L2_PIX_FMT_RGB444:
814 case V4L2_PIX_FMT_ARGB444:
815 case V4L2_PIX_FMT_XRGB444:
816 case V4L2_PIX_FMT_ABGR444:
817 case V4L2_PIX_FMT_XBGR444:
818 case V4L2_PIX_FMT_RGBA444:
819 case V4L2_PIX_FMT_RGBX444:
820 case V4L2_PIX_FMT_BGRA444:
821 case V4L2_PIX_FMT_BGRX444:
822 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA4, m_v4l_fmt.g_width(), m_v4l_fmt.g_height(), 0,
823 GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4, NULL);
824 break;
825
826 case V4L2_PIX_FMT_RGB555X:
827 case V4L2_PIX_FMT_XRGB555X:
828 case V4L2_PIX_FMT_ARGB555X:
829 case V4L2_PIX_FMT_XBGR555:
830 case V4L2_PIX_FMT_ABGR555:
831 glTexImage2D(GL_TEXTURE_2D, 0, internalFmt, m_v4l_fmt.g_width(), m_v4l_fmt.g_height(), 0,
832 GL_BGRA, GL_UNSIGNED_SHORT_1_5_5_5_REV, NULL);
833 break;
834
835 case V4L2_PIX_FMT_RGBX555:
836 case V4L2_PIX_FMT_RGBA555:
837 case V4L2_PIX_FMT_BGRX555:
838 case V4L2_PIX_FMT_BGRA555:
839 glTexImage2D(GL_TEXTURE_2D, 0, internalFmt, m_v4l_fmt.g_width(), m_v4l_fmt.g_height(), 0,
840 GL_BGRA, GL_UNSIGNED_SHORT_5_5_5_1, NULL);
841 break;
842
843 case V4L2_PIX_FMT_BGR666:
844 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, m_v4l_fmt.g_width(), m_v4l_fmt.g_height(), 0,
845 GL_RGBA, GL_UNSIGNED_INT_8_8_8_8, NULL);
846 break;
847
848 case V4L2_PIX_FMT_RGB332:
849 glTexImage2D(GL_TEXTURE_2D, 0, internalFmt, m_v4l_fmt.g_width(), m_v4l_fmt.g_height(), 0,
850 GL_RGB, GL_UNSIGNED_BYTE_3_3_2, NULL);
851 break;
852
853 case V4L2_PIX_FMT_RGB565:
854 case V4L2_PIX_FMT_RGB565X:
855 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB565, m_v4l_fmt.g_width(), m_v4l_fmt.g_height(), 0,
856 GL_RGB, GL_UNSIGNED_SHORT_5_6_5, NULL);
857 break;
858 case V4L2_PIX_FMT_RGB32:
859 case V4L2_PIX_FMT_ARGB32:
860 case V4L2_PIX_FMT_XRGB32:
861 case V4L2_PIX_FMT_RGBA32:
862 case V4L2_PIX_FMT_RGBX32:
863 case V4L2_PIX_FMT_HSV32:
864 case V4L2_PIX_FMT_BGR32:
865 case V4L2_PIX_FMT_ABGR32:
866 case V4L2_PIX_FMT_XBGR32:
867 case V4L2_PIX_FMT_BGRA32:
868 case V4L2_PIX_FMT_BGRX32:
869 glTexImage2D(GL_TEXTURE_2D, 0, internalFmt, m_v4l_fmt.g_width(), m_v4l_fmt.g_height(), 0,
870 GL_RGBA, GL_UNSIGNED_BYTE, NULL);
871 break;
872 case V4L2_PIX_FMT_GREY:
873 glTexImage2D(GL_TEXTURE_2D, 0, GL_R8UI, m_v4l_fmt.g_width(), m_v4l_fmt.g_height(), 0,
874 GL_RED_INTEGER, GL_UNSIGNED_BYTE, NULL);
875 break;
876 case V4L2_PIX_FMT_Y10:
877 case V4L2_PIX_FMT_Y12:
878 case V4L2_PIX_FMT_Y16:
879 case V4L2_PIX_FMT_Y16_BE:
880 case V4L2_PIX_FMT_Z16:
881 glTexImage2D(GL_TEXTURE_2D, 0, GL_R16UI, m_v4l_fmt.g_width(), m_v4l_fmt.g_height(), 0,
882 GL_RED_INTEGER, GL_UNSIGNED_SHORT, NULL);
883 break;
884 case V4L2_PIX_FMT_RGB24:
885 case V4L2_PIX_FMT_BGR24:
886 case V4L2_PIX_FMT_HSV24:
887 default:
888 glTexImage2D(GL_TEXTURE_2D, 0, m_accepts_srgb ? GL_SRGB8 : GL_RGB8, m_v4l_fmt.g_width(), m_v4l_fmt.g_height(), 0,
889 GL_RGB, GL_UNSIGNED_BYTE, NULL);
890 break;
891 }
892
893 checkError("RGB shader");
894 }
895
shader_Bayer()896 void CaptureWin::shader_Bayer()
897 {
898 m_screenTextureCount = 1;
899 glGenTextures(m_screenTextureCount, m_screenTexture);
900 glActiveTexture(GL_TEXTURE0);
901 configureTexture(0);
902
903 switch (m_v4l_fmt.g_pixelformat()) {
904 case V4L2_PIX_FMT_SBGGR8:
905 case V4L2_PIX_FMT_SGBRG8:
906 case V4L2_PIX_FMT_SGRBG8:
907 case V4L2_PIX_FMT_SRGGB8:
908 glTexImage2D(GL_TEXTURE_2D, 0, GL_R8UI, m_v4l_fmt.g_width(), m_v4l_fmt.g_height(), 0,
909 GL_RED_INTEGER, GL_UNSIGNED_BYTE, NULL);
910 break;
911 case V4L2_PIX_FMT_SBGGR10:
912 case V4L2_PIX_FMT_SGBRG10:
913 case V4L2_PIX_FMT_SGRBG10:
914 case V4L2_PIX_FMT_SRGGB10:
915 case V4L2_PIX_FMT_SBGGR12:
916 case V4L2_PIX_FMT_SGBRG12:
917 case V4L2_PIX_FMT_SGRBG12:
918 case V4L2_PIX_FMT_SRGGB12:
919 case V4L2_PIX_FMT_SBGGR16:
920 case V4L2_PIX_FMT_SGBRG16:
921 case V4L2_PIX_FMT_SGRBG16:
922 case V4L2_PIX_FMT_SRGGB16:
923 glTexImage2D(GL_TEXTURE_2D, 0, GL_R16UI, m_v4l_fmt.g_width(), m_v4l_fmt.g_height(), 0,
924 GL_RED_INTEGER, GL_UNSIGNED_SHORT, NULL);
925 break;
926 }
927
928 checkError("Bayer shader");
929 }
930
shader_YUV_packed()931 void CaptureWin::shader_YUV_packed()
932 {
933 m_screenTextureCount = 1;
934 glGenTextures(m_screenTextureCount, m_screenTexture);
935 glActiveTexture(GL_TEXTURE0);
936 configureTexture(0);
937
938 switch (m_v4l_fmt.g_pixelformat()) {
939 case V4L2_PIX_FMT_YUV555:
940 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, m_v4l_fmt.g_width(), m_v4l_fmt.g_height(), 0,
941 GL_BGRA, GL_UNSIGNED_SHORT_1_5_5_5_REV, NULL);
942 break;
943
944 case V4L2_PIX_FMT_YUV444:
945 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA4, m_v4l_fmt.g_width(), m_v4l_fmt.g_height(), 0,
946 GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4, NULL);
947 break;
948
949 case V4L2_PIX_FMT_YUV565:
950 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB565, m_v4l_fmt.g_width(), m_v4l_fmt.g_height(), 0,
951 GL_RGB, GL_UNSIGNED_SHORT_5_6_5, NULL);
952 break;
953 case V4L2_PIX_FMT_YUV32:
954 case V4L2_PIX_FMT_AYUV32:
955 case V4L2_PIX_FMT_XYUV32:
956 case V4L2_PIX_FMT_VUYA32:
957 case V4L2_PIX_FMT_VUYX32:
958 case V4L2_PIX_FMT_YUVA32:
959 case V4L2_PIX_FMT_YUVX32:
960 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, m_v4l_fmt.g_width(), m_v4l_fmt.g_height(), 0,
961 GL_RGBA, GL_UNSIGNED_BYTE, NULL);
962 break;
963 }
964
965 checkError("Packed YUV shader");
966 }
967
render_YUV(__u32 format)968 void CaptureWin::render_YUV(__u32 format)
969 {
970 unsigned vdiv = 2, hdiv = 2;
971 int idxU = 0;
972 int idxV = 0;
973
974 switch (format) {
975 case V4L2_PIX_FMT_YUV444M:
976 case V4L2_PIX_FMT_YVU444M:
977 vdiv = hdiv = 1;
978 break;
979 case V4L2_PIX_FMT_YUV422P:
980 idxU = m_v4l_fmt.g_width() * m_v4l_fmt.g_height();
981 idxV = idxU + (idxU / 2);
982 vdiv = 1;
983 break;
984 case V4L2_PIX_FMT_YUV422M:
985 case V4L2_PIX_FMT_YVU422M:
986 vdiv = 1;
987 break;
988 case V4L2_PIX_FMT_YUV420:
989 idxU = m_v4l_fmt.g_width() * m_v4l_fmt.g_height();
990 idxV = idxU + (idxU / 4);
991 break;
992 case V4L2_PIX_FMT_YVU420:
993 idxV = m_v4l_fmt.g_width() * m_v4l_fmt.g_height();
994 idxU = idxV + (idxV / 4);
995 break;
996 }
997
998 glActiveTexture(GL_TEXTURE0);
999 glBindTexture(GL_TEXTURE_2D, m_screenTexture[0]);
1000 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, m_v4l_fmt.g_width(), m_v4l_fmt.g_height(),
1001 GL_RED, GL_UNSIGNED_BYTE, m_curData[0]);
1002 checkError("YUV paint ytex");
1003
1004 glActiveTexture(GL_TEXTURE1);
1005 glBindTexture(GL_TEXTURE_2D, m_screenTexture[1]);
1006 switch (format) {
1007 case V4L2_PIX_FMT_YUV422P:
1008 case V4L2_PIX_FMT_YUV420:
1009 case V4L2_PIX_FMT_YVU420:
1010 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, m_v4l_fmt.g_width() / hdiv, m_v4l_fmt.g_height() / vdiv,
1011 GL_RED, GL_UNSIGNED_BYTE, m_curData[0] == NULL ? NULL : &m_curData[0][idxU]);
1012 break;
1013 case V4L2_PIX_FMT_YUV420M:
1014 case V4L2_PIX_FMT_YUV422M:
1015 case V4L2_PIX_FMT_YUV444M:
1016 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, m_v4l_fmt.g_width() / hdiv, m_v4l_fmt.g_height() / vdiv,
1017 GL_RED, GL_UNSIGNED_BYTE, m_curData[1]);
1018 break;
1019 case V4L2_PIX_FMT_YVU420M:
1020 case V4L2_PIX_FMT_YVU422M:
1021 case V4L2_PIX_FMT_YVU444M:
1022 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, m_v4l_fmt.g_width() / hdiv, m_v4l_fmt.g_height() / vdiv,
1023 GL_RED, GL_UNSIGNED_BYTE, m_curData[2]);
1024 break;
1025 }
1026 checkError("YUV paint utex");
1027
1028 glActiveTexture(GL_TEXTURE2);
1029 glBindTexture(GL_TEXTURE_2D, m_screenTexture[2]);
1030 switch (format) {
1031 case V4L2_PIX_FMT_YUV422P:
1032 case V4L2_PIX_FMT_YUV420:
1033 case V4L2_PIX_FMT_YVU420:
1034 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, m_v4l_fmt.g_width() / hdiv, m_v4l_fmt.g_height() / vdiv,
1035 GL_RED, GL_UNSIGNED_BYTE, m_curData[0] == NULL ? NULL : &m_curData[0][idxV]);
1036 break;
1037 case V4L2_PIX_FMT_YUV420M:
1038 case V4L2_PIX_FMT_YUV422M:
1039 case V4L2_PIX_FMT_YUV444M:
1040 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, m_v4l_fmt.g_width() / hdiv, m_v4l_fmt.g_height() / vdiv,
1041 GL_RED, GL_UNSIGNED_BYTE, m_curData[2]);
1042 break;
1043 case V4L2_PIX_FMT_YVU420M:
1044 case V4L2_PIX_FMT_YVU422M:
1045 case V4L2_PIX_FMT_YVU444M:
1046 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, m_v4l_fmt.g_width() / hdiv, m_v4l_fmt.g_height() / vdiv,
1047 GL_RED, GL_UNSIGNED_BYTE, m_curData[1]);
1048 break;
1049 }
1050 checkError("YUV paint vtex");
1051 }
1052
render_NV12(__u32 format)1053 void CaptureWin::render_NV12(__u32 format)
1054 {
1055 glActiveTexture(GL_TEXTURE0);
1056 glBindTexture(GL_TEXTURE_2D, m_screenTexture[0]);
1057 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, m_v4l_fmt.g_width(), m_v4l_fmt.g_height(),
1058 GL_RED, GL_UNSIGNED_BYTE, m_curData[0]);
1059 checkError("NV12 paint ytex");
1060
1061 glActiveTexture(GL_TEXTURE1);
1062 glBindTexture(GL_TEXTURE_2D, m_screenTexture[1]);
1063 switch (format) {
1064 case V4L2_PIX_FMT_NV12:
1065 case V4L2_PIX_FMT_NV21:
1066 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, m_v4l_fmt.g_width(), m_v4l_fmt.g_height() / 2,
1067 GL_RED, GL_UNSIGNED_BYTE,
1068 m_curData[0] ? m_curData[0] + m_v4l_fmt.g_width() * m_v4l_fmt.g_height() : NULL);
1069 break;
1070 case V4L2_PIX_FMT_NV12M:
1071 case V4L2_PIX_FMT_NV21M:
1072 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, m_v4l_fmt.g_width(), m_v4l_fmt.g_height() / 2,
1073 GL_RED, GL_UNSIGNED_BYTE, m_curData[1]);
1074 break;
1075 }
1076 checkError("NV12 paint uvtex");
1077 }
1078
render_NV24(__u32 format)1079 void CaptureWin::render_NV24(__u32 format)
1080 {
1081 glActiveTexture(GL_TEXTURE0);
1082 glBindTexture(GL_TEXTURE_2D, m_screenTexture[0]);
1083 glPixelStorei(GL_UNPACK_ROW_LENGTH, m_v4l_fmt.g_bytesperline());
1084 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, m_v4l_fmt.g_width(), m_v4l_fmt.g_height(),
1085 GL_RED, GL_UNSIGNED_BYTE, m_curData[0]);
1086 checkError("NV24 paint ytex");
1087
1088 glActiveTexture(GL_TEXTURE1);
1089 glBindTexture(GL_TEXTURE_2D, m_screenTexture[1]);
1090 glPixelStorei(GL_UNPACK_ROW_LENGTH, m_v4l_fmt.g_bytesperline());
1091 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, m_v4l_fmt.g_width(), m_v4l_fmt.g_height(),
1092 GL_RG, GL_UNSIGNED_BYTE,
1093 m_curData[0] ? m_curData[0] + m_v4l_fmt.g_sizeimage() / 3 : NULL);
1094 checkError("NV24 paint uvtex");
1095 }
1096
render_NV16(__u32 format)1097 void CaptureWin::render_NV16(__u32 format)
1098 {
1099 glActiveTexture(GL_TEXTURE0);
1100 glBindTexture(GL_TEXTURE_2D, m_screenTexture[0]);
1101 glPixelStorei(GL_UNPACK_ROW_LENGTH, m_v4l_fmt.g_bytesperline());
1102 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, m_v4l_fmt.g_width(), m_v4l_fmt.g_height(),
1103 GL_RED, GL_UNSIGNED_BYTE, m_curData[0]);
1104 checkError("NV16 paint ytex");
1105
1106 glActiveTexture(GL_TEXTURE1);
1107 glBindTexture(GL_TEXTURE_2D, m_screenTexture[1]);
1108 switch (format) {
1109 case V4L2_PIX_FMT_NV16:
1110 case V4L2_PIX_FMT_NV61:
1111 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, m_v4l_fmt.g_width(), m_v4l_fmt.g_height(),
1112 GL_RED, GL_UNSIGNED_BYTE,
1113 m_curData[0] ? m_curData[0] + m_v4l_fmt.g_sizeimage() / 2 : NULL);
1114 break;
1115 case V4L2_PIX_FMT_NV16M:
1116 case V4L2_PIX_FMT_NV61M:
1117 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, m_v4l_fmt.g_width(), m_v4l_fmt.g_height(),
1118 GL_RED, GL_UNSIGNED_BYTE, m_curData[1]);
1119 break;
1120 }
1121 glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
1122 checkError("NV16 paint uvtex");
1123 }
1124
render_YUY2(__u32 format)1125 void CaptureWin::render_YUY2(__u32 format)
1126 {
1127 glActiveTexture(GL_TEXTURE0);
1128 glBindTexture(GL_TEXTURE_2D, m_screenTexture[0]);
1129 glPixelStorei(GL_UNPACK_ROW_LENGTH, m_v4l_fmt.g_bytesperline() / 4);
1130 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, m_v4l_fmt.g_width() / 2, m_v4l_fmt.g_height(),
1131 GL_RGBA, GL_UNSIGNED_BYTE, m_curData[0]);
1132 glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
1133 checkError("YUY2 paint");
1134 }
1135
render_RGB(__u32 format)1136 void CaptureWin::render_RGB(__u32 format)
1137 {
1138 glActiveTexture(GL_TEXTURE0);
1139 glBindTexture(GL_TEXTURE_2D, m_screenTexture[0]);
1140
1141 switch (format) {
1142 case V4L2_PIX_FMT_RGB332:
1143 glPixelStorei(GL_UNPACK_ROW_LENGTH, m_v4l_fmt.g_bytesperline());
1144 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, m_v4l_fmt.g_width(), m_v4l_fmt.g_height(),
1145 GL_RGB, GL_UNSIGNED_BYTE_3_3_2, m_curData[0]);
1146 break;
1147
1148 case V4L2_PIX_FMT_RGB444:
1149 case V4L2_PIX_FMT_XRGB444:
1150 case V4L2_PIX_FMT_ARGB444:
1151 case V4L2_PIX_FMT_XBGR444:
1152 case V4L2_PIX_FMT_ABGR444:
1153 case V4L2_PIX_FMT_RGBX444:
1154 case V4L2_PIX_FMT_RGBA444:
1155 case V4L2_PIX_FMT_BGRX444:
1156 case V4L2_PIX_FMT_BGRA444:
1157 glPixelStorei(GL_UNPACK_ROW_LENGTH, m_v4l_fmt.g_bytesperline() / 2);
1158 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, m_v4l_fmt.g_width(), m_v4l_fmt.g_height(),
1159 GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4, m_curData[0]);
1160 break;
1161
1162 case V4L2_PIX_FMT_GREY:
1163 glPixelStorei(GL_UNPACK_ROW_LENGTH, m_v4l_fmt.g_bytesperline());
1164 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, m_v4l_fmt.g_width(), m_v4l_fmt.g_height(),
1165 GL_RED_INTEGER, GL_UNSIGNED_BYTE, m_curData[0]);
1166 break;
1167
1168 case V4L2_PIX_FMT_Y10:
1169 case V4L2_PIX_FMT_Y12:
1170 case V4L2_PIX_FMT_Y16:
1171 case V4L2_PIX_FMT_Z16:
1172 glPixelStorei(GL_UNPACK_ROW_LENGTH, m_v4l_fmt.g_bytesperline() / 2);
1173 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, m_v4l_fmt.g_width(), m_v4l_fmt.g_height(),
1174 GL_RED_INTEGER, GL_UNSIGNED_SHORT, m_curData[0]);
1175 break;
1176 case V4L2_PIX_FMT_Y16_BE:
1177 glPixelStorei(GL_UNPACK_ROW_LENGTH, m_v4l_fmt.g_bytesperline() / 2);
1178 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, m_v4l_fmt.g_width(), m_v4l_fmt.g_height(),
1179 GL_RED_INTEGER, GL_UNSIGNED_SHORT, m_curData[0]);
1180 break;
1181
1182 case V4L2_PIX_FMT_RGB555:
1183 case V4L2_PIX_FMT_XRGB555:
1184 case V4L2_PIX_FMT_ARGB555:
1185 case V4L2_PIX_FMT_XBGR555:
1186 case V4L2_PIX_FMT_ABGR555:
1187 glPixelStorei(GL_UNPACK_ROW_LENGTH, m_v4l_fmt.g_bytesperline() / 2);
1188 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, m_v4l_fmt.g_width(), m_v4l_fmt.g_height(),
1189 GL_BGRA, GL_UNSIGNED_SHORT_1_5_5_5_REV, m_curData[0]);
1190 break;
1191
1192 case V4L2_PIX_FMT_RGB555X:
1193 case V4L2_PIX_FMT_XRGB555X:
1194 case V4L2_PIX_FMT_ARGB555X:
1195 glPixelStorei(GL_UNPACK_ROW_LENGTH, m_v4l_fmt.g_bytesperline() / 2);
1196 // Note: most likely for big-endian systems SWAP_BYTES should be true
1197 // for the RGB555 format, and false for this format. This would have
1198 // to be tested first, though.
1199 glPixelStorei(GL_UNPACK_SWAP_BYTES, GL_TRUE);
1200 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, m_v4l_fmt.g_width(), m_v4l_fmt.g_height(),
1201 GL_BGRA, GL_UNSIGNED_SHORT_1_5_5_5_REV, m_curData[0]);
1202 glPixelStorei(GL_UNPACK_SWAP_BYTES, GL_FALSE);
1203 break;
1204
1205 case V4L2_PIX_FMT_RGBX555:
1206 case V4L2_PIX_FMT_RGBA555:
1207 case V4L2_PIX_FMT_BGRX555:
1208 case V4L2_PIX_FMT_BGRA555:
1209 glPixelStorei(GL_UNPACK_ROW_LENGTH, m_v4l_fmt.g_bytesperline() / 2);
1210 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, m_v4l_fmt.g_width(), m_v4l_fmt.g_height(),
1211 GL_BGRA, GL_UNSIGNED_SHORT_5_5_5_1, m_curData[0]);
1212 break;
1213
1214 case V4L2_PIX_FMT_RGB565:
1215 glPixelStorei(GL_UNPACK_ROW_LENGTH, m_v4l_fmt.g_bytesperline() / 2);
1216 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, m_v4l_fmt.g_width(), m_v4l_fmt.g_height(),
1217 GL_RGB, GL_UNSIGNED_SHORT_5_6_5, m_curData[0]);
1218 break;
1219
1220 case V4L2_PIX_FMT_RGB565X:
1221 glPixelStorei(GL_UNPACK_ROW_LENGTH, m_v4l_fmt.g_bytesperline() / 2);
1222 // Note: most likely for big-endian systems SWAP_BYTES should be true
1223 // for the RGB565 format, and false for this format. This would have
1224 // to be tested first, though.
1225 glPixelStorei(GL_UNPACK_SWAP_BYTES, GL_TRUE);
1226 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, m_v4l_fmt.g_width(), m_v4l_fmt.g_height(),
1227 GL_RGB, GL_UNSIGNED_SHORT_5_6_5, m_curData[0]);
1228 glPixelStorei(GL_UNPACK_SWAP_BYTES, GL_FALSE);
1229 break;
1230
1231 case V4L2_PIX_FMT_RGB32:
1232 case V4L2_PIX_FMT_XRGB32:
1233 case V4L2_PIX_FMT_ARGB32:
1234 case V4L2_PIX_FMT_RGBX32:
1235 case V4L2_PIX_FMT_RGBA32:
1236 case V4L2_PIX_FMT_HSV32:
1237 case V4L2_PIX_FMT_BGR32:
1238 case V4L2_PIX_FMT_XBGR32:
1239 case V4L2_PIX_FMT_ABGR32:
1240 case V4L2_PIX_FMT_BGRX32:
1241 case V4L2_PIX_FMT_BGRA32:
1242 glPixelStorei(GL_UNPACK_ROW_LENGTH, m_v4l_fmt.g_bytesperline() / 4);
1243 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, m_v4l_fmt.g_width(), m_v4l_fmt.g_height(),
1244 GL_RGBA, GL_UNSIGNED_BYTE, m_curData[0]);
1245 break;
1246 case V4L2_PIX_FMT_BGR666:
1247 glPixelStorei(GL_UNPACK_ROW_LENGTH, m_v4l_fmt.g_bytesperline() / 4);
1248 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, m_v4l_fmt.g_width(), m_v4l_fmt.g_height(),
1249 GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, m_curData[0]);
1250 break;
1251
1252 case V4L2_PIX_FMT_RGB24:
1253 case V4L2_PIX_FMT_BGR24:
1254 case V4L2_PIX_FMT_HSV24:
1255 default:
1256 glPixelStorei(GL_UNPACK_ROW_LENGTH, m_v4l_fmt.g_bytesperline() / 3);
1257 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, m_v4l_fmt.g_width(), m_v4l_fmt.g_height(),
1258 GL_RGB, GL_UNSIGNED_BYTE, m_curData[0]);
1259 break;
1260 }
1261 glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
1262 checkError("RGB paint");
1263 }
1264
render_Bayer(__u32 format)1265 void CaptureWin::render_Bayer(__u32 format)
1266 {
1267 glActiveTexture(GL_TEXTURE0);
1268 glBindTexture(GL_TEXTURE_2D, m_screenTexture[0]);
1269
1270 switch (format) {
1271 case V4L2_PIX_FMT_SBGGR8:
1272 case V4L2_PIX_FMT_SGBRG8:
1273 case V4L2_PIX_FMT_SGRBG8:
1274 case V4L2_PIX_FMT_SRGGB8:
1275 glPixelStorei(GL_UNPACK_ROW_LENGTH, m_v4l_fmt.g_bytesperline());
1276 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, m_v4l_fmt.g_width(), m_v4l_fmt.g_height(),
1277 GL_RED_INTEGER, GL_UNSIGNED_BYTE, m_curData[0]);
1278 break;
1279 case V4L2_PIX_FMT_SBGGR10:
1280 case V4L2_PIX_FMT_SGBRG10:
1281 case V4L2_PIX_FMT_SGRBG10:
1282 case V4L2_PIX_FMT_SRGGB10:
1283 case V4L2_PIX_FMT_SBGGR12:
1284 case V4L2_PIX_FMT_SGBRG12:
1285 case V4L2_PIX_FMT_SGRBG12:
1286 case V4L2_PIX_FMT_SRGGB12:
1287 case V4L2_PIX_FMT_SBGGR16:
1288 case V4L2_PIX_FMT_SGBRG16:
1289 case V4L2_PIX_FMT_SGRBG16:
1290 case V4L2_PIX_FMT_SRGGB16:
1291 glPixelStorei(GL_UNPACK_ROW_LENGTH, m_v4l_fmt.g_bytesperline() / 2);
1292 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, m_v4l_fmt.g_width(), m_v4l_fmt.g_height(),
1293 GL_RED_INTEGER, GL_UNSIGNED_SHORT, m_curData[0]);
1294 break;
1295 }
1296 checkError("Bayer paint");
1297 }
1298
render_YUV_packed(__u32 format)1299 void CaptureWin::render_YUV_packed(__u32 format)
1300 {
1301 glActiveTexture(GL_TEXTURE0);
1302 glBindTexture(GL_TEXTURE_2D, m_screenTexture[0]);
1303
1304 switch (format) {
1305 case V4L2_PIX_FMT_YUV555:
1306 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, m_v4l_fmt.g_width(), m_v4l_fmt.g_height(),
1307 GL_BGRA, GL_UNSIGNED_SHORT_1_5_5_5_REV, m_curData[0]);
1308 break;
1309
1310 case V4L2_PIX_FMT_YUV444:
1311 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, m_v4l_fmt.g_width(), m_v4l_fmt.g_height(),
1312 GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4, m_curData[0]);
1313 break;
1314
1315 case V4L2_PIX_FMT_YUV565:
1316 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, m_v4l_fmt.g_width(), m_v4l_fmt.g_height(),
1317 GL_RGB, GL_UNSIGNED_SHORT_5_6_5, m_curData[0]);
1318 break;
1319
1320 case V4L2_PIX_FMT_YUV32:
1321 case V4L2_PIX_FMT_AYUV32:
1322 case V4L2_PIX_FMT_XYUV32:
1323 case V4L2_PIX_FMT_VUYA32:
1324 case V4L2_PIX_FMT_VUYX32:
1325 case V4L2_PIX_FMT_YUVA32:
1326 case V4L2_PIX_FMT_YUVX32:
1327 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, m_v4l_fmt.g_width(), m_v4l_fmt.g_height(),
1328 GL_RGBA, GL_UNSIGNED_BYTE, m_curData[0]);
1329 break;
1330 }
1331 checkError("Packed YUV paint");
1332 }
1333