title: PyQt5's OpenGL ES 2.0 Texture Mapping for Raspberry Pi not working
body: <p>I want to use PyQT5 and OpenGL to create an interactive application which should run on the Raspberry Pi Zero with Raspbian.</p>
  
  <p>The first step is to display an image texture on screen, but this already fails with an error message on the Pi. (see down below)</p>
  
  <p>However it is running fine when executed on my Ubuntu development machine with OpenGL 2.0 profile.</p>
  
  <pre><code>#!/usr/bin/env python
  import sys
  
  from PIL import Image
  from PyQt5.QtCore import QSize, Qt
  from PyQt5.QtGui import (QColor, QSurfaceFormat, QOpenGLVersionProfile)
  from PyQt5.QtWidgets import QApplication, QGridLayout, QOpenGLWidget, QWidget
  
  
  class GLWidget(QOpenGLWidget):
  
      def __init__(self, path, width, height, parent=None):
          super(GLWidget, self).__init__(parent)
  
          self.path = path
          self.width = width
          self.height = height
          self.texture_array = []
          self.current_texture_index = 0
          self.fps = 0
  
          self.elapsed = 0
          self.clearColor = QColor(Qt.black)
  
      def sizeHint(self):
          return QSize(self.width, self.height)
  
      def initializeGL(self):
          version = QOpenGLVersionProfile()
          version.setVersion(2, 0)
  
          self.gl = self.context().versionFunctions(version)
          self.gl.initializeOpenGLFunctions()
  
          self.gl.glEnable(self.gl.GL_DEPTH_TEST)
          self.gl.glEnable(self.gl.GL_TEXTURE_2D)
  
          self.gl.glClearColor(self.clearColor.redF(), self.clearColor.greenF(),
                               self.clearColor.blueF(), self.clearColor.alphaF())
  
          img = Image.open(self.path)
          img_data = img.convert("RGBA").tobytes("raw", "RGBA")
          self.texture_array.append(self.frameToTex(img_data, self.width, self.height))
  
      def frameToTex(self, data, width, height):
          texture_id = self.gl.glGenTextures(1)
  
          self.gl.glBindTexture(self.gl.GL_TEXTURE_2D, texture_id)
  
          self.gl.glTexParameterf(self.gl.GL_TEXTURE_2D, self.gl.GL_TEXTURE_MIN_FILTER, self.gl.GL_LINEAR_MIPMAP_LINEAR)
          self.gl.glTexParameterf(self.gl.GL_TEXTURE_2D, self.gl.GL_TEXTURE_MAG_FILTER, self.gl.GL_LINEAR)
  
          self.gl.glTexParameteri(self.gl.GL_TEXTURE_2D, self.gl.GL_GENERATE_MIPMAP, self.gl.GL_TRUE)
          self.gl.glTexImage2D(self.gl.GL_TEXTURE_2D, 0, self.gl.GL_RGBA, width,
                               height, 0, self.gl.GL_RGBA, self.gl.GL_UNSIGNED_BYTE,
                               data)
  
          return texture_id
  
      def paintGL(self):
          self.gl.glClear(self.gl.GL_COLOR_BUFFER_BIT | self.gl.GL_DEPTH_BUFFER_BIT)
          self.gl.glMatrixMode(self.gl.GL_MODELVIEW)
          self.gl.glLoadIdentity()
          self.gl.glBindTexture(self.gl.GL_TEXTURE_2D, self.texture_array[self.current_texture_index])
  
          self.gl.glRotatef(-90, 0.0, 0.0, 1.0)
  
          self.gl.glBegin(self.gl.GL_QUADS)
          self.gl.glTexCoord2f(0.0, 0.0)
          self.gl.glVertex2f(-1.0, -1.0)
          self.gl.glTexCoord2f(0.0, 1.0)
          self.gl.glVertex2f(1.0, -1.0)
          self.gl.glTexCoord2f(1.0, 1.0)
          self.gl.glVertex2f(1.0, 1.0)
          self.gl.glTexCoord2f(1.0, 0.0)
          self.gl.glVertex2f(-1.0, 1.0)
          self.gl.glEnd()
  
      def resizeGL(self, width, height):
          side = min(width, height)
          self.gl.glViewport((width - side) // 2, (height - side) // 2, side,
                             side)
  
  
  class Window(QWidget):
      def __init__(self):
          super(Window, self).__init__()
  
          main_layout = QGridLayout()
  
          main_layout.setContentsMargins(0, 0, 0, 0)
          widget = GLWidget('images/bg.jpg', 800, 480)
          main_layout.addWidget(widget)
  
          self.setLayout(main_layout)
          self.currentGlWidget = widget
          self.setWindowTitle("Texture Test")
  
      def setCurrentGlWidget(self):
          self.currentGlWidget = self.sender()
  
  
  if __name__ == '__main__':
      app = QApplication(sys.argv)
  
      format = QSurfaceFormat()
      format.setDepthBufferSize(24)
      QSurfaceFormat.setDefaultFormat(format)
  
      window = Window()
      window.show()
      sys.exit(app.exec_())
  </code></pre>
  
  <p>This code does not work when executed on the RPI. The following error is shown:</p>
  
  <pre><code>$ python3 GLWidget.py 
  MESA-LOADER: failed to retrieve device information
  MESA-LOADER: failed to retrieve device information
  MESA-LOADER: failed to retrieve device information
  Traceback (most recent call last):
    File "GLWidget.py", line 43, in initializeGL
      self.texture_array.append(self.frameToTex(img_data, self.width, self.height))
    File "GLWidget.py", line 46, in frameToTex
      texture_id = self.gl.glGenTextures(1)
  TypeError: QOpenGLFunctions_ES2.glGenTextures(): not enough arguments
  Abort
  </code></pre>
  
  <p>I looked up the signatures of both bindings which are these:</p>
  
  <p><a href="https://github.com/baoboa/pyqt5/blob/master/sip/_QOpenGLFunctions_2_0/qopenglfunctions_2_0.sip" rel="nofollow noreferrer">QOpenGLFunctions_2_0</a>:</p>
  
  <pre><code>void glGenTextures(GLsizei n, SIP_PYOBJECT *textures /TypeHint="Union[int, Tuple[int, ...]]"/);
  </code></pre>
  
  <p>and <a href="https://github.com/baoboa/pyqt5/blob/master/sip/_QOpenGLFunctions_ES2/qopenglfunctions_es2.sip" rel="nofollow noreferrer">QOpenGLFunctions_ES2</a>:</p>
  
  <pre><code>void glGenTextures(GLsizei n, SIP_PYOBJECT textures /TypeHint="Union[int, Tuple[int, ...]]"/);
  </code></pre>
  
  <p>Being unfamiliar with python-sip, I tried to use an int-array and passed it to glGenTexturesleads with no success. The array remains empty.</p>
  
  <p>How is it possible to make use of the RPI OpenGL support with PyQT5 in general and also specificly showing a simple image texture?</p>