• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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