| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186 |
- // This file is part of Desktop App Toolkit,
- // a set of libraries for developing nice desktop applications.
- //
- // For license and copyright information please follow this link:
- // https://github.com/desktop-app/legal/blob/master/LEGAL
- //
- #include "ui/gl/gl_surface.h"
- #include "ui/rp_widget.h"
- #include "ui/painter.h"
- #include <QtCore/QCoreApplication>
- #include <QtGui/QtEvents>
- #include <QtGui/QOpenGLContext>
- #include <QtGui/QWindow>
- #include <QOpenGLWidget>
- namespace Ui::GL {
- namespace {
- struct SurfaceTraits : RpWidgetDefaultTraits {
- static constexpr bool kSetZeroGeometry = false;
- };
- class SurfaceOpenGL final
- : public RpWidgetBase<QOpenGLWidget, SurfaceTraits> {
- public:
- SurfaceOpenGL(QWidget *parent, std::unique_ptr<Renderer> renderer);
- ~SurfaceOpenGL();
- private:
- void initializeGL() override;
- void resizeEvent(QResizeEvent *e) override;
- void resizeGL(int w, int h) override;
- void paintEvent(QPaintEvent *e) override;
- void paintGL() override;
- bool eventHook(QEvent *e) override;
- void callDeInit();
- const std::unique_ptr<Renderer> _renderer;
- QMetaObject::Connection _connection;
- QSize _deviceSize;
- };
- class SurfaceRaster final : public RpWidgetBase<QWidget, SurfaceTraits> {
- public:
- SurfaceRaster(QWidget *parent, std::unique_ptr<Renderer> renderer);
- private:
- void paintEvent(QPaintEvent *e) override;
- const std::unique_ptr<Renderer> _renderer;
- };
- SurfaceOpenGL::SurfaceOpenGL(
- QWidget *parent,
- std::unique_ptr<Renderer> renderer)
- : RpWidgetBase<QOpenGLWidget, SurfaceTraits>(parent)
- , _renderer(std::move(renderer)) {
- setUpdateBehavior(QOpenGLWidget::PartialUpdate);
- }
- SurfaceOpenGL::~SurfaceOpenGL() {
- callDeInit();
- }
- void SurfaceOpenGL::initializeGL() {
- if (_connection) {
- QObject::disconnect(base::take(_connection));
- }
- const auto context = this->context();
- _connection = QObject::connect(
- context,
- &QOpenGLContext::aboutToBeDestroyed,
- [=] { callDeInit(); });
- _renderer->init(this, *context->functions());
- }
- void SurfaceOpenGL::resizeEvent(QResizeEvent *e) {
- if (!window()->windowHandle()) {
- return;
- }
- QOpenGLWidget::resizeEvent(e);
- }
- void SurfaceOpenGL::resizeGL(int w, int h) {
- _deviceSize = QSize(w, h) * devicePixelRatio();
- _renderer->resize(this, *context()->functions(), w, h);
- }
- void SurfaceOpenGL::paintEvent(QPaintEvent *e) {
- if (_deviceSize != size() * devicePixelRatio()) {
- QCoreApplication::postEvent(this, new QResizeEvent(size(), size()));
- }
- QOpenGLWidget::paintEvent(e);
- }
- void SurfaceOpenGL::paintGL() {
- if (!updatesEnabled() || size().isEmpty() || !isValid()) {
- return;
- }
- const auto f = context()->functions();
- if (const auto bg = _renderer->clearColor()) {
- f->glClearColor(bg->redF(), bg->greenF(), bg->blueF(), bg->alphaF());
- f->glClear(GL_COLOR_BUFFER_BIT);
- }
- f->glDisable(GL_BLEND);
- _renderer->paint(this, *f);
- }
- bool SurfaceOpenGL::eventHook(QEvent *e) {
- const auto result = RpWidgetBase::eventHook(e);
- if (e->type() == QEvent::ScreenChangeInternal) {
- _deviceSize = size() * devicePixelRatio();
- }
- return result;
- }
- void SurfaceOpenGL::callDeInit() {
- if (!_connection) {
- return;
- }
- QObject::disconnect(base::take(_connection));
- makeCurrent();
- const auto context = this->context();
- _renderer->deinit(
- this,
- ((isValid() && context && QOpenGLContext::currentContext() == context)
- ? context->functions()
- : nullptr));
- }
- SurfaceRaster::SurfaceRaster(
- QWidget *parent,
- std::unique_ptr<Renderer> renderer)
- : RpWidgetBase<QWidget, SurfaceTraits>(parent)
- , _renderer(std::move(renderer)) {
- }
- void SurfaceRaster::paintEvent(QPaintEvent *e) {
- _renderer->paintFallback(Painter(this), e->region(), Backend::Raster);
- }
- } // namespace
- void Renderer::paint(
- not_null<QOpenGLWidget*> widget,
- QOpenGLFunctions &f) {
- paintFallback(Painter(widget.get()), widget->rect(), Backend::OpenGL);
- }
- std::unique_ptr<RpWidgetWrap> CreateSurface(
- Fn<ChosenRenderer(Capabilities)> chooseRenderer) {
- auto chosen = chooseRenderer(CheckCapabilities(nullptr));
- switch (chosen.backend) {
- case Backend::OpenGL:
- return std::make_unique<SurfaceOpenGL>(
- nullptr,
- std::move(chosen.renderer));
- case Backend::Raster:
- return std::make_unique<SurfaceRaster>(
- nullptr,
- std::move(chosen.renderer));
- }
- Unexpected("Backend value in Ui::GL::CreateSurface.");
- }
- std::unique_ptr<RpWidgetWrap> CreateSurface(
- QWidget *parent,
- ChosenRenderer chosen) {
- switch (chosen.backend) {
- case Backend::OpenGL:
- return std::make_unique<SurfaceOpenGL>(
- parent,
- std::move(chosen.renderer));
- case Backend::Raster:
- return std::make_unique<SurfaceRaster>(
- parent,
- std::move(chosen.renderer));
- }
- Unexpected("Backend value in Ui::GL::CreateSurface.");
- }
- } // namespace Ui::GL
|