1 /*
2  * SPDX-FileCopyrightText: 2017-2017 CSSlayer <wengxt@gmail.com>
3  *
4  * SPDX-License-Identifier: LGPL-2.1-or-later
5  *
6  */
7 #include "config.h"
8 
9 #ifdef CAIRO_EGL_FOUND
10 
11 #include <cairo/cairo-gl.h>
12 #include <wayland-egl.h>
13 #include "waylandeglwindow.h"
14 #include "wl_callback.h"
15 
16 namespace fcitx {
17 namespace classicui {
WaylandEGLWindow(WaylandUI * ui)18 WaylandEGLWindow::WaylandEGLWindow(WaylandUI *ui)
19     : WaylandWindow(ui), window_(nullptr), cairoSurface_(nullptr) {}
20 
~WaylandEGLWindow()21 WaylandEGLWindow::~WaylandEGLWindow() { destroyWindow(); }
22 
createWindow()23 void WaylandEGLWindow::createWindow() { WaylandWindow::createWindow(); }
24 
destroyWindow()25 void WaylandEGLWindow::destroyWindow() {
26     hide();
27     WaylandWindow::destroyWindow();
28 }
29 
prerender()30 cairo_surface_t *WaylandEGLWindow::prerender() {
31     if (width_ == 0 || height_ == 0) {
32         hide();
33         return nullptr;
34     }
35 
36     if (!window_) {
37         window_.reset(wl_egl_window_create(*surface_, width_, height_));
38     }
39     if (window_ && !eglSurface_) {
40         eglSurface_ = ui_->createEGLSurface(window_.get(), nullptr);
41     }
42     if (eglSurface_ && !cairoSurface_) {
43         cairoSurface_.reset(
44             ui_->createEGLCairoSurface(eglSurface_, width_, height_));
45     }
46     if (!cairoSurface_) {
47         return nullptr;
48     }
49     int width, height;
50     wl_egl_window_get_attached_size(window_.get(), &width, &height);
51     if (width != static_cast<int>(width_) ||
52         height != static_cast<int>(height_)) {
53         wl_egl_window_resize(window_.get(), width_, height_, 0, 0);
54     }
55     cairo_gl_surface_set_size(cairoSurface_.get(), width_, height_);
56     if (cairo_surface_status(cairoSurface_.get()) != CAIRO_STATUS_SUCCESS) {
57         return nullptr;
58     }
59 
60     return cairoSurface_.get();
61 }
62 
render()63 void WaylandEGLWindow::render() {
64     if (cairo_surface_status(cairoSurface_.get()) != CAIRO_STATUS_SUCCESS) {
65         return;
66     }
67     cairo_gl_surface_swapbuffers(cairoSurface_.get());
68     callback_.reset(surface_->frame());
69     callback_->done().connect([this](uint32_t) { callback_.reset(); });
70 }
71 
hide()72 void WaylandEGLWindow::hide() {
73     cairoSurface_.reset();
74     if (eglSurface_) {
75         ui_->destroyEGLSurface(eglSurface_);
76         eglSurface_ = nullptr;
77     }
78     window_.reset();
79     surface_->attach(nullptr, 0, 0);
80     surface_->commit();
81 }
82 } // namespace classicui
83 } // namespace fcitx
84 
85 #endif
86