blob: 8d3114bf8444606d997001a1bac6d6714ceb1ded [file] [log] [blame]
// Copyright 2016 The Android Open Source Project
// This software is licensed under the terms of the GNU General Public
// License version 2, as published by the Free Software Foundation, and
// may be copied, distributed, and modified under those terms.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
#pragma once
#include "android/skin/qt/gl-canvas.h"
#include "android/skin/qt/gl-texture-draw.h"
#include "OpenGLESDispatch/GLESv2Dispatch.h"
#include <cmath>
#include <memory>
#include <QWidget>
struct EGLState;
struct EGLDispatch;
// Helper class used to perform EGL/GLESv2 rendering inside a Qt widget.
// Relies on EmuGL's OpenGLESDispatch library to access the correct set of
// host graphics libraries, and provide dispatch tables to call their functions.
//
// Client should create a derived class and override initGL(), repaintGL()
// and resizeGL() properly. These methods can use the |mEGL| and |mGLES2|
// fields to perform EGL/GLESv2 calls.
class GLWidget : public QWidget {
Q_OBJECT
public:
explicit GLWidget(QWidget* parent = 0);
virtual ~GLWidget();
QPaintEngine* paintEngine() const override { return nullptr; }
bool readyForRendering() const { return mValid; }
public slots:
void renderFrame();
bool makeContextCurrent();
private slots:
void handleScreenChange(QScreen*);
protected:
// Dispatch tables for EGL and GLESv2 APIs. Note that these will be nullptr
// if there was a problem when loading the host libraries.
const EGLDispatch* mEGL;
const GLESv2Dispatch* mGLES2;
// Called the first time a frame needs to be rendered by the widget.
// This will always happen before the first repaintGL() or resizeGL()
// call. The implementation can assume that |mEGL| and |mGLES2| are valid,
// and that the widget's context is already set.
// This function should return true if the initialization is successful and
// false otherwise.
virtual bool initGL() { return true; }
// Called whenever a frame needs to be repainted by the widget.
// The implementation can assume that |mEGL| and |mGLES2| are valid,
// and that the widget's context is already set.
virtual void repaintGL() {}
// Called whenever the widget needs to be resized and updated.
// Note that this will always followed by a call to repaintGL(). The
// implementation can assume that |mEGL| and |mGLES2| are valid and that
// the widget's context is already set. |w| and |h| are the widget's
// new dimensions in pixels.
virtual void resizeGL(int w, int h) {}
int realPixelsWidth() const { return std::ceil(width() * devicePixelRatio()); }
int realPixelsHeight() const { return std::ceil(height() * devicePixelRatio()); }
void toggleAA() { mEnableAA = !mEnableAA; }
private:
void paintEvent(QPaintEvent*) override;
void resizeEvent(QResizeEvent*) override;
void showEvent(QShowEvent*) override;
bool ensureInit();
void destroyContext();
EGLState* mEGLState;
bool mValid;
std::unique_ptr<GLCanvas> mCanvas;
std::unique_ptr<TextureDraw> mTextureDraw;
bool mEnableAA;
};