Revision control

++ // Copyright (C) 2016 The Qt Company Ltd.
++ // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
++
++ /*!
++ \example openglwindow
++ \title OpenGL Window Example
++ \ingroup examples-widgets-opengl
++ \examplecategory {Graphics}
++
++ \brief This example shows how to create a minimal QWindow based application
++ for the purpose of using OpenGL.
++
++ \image openglwindow-example.png Screenshot of the OpenGLWindow example
++
++ \note This is a low level example of how to use QWindow with OpenGL.
++ In practice you should consider using the higher level QOpenGLWindow class.
++ See the \l{Hello GLES3 Example} for a demonstration of the QOpenGLWindow
++ convenience class.
++
++ \section1 OpenGLWindow Super Class
++
++ Our OpenGLWindow class acts as an API which is then subclassed to do the
++ actual rendering. It has functions to make a request for render() to be
++ called, either immediately with renderNow() or as soon as the event loop
++ has finished processing the current batch of events with renderLater().
++ The OpenGLWindow subclass can either reimplement render() for OpenGL based
++ rendering, or render(QPainter *) for rendering with a QPainter. Use
++ OpenGLWindow::setAnimating(true) for render() to be called at the vertical
++ refresh rate, assuming vertical sync is enabled in the underlying OpenGL
++ drivers.
++
++ In the class that does the OpenGL rendering you will typically want to
++ inherit from QOpenGLFunctions, as our OpenGLWindow does, in order to get
++ platform independent access to OpenGL ES 2.0 functions. By inheriting from
++ QOpenGLFunctions the OpenGL functions it contains will get precedence, and
++ you will not have to worry about resolving those functions if you want your
++ application to work with OpenGL as well as OpenGL ES 2.0.
++
++ \snippet openglwindow/openglwindow.h 1
++
++ The window's surface type must be set to QSurface::OpenGLSurface to
++ indicate that the window is to be used for OpenGL rendering and not for
++ rendering raster content with QPainter using a QBackingStore.
++
++ \snippet openglwindow/openglwindow.cpp 1
++
++ Any OpenGL initialization needed can be done by overriding the initialize()
++ function, which is called once before the first call to render(), with a
++ valid current QOpenGLContext. As can be seen in the following code snippet,
++ the default render(QPainter *) and initialize() implementations are empty,
++ whereas the default render() implementation initializes a
++ QOpenGLPaintDevice and then calls into render(QPainter *).
++
++ \snippet openglwindow/openglwindow.cpp 2
++
++ The renderLater() function simply calls QWindow::requestUpdate() to schedule
++ an update for when the system is ready to repaint.
++
++ We also call renderNow() when we get an expose event. The exposeEvent() is
++ the notification to the window that its exposure, meaning visibility, on
++ the screen has changed. When the expose event is received you can query
++ QWindow::isExposed() to find out whether or not the window is currently
++ exposed. Do not render to or call QOpenGLContext::swapBuffers() on a window
++ before it has received its first expose event, as before then its final
++ size might be unknown, and in addition what is rendered might not even end
++ up on the screen.
++
++ \snippet openglwindow/openglwindow.cpp 3
++
++ In renderNow() we return if we are not currently exposed, in which case
++ rendering is delayed until we actually get an expose event. If we have not
++ yet done so, we create the QOpenGLContext with the same QSurfaceFormat as
++ was set on the OpenGLWindow, and call initialize() for the sake of the sub
++ class, and initializeOpenGLFunctions() in order for the QOpenGLFunctions
++ super class to be associated with the correct QOpenGLContext. In any case
++ we make the context current by calling QOpenGLContext::makeCurrent(), call
++ render() to do the actual rendering, and finally we schedule for the
++ rendered contents to be made visible by calling
++ QOpenGLContext::swapBuffers() with the OpenGLWindow as parameter.
++
++ Once the rendering of a frame using an OpenGL context is initiated by
++ calling QOpenGLContext::makeCurrent(), giving the surface on which to
++ render as a parameter, OpenGL commands can be issued. The commands can be
++ issued either directly by including <qopengl.h>, which also includes the
++ system's OpenGL headers, or as by using QOpenGLFunctions, which can
++ either be inherited from for convenience, or accessed using
++ QOpenGLContext::functions(). QOpenGLFunctions gives access to all the
++ OpenGL ES 2.0 level OpenGL calls that are not already standard in both
++ OpenGL ES 2.0 and desktop OpenGL. For more information about the OpenGL and
++ OpenGL ES APIs, refer to the official \l{http://www.opengl.org/registry/}{OpenGL Registry} and
++ \l {http://www.khronos.org/registry/gles/}{Khronos OpenGL ES API Registry}.
++
++ If animation has been enabled with OpenGLWindow::setAnimating(true), we
++ call renderLater() to schedule another update request.
++
++ \snippet openglwindow/openglwindow.cpp 4
++
++ Enabling animation also schedules an update request as shown in the
++ following code snippet.
++
++ \snippet openglwindow/openglwindow.cpp 5
++
++ \section1 Example OpenGL Rendering Sub Class
++
++ Here we sub class OpenGLWindow to show how to do OpenGL to render a
++ rotating triangle. By indirectly sub classing QOpenGLFunctions we gain
++ access to all OpenGL ES 2.0 level functionality.
++
++ \snippet openglwindow/main.cpp 1
++
++ In our main function we initialize QGuiApplication and instantiate our
++ TriangleOpenGLWindow. We give it a QSurfaceFormat specifying that we want
++ four samples of multisample antialiasing, as well as a default geometry.
++ Since we want to have animation we call the above mentioned setAnimating()
++ function with an argument of true.
++
++ \snippet openglwindow/main.cpp 2
++
++ The following code snippet shows the OpenGL shader program used in this
++ example. The vertex and fragment shaders are relatively simple, doing
++ vertex transformation and interpolated vertex coloring.
++
++ \snippet openglwindow/main.cpp 3
++
++ Here is the code that loads the shaders and initializes the shader program
++ By using QOpenGLShaderProgram instead of raw OpenGL we get the convenience
++ that strips out the highp, mediump, and lowp qualifiers on desktop OpenGL,
++ where they are not part of the standard. We store the attribute and uniform
++ locations in member variables to avoid having to do the location lookup
++ each frame.
++
++ \snippet openglwindow/main.cpp 4
++
++ Finally, here is our render() function, where we use OpenGL to set up the
++ viewport, clear the background, and render a rotating triangle.
++
++ \snippet openglwindow/main.cpp 5
++ */