qeglfscursor.cpp

Absolute File Name:/home/qt/qt5_coco/qt5/qtbase/src/plugins/platforms/eglfs/qeglfscursor.cpp
Switch to Source codePreprocessed file
LineSourceCount
1-
2-
3-
4-
5-
6-
7-
8-
9-
10QEglFSCursor::QEglFSCursor(QPlatformScreen *screen)-
11 : m_visible(true),-
12 m_screen(static_cast<QEglFSScreen *>(screen)),-
13 m_program(0),-
14 m_textureEntry(0),-
15 m_deviceListener(0),-
16 m_updateRequested(false)-
17{-
18 QByteArray hideCursorVal = qgetenv("QT_QPA_EGLFS_HIDECURSOR");-
19 if (!hideCursorVal.isEmpty()
!hideCursorVal.isEmpty()Description
TRUEnever evaluated
FALSEnever evaluated
)
0
20 m_visible = hideCursorVal.toInt() == 0;
never executed: m_visible = hideCursorVal.toInt() == 0;
0
21 if (!m_visible
!m_visibleDescription
TRUEnever evaluated
FALSEnever evaluated
)
0
22 return;
never executed: return;
0
23-
24-
25-
26 initCursorAtlas();-
27-
28-
29-
30 QCursor cursor(Qt::ArrowCursor);-
31 setCurrentCursor(&cursor);-
32-
33-
34 m_deviceListener = new QEglFSCursorDeviceListener(this);-
35 connect(QGuiApplicationPrivate::inputDeviceManager(), &QInputDeviceManager::deviceListChanged,-
36 m_deviceListener, &QEglFSCursorDeviceListener::onDeviceListChanged);-
37 updateMouseStatus();-
38}
never executed: end of block
0
39-
40QEglFSCursor::~QEglFSCursor()-
41{-
42 resetResources();-
43 delete m_deviceListener;-
44}
never executed: end of block
0
45-
46void QEglFSCursor::updateMouseStatus()-
47{-
48 m_visible = m_deviceListener->hasMouse();-
49}
never executed: end of block
0
50-
51bool QEglFSCursorDeviceListener::hasMouse() const-
52{-
53 return
never executed: return QGuiApplicationPrivate::inputDeviceManager()->deviceCount(QInputDeviceManager::DeviceTypePointer) > 0;
QGuiApplicationPrivate::inputDeviceManager()->deviceCount(QInputDeviceManager::DeviceTypePointer) > 0;
never executed: return QGuiApplicationPrivate::inputDeviceManager()->deviceCount(QInputDeviceManager::DeviceTypePointer) > 0;
0
54}-
55-
56void QEglFSCursorDeviceListener::onDeviceListChanged(QInputDeviceManager::DeviceType type)-
57{-
58 if (type == QInputDeviceManager::DeviceTypePointer
type == QInput...iceTypePointerDescription
TRUEnever evaluated
FALSEnever evaluated
)
0
59 m_cursor->updateMouseStatus();
never executed: m_cursor->updateMouseStatus();
0
60}
never executed: end of block
0
61-
62void QEglFSCursor::resetResources()-
63{-
64 if (QOpenGLContext::currentContext()
QOpenGLContext...rrentContext()Description
TRUEnever evaluated
FALSEnever evaluated
) {
0
65 delete m_program;-
66 glDeleteTextures(1, &m_cursor.customCursorTexture);-
67 glDeleteTextures(1, &m_cursorAtlas.texture);-
68 }
never executed: end of block
0
69 m_program = 0;-
70 m_cursor.customCursorTexture = 0;-
71 m_cursor.customCursorPending = !m_cursor.customCursorImage.isNull();-
72 m_cursorAtlas.texture = 0;-
73}
never executed: end of block
0
74-
75void QEglFSCursor::createShaderPrograms()-
76{-
77 static const char *textureVertexProgram =-
78 "attribute highp vec2 vertexCoordEntry;\n"-
79 "attribute highp vec2 textureCoordEntry;\n"-
80 "varying highp vec2 textureCoord;\n"-
81 "void main() {\n"-
82 " textureCoord = textureCoordEntry;\n"-
83 " gl_Position = vec4(vertexCoordEntry, 1.0, 1.0);\n"-
84 "}\n";-
85-
86 static const char *textureFragmentProgram =-
87 "uniform sampler2D texture;\n"-
88 "varying highp vec2 textureCoord;\n"-
89 "void main() {\n"-
90 " gl_FragColor = texture2D(texture, textureCoord).bgra;\n"-
91 "}\n";-
92-
93 m_program = new QOpenGLShaderProgram;-
94 m_program->addShaderFromSourceCode(QOpenGLShader::Vertex, textureVertexProgram);-
95 m_program->addShaderFromSourceCode(QOpenGLShader::Fragment, textureFragmentProgram);-
96 m_program->bindAttributeLocation("vertexCoordEntry", 0);-
97 m_program->bindAttributeLocation("textureCoordEntry", 1);-
98 m_program->link();-
99-
100 m_textureEntry = m_program->uniformLocation("texture");-
101}
never executed: end of block
0
102-
103void QEglFSCursor::createCursorTexture(uint *texture, const QImage &image)-
104{-
105 if (!*texture
!*textureDescription
TRUEnever evaluated
FALSEnever evaluated
)
0
106 glGenTextures(1, texture);
never executed: glGenTextures(1, texture);
0
107 glBindTexture(0x0DE1, *texture);-
108 glTexParameterf(0x0DE1, 0x2801, 0x2600);-
109 glTexParameterf(0x0DE1, 0x2800, 0x2600);-
110 glTexParameterf(0x0DE1, 0x2802, 0x812F);-
111 glTexParameterf(0x0DE1, 0x2803, 0x812F);-
112-
113 glTexImage2D(0x0DE1, 0 , 0x1908, image.width(), image.height(), 0 ,-
114 0x1908, 0x1401, image.constBits());-
115}
never executed: end of block
0
116-
117void QEglFSCursor::initCursorAtlas()-
118{-
119 static QByteArray json = qgetenv("QT_QPA_EGLFS_CURSOR");-
120 if (json.isEmpty()
json.isEmpty()Description
TRUEnever evaluated
FALSEnever evaluated
)
0
121 json = ":/cursor.json";
never executed: json = ":/cursor.json";
0
122-
123 QFile file(QString::fromUtf8(json));-
124 if (!file.open(QFile::ReadOnly)
!file.open(QFile::ReadOnly)Description
TRUEnever evaluated
FALSEnever evaluated
) {
0
125 m_visible = false;-
126 return;
never executed: return;
0
127 }-
128-
129 QJsonDocument doc = QJsonDocument::fromJson(file.readAll());-
130 QJsonObject object = doc.object();-
131-
132 QString atlas = object.value(QLatin1String("image")).toString();-
133 ((!(!atlas.isEmpty())) ? qt_assert("!atlas.isEmpty()",__FILE__,184) : qt_noop());-
134-
135 const int cursorsPerRow = object.value(QLatin1String("cursorsPerRow")).toDouble();-
136 ((!(cursorsPerRow)) ? qt_assert("cursorsPerRow",__FILE__,187) : qt_noop());-
137 m_cursorAtlas.cursorsPerRow = cursorsPerRow;-
138-
139 const QJsonArray hotSpots = object.value(QLatin1String("hotSpots")).toArray();-
140 ((!(hotSpots.count() == Qt::LastCursor + 1)) ? qt_assert("hotSpots.count() == Qt::LastCursor + 1",__FILE__,191) : qt_noop());-
141 for (int i = 0; i < hotSpots.count()
i < hotSpots.count()Description
TRUEnever evaluated
FALSEnever evaluated
; i++) {
0
142 QPoint hotSpot(hotSpots[i].toArray()[0].toDouble(), hotSpots[i].toArray()[1].toDouble());-
143 m_cursorAtlas.hotSpots << hotSpot;-
144 }
never executed: end of block
0
145-
146 QImage image = QImage(atlas).convertToFormat(QImage::Format_ARGB32_Premultiplied);-
147 m_cursorAtlas.cursorWidth = image.width() / m_cursorAtlas.cursorsPerRow;-
148 m_cursorAtlas.cursorHeight = image.height() / ((Qt::LastCursor + cursorsPerRow) / cursorsPerRow);-
149 m_cursorAtlas.width = image.width();-
150 m_cursorAtlas.height = image.height();-
151 m_cursorAtlas.image = image;-
152}
never executed: end of block
0
153-
154-
155void QEglFSCursor::changeCursor(QCursor *cursor, QWindow *window)-
156{-
157 (void)window;;-
158 const QRect oldCursorRect = cursorRect();-
159 if (setCurrentCursor(cursor)
setCurrentCursor(cursor)Description
TRUEnever evaluated
FALSEnever evaluated
)
0
160 update(oldCursorRect | cursorRect());
never executed: update(oldCursorRect | cursorRect());
0
161}
never executed: end of block
0
162-
163bool QEglFSCursor::setCurrentCursor(QCursor *cursor)-
164{-
165 if (!m_visible
!m_visibleDescription
TRUEnever evaluated
FALSEnever evaluated
)
0
166 return
never executed: return false;
false;
never executed: return false;
0
167-
168 const Qt::CursorShape newShape = cursor
cursorDescription
TRUEnever evaluated
FALSEnever evaluated
? cursor->shape() : Qt::ArrowCursor;
0
169 if (m_cursor.shape == newShape
m_cursor.shape == newShapeDescription
TRUEnever evaluated
FALSEnever evaluated
&& newShape != Qt::BitmapCursor
newShape != Qt::BitmapCursorDescription
TRUEnever evaluated
FALSEnever evaluated
)
0
170 return
never executed: return false;
false;
never executed: return false;
0
171-
172 if (m_cursor.shape == Qt::BitmapCursor
m_cursor.shape...::BitmapCursorDescription
TRUEnever evaluated
FALSEnever evaluated
) {
0
173 m_cursor.customCursorImage = QImage();-
174 m_cursor.customCursorPending = false;-
175 }
never executed: end of block
0
176 m_cursor.shape = newShape;-
177 if (newShape != Qt::BitmapCursor
newShape != Qt::BitmapCursorDescription
TRUEnever evaluated
FALSEnever evaluated
) {
0
178 const float ws = (float)m_cursorAtlas.cursorWidth / m_cursorAtlas.width,-
179 hs = (float)m_cursorAtlas.cursorHeight / m_cursorAtlas.height;-
180 m_cursor.textureRect = QRectF(ws * (m_cursor.shape % m_cursorAtlas.cursorsPerRow),-
181 hs * (m_cursor.shape / m_cursorAtlas.cursorsPerRow),-
182 ws, hs);-
183 m_cursor.hotSpot = m_cursorAtlas.hotSpots[m_cursor.shape];-
184 m_cursor.texture = m_cursorAtlas.texture;-
185 m_cursor.size = QSize(m_cursorAtlas.cursorWidth, m_cursorAtlas.cursorHeight);-
186 }
never executed: end of block
else {
0
187 QImage image = cursor->pixmap().toImage();-
188 m_cursor.textureRect = QRectF(0, 0, 1, 1);-
189 m_cursor.hotSpot = cursor->hotSpot();-
190 m_cursor.texture = 0;-
191 m_cursor.size = image.size();-
192 m_cursor.customCursorImage = image;-
193 m_cursor.customCursorPending = true;-
194 }
never executed: end of block
0
195-
196 return
never executed: return true;
true;
never executed: return true;
0
197}-
198-
199-
200class CursorUpdateEvent : public QEvent-
201{-
202public:-
203 CursorUpdateEvent(const QPoint &pos, const QRegion &rgn)-
204 : QEvent(QEvent::Type(QEvent::User + 1)),-
205 m_pos(pos),-
206 m_region(rgn)-
207 { }
never executed: end of block
0
208 QPoint pos() const { return
never executed: return m_pos;
m_pos;
never executed: return m_pos;
}
0
209 QRegion region() const { return
never executed: return m_region;
m_region;
never executed: return m_region;
}
0
210-
211private:-
212 QPoint m_pos;-
213 QRegion m_region;-
214};-
215-
216bool QEglFSCursor::event(QEvent *e)-
217{-
218 if (e->type() == QEvent::User + 1
e->type() == QEvent::User + 1Description
TRUEnever evaluated
FALSEnever evaluated
) {
0
219 CursorUpdateEvent *ev = static_cast<CursorUpdateEvent *>(e);-
220 m_updateRequested = false;-
221 QWindowSystemInterface::handleExposeEvent(m_screen->topLevelAt(ev->pos()), ev->region());-
222 QWindowSystemInterface::flushWindowSystemEvents(QEventLoop::ExcludeUserInputEvents);-
223 return
never executed: return true;
true;
never executed: return true;
0
224 }-
225 return
never executed: return QPlatformCursor::event(e);
QPlatformCursor::event(e);
never executed: return QPlatformCursor::event(e);
0
226}-
227-
228void QEglFSCursor::update(const QRegion &rgn)-
229{-
230 if (!m_updateRequested
!m_updateRequestedDescription
TRUEnever evaluated
FALSEnever evaluated
) {
0
231-
232-
233-
234 m_updateRequested = true;-
235 QCoreApplication::postEvent(this, new CursorUpdateEvent(m_cursor.pos, rgn));-
236 }
never executed: end of block
0
237}
never executed: end of block
0
238-
239QRect QEglFSCursor::cursorRect() const-
240{-
241 return
never executed: return QRect(m_cursor.pos - m_cursor.hotSpot, m_cursor.size);
QRect(m_cursor.pos - m_cursor.hotSpot, m_cursor.size);
never executed: return QRect(m_cursor.pos - m_cursor.hotSpot, m_cursor.size);
0
242}-
243-
244QPoint QEglFSCursor::pos() const-
245{-
246 return
never executed: return m_cursor.pos;
m_cursor.pos;
never executed: return m_cursor.pos;
0
247}-
248-
249void QEglFSCursor::setPos(const QPoint &pos)-
250{-
251 QGuiApplicationPrivate::inputDeviceManager()->setCursorPos(pos);-
252 const QRect oldCursorRect = cursorRect();-
253 m_cursor.pos = pos;-
254 update(oldCursorRect | cursorRect());-
255 m_screen->handleCursorMove(m_cursor.pos);-
256}
never executed: end of block
0
257-
258void QEglFSCursor::pointerEvent(const QMouseEvent &event)-
259{-
260 if (event.type() != QEvent::MouseMove
event.type() !...ent::MouseMoveDescription
TRUEnever evaluated
FALSEnever evaluated
)
0
261 return;
never executed: return;
0
262 const QRect oldCursorRect = cursorRect();-
263 m_cursor.pos = event.screenPos().toPoint();-
264 update(oldCursorRect | cursorRect());-
265 m_screen->handleCursorMove(m_cursor.pos);-
266}
never executed: end of block
0
267-
268void QEglFSCursor::paintOnScreen()-
269{-
270 if (!m_visible
!m_visibleDescription
TRUEnever evaluated
FALSEnever evaluated
)
0
271 return;
never executed: return;
0
272-
273 const QRectF cr = cursorRect();-
274 const QRect screenRect(m_screen->geometry());-
275 const GLfloat x1 = 2 * (cr.left() / screenRect.width()) - 1;-
276 const GLfloat x2 = 2 * (cr.right() / screenRect.width()) - 1;-
277 const GLfloat y1 = 1 - (cr.top() / screenRect.height()) * 2;-
278 const GLfloat y2 = 1 - (cr.bottom() / screenRect.height()) * 2;-
279 QRectF r(QPointF(x1, y1), QPointF(x2, y2));-
280-
281 draw(r);-
282}
never executed: end of block
0
283-
284-
285-
286-
287-
288struct StateSaver-
289{-
290 StateSaver() {-
291 f = QOpenGLContext::currentContext()->functions();-
292 vaoHelper = new QOpenGLVertexArrayObjectHelper(QOpenGLContext::currentContext());-
293-
294 static bool windowsChecked = false;-
295 static bool shouldSave = true;-
296 if (!windowsChecked
!windowsCheckedDescription
TRUEnever evaluated
FALSEnever evaluated
) {
0
297 windowsChecked = true;-
298 QWindowList windows = QGuiApplication::allWindows();-
299 if (!windows.isEmpty()
!windows.isEmpty()Description
TRUEnever evaluated
FALSEnever evaluated
&& windows[0]->inherits("QQuickWindow")
windows[0]->in...QQuickWindow")Description
TRUEnever evaluated
FALSEnever evaluated
)
0
300 shouldSave = false;
never executed: shouldSave = false;
0
301 }
never executed: end of block
0
302 saved = shouldSave;-
303 if (!shouldSave
!shouldSaveDescription
TRUEnever evaluated
FALSEnever evaluated
)
0
304 return;
never executed: return;
0
305-
306 f->glGetIntegerv(0x8B8D, &program);-
307 f->glGetIntegerv(0x8069, &texture);-
308 f->glGetIntegerv(0x84E0, &activeTexture);-
309 f->glGetIntegerv(0x0B46, &frontFace);-
310 cull = f->glIsEnabled(0x0B44);-
311 depthTest = f->glIsEnabled(0x0B71);-
312 blend = f->glIsEnabled(0x0BE2);-
313 f->glGetIntegerv(0x80C9, blendFunc);-
314 f->glGetIntegerv(0x80CB, blendFunc + 1);-
315 f->glGetIntegerv(0x80C8, blendFunc + 2);-
316 f->glGetIntegerv(0x80CA, blendFunc + 3);-
317 f->glGetIntegerv(0x8894, &arrayBuf);-
318 if (vaoHelper->isValid()
vaoHelper->isValid()Description
TRUEnever evaluated
FALSEnever evaluated
)
0
319 f->glGetIntegerv(0x85B5, &vao);
never executed: f->glGetIntegerv(0x85B5, &vao);
0
320 for (int i = 0; i < 2
i < 2Description
TRUEnever evaluated
FALSEnever evaluated
; ++i) {
0
321 f->glGetVertexAttribiv(i, 0x8622, &va[i].enabled);-
322 f->glGetVertexAttribiv(i, 0x8623, &va[i].size);-
323 f->glGetVertexAttribiv(i, 0x8625, &va[i].type);-
324 f->glGetVertexAttribiv(i, 0x886A, &va[i].normalized);-
325 f->glGetVertexAttribiv(i, 0x8624, &va[i].stride);-
326 f->glGetVertexAttribiv(i, 0x889F, &va[i].buffer);-
327 f->glGetVertexAttribPointerv(i, 0x8645, &va[i].pointer);-
328 }
never executed: end of block
0
329 }
never executed: end of block
0
330 ~StateSaver() {-
331 if (saved
savedDescription
TRUEnever evaluated
FALSEnever evaluated
) {
0
332 f->glUseProgram(program);-
333 f->glBindTexture(0x0DE1, texture);-
334 f->glActiveTexture(activeTexture);-
335 f->glFrontFace(frontFace);-
336 if (cull
cullDescription
TRUEnever evaluated
FALSEnever evaluated
)
0
337 f->glEnable(0x0B44);
never executed: f->glEnable(0x0B44);
0
338 else-
339 f->glDisable(0x0B44);
never executed: f->glDisable(0x0B44);
0
340 if (depthTest
depthTestDescription
TRUEnever evaluated
FALSEnever evaluated
)
0
341 f->glEnable(0x0B71);
never executed: f->glEnable(0x0B71);
0
342 else-
343 f->glDisable(0x0B71);
never executed: f->glDisable(0x0B71);
0
344 if (blend
blendDescription
TRUEnever evaluated
FALSEnever evaluated
)
0
345 f->glEnable(0x0BE2);
never executed: f->glEnable(0x0BE2);
0
346 else-
347 f->glDisable(0x0BE2);
never executed: f->glDisable(0x0BE2);
0
348 f->glBlendFuncSeparate(blendFunc[0], blendFunc[1], blendFunc[2], blendFunc[3]);-
349 f->glBindBuffer(0x8892, arrayBuf);-
350 if (vaoHelper->isValid()
vaoHelper->isValid()Description
TRUEnever evaluated
FALSEnever evaluated
)
0
351 vaoHelper->glBindVertexArray(vao);
never executed: vaoHelper->glBindVertexArray(vao);
0
352 for (int i = 0; i < 2
i < 2Description
TRUEnever evaluated
FALSEnever evaluated
; ++i) {
0
353 if (va[i].enabled
va[i].enabledDescription
TRUEnever evaluated
FALSEnever evaluated
)
0
354 f->glEnableVertexAttribArray(i);
never executed: f->glEnableVertexAttribArray(i);
0
355 else-
356 f->glDisableVertexAttribArray(i);
never executed: f->glDisableVertexAttribArray(i);
0
357 f->glBindBuffer(0x8892, va[i].buffer);-
358 f->glVertexAttribPointer(i, va[i].size, va[i].type, va[i].normalized, va[i].stride, va[i].pointer);-
359 }
never executed: end of block
0
360 }
never executed: end of block
0
361 delete vaoHelper;-
362 }
never executed: end of block
0
363 QOpenGLFunctions *f;-
364 QOpenGLVertexArrayObjectHelper *vaoHelper;-
365 bool saved;-
366 GLint program;-
367 GLint texture;-
368 GLint activeTexture;-
369 GLint frontFace;-
370 bool cull;-
371 bool depthTest;-
372 bool blend;-
373 GLint blendFunc[4];-
374 GLint vao;-
375 GLint arrayBuf;-
376 struct { GLint enabled, type, size, normalized, stride, buffer; GLvoid *pointer; } va[2];-
377};-
378-
379void QEglFSCursor::draw(const QRectF &r)-
380{-
381 StateSaver stateSaver;-
382-
383 if (!m_program
!m_programDescription
TRUEnever evaluated
FALSEnever evaluated
) {
0
384-
385 initializeOpenGLFunctions();-
386-
387 createShaderPrograms();-
388-
389 if (!m_cursorAtlas.texture
!m_cursorAtlas.textureDescription
TRUEnever evaluated
FALSEnever evaluated
) {
0
390 createCursorTexture(&m_cursorAtlas.texture, m_cursorAtlas.image);-
391-
392 if (m_cursor.shape != Qt::BitmapCursor
m_cursor.shape...::BitmapCursorDescription
TRUEnever evaluated
FALSEnever evaluated
)
0
393 m_cursor.texture = m_cursorAtlas.texture;
never executed: m_cursor.texture = m_cursorAtlas.texture;
0
394 }
never executed: end of block
0
395 }
never executed: end of block
0
396-
397 if (m_cursor.shape == Qt::BitmapCursor
m_cursor.shape...::BitmapCursorDescription
TRUEnever evaluated
FALSEnever evaluated
&& m_cursor.customCursorPending
m_cursor.customCursorPendingDescription
TRUEnever evaluated
FALSEnever evaluated
) {
0
398-
399 createCursorTexture(&m_cursor.customCursorTexture, m_cursor.customCursorImage);-
400 m_cursor.texture = m_cursor.customCursorTexture;-
401 m_cursor.customCursorPending = false;-
402 }
never executed: end of block
0
403-
404 ((!(m_cursor.texture)) ? qt_assert("m_cursor.texture",__FILE__,455) : qt_noop());-
405-
406 m_program->bind();-
407-
408 const GLfloat x1 = r.left();-
409 const GLfloat x2 = r.right();-
410 const GLfloat y1 = r.top();-
411 const GLfloat y2 = r.bottom();-
412 const GLfloat cursorCoordinates[] = {-
413 x1, y2,-
414 x2, y2,-
415 x1, y1,-
416 x2, y1-
417 };-
418-
419 const GLfloat s1 = m_cursor.textureRect.left();-
420 const GLfloat s2 = m_cursor.textureRect.right();-
421 const GLfloat t1 = m_cursor.textureRect.top();-
422 const GLfloat t2 = m_cursor.textureRect.bottom();-
423 const GLfloat textureCoordinates[] = {-
424 s1, t2,-
425 s2, t2,-
426 s1, t1,-
427 s2, t1-
428 };-
429-
430 glActiveTexture(0x84C0);-
431 glBindTexture(0x0DE1, m_cursor.texture);-
432-
433 if (stateSaver.vaoHelper->isValid()
stateSaver.vao...per->isValid()Description
TRUEnever evaluated
FALSEnever evaluated
)
0
434 stateSaver.vaoHelper->glBindVertexArray(0);
never executed: stateSaver.vaoHelper->glBindVertexArray(0);
0
435-
436 glBindBuffer(0x8892, 0);-
437-
438 m_program->enableAttributeArray(0);-
439 m_program->enableAttributeArray(1);-
440 m_program->setAttributeArray(0, cursorCoordinates, 2);-
441 m_program->setAttributeArray(1, textureCoordinates, 2);-
442-
443 m_program->setUniformValue(m_textureEntry, 0);-
444-
445 glDisable(0x0B44);-
446 glFrontFace(0x0901);-
447 glEnable(0x0BE2);-
448 glBlendFunc(1, 0x0303);-
449 glDisable(0x0B71);-
450-
451 glDrawArrays(0x0005, 0, 4);-
452-
453 m_program->disableAttributeArray(0);-
454 m_program->disableAttributeArray(1);-
455 m_program->release();-
456}
never executed: end of block
0
457-
458-
Switch to Source codePreprocessed file

Generated by Squish Coco Non-Commercial 4.3.0-BETA-master-30-08-2018-4cb69e9