2 * Copyright (C) 2011-2013 Team XBMC
5 * This Program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2, or (at your option)
10 * This Program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with XBMC; see the file COPYING. If not, see
17 * <http://www.gnu.org/licenses/>.
23 #include <boost/bind.hpp>
24 #include <boost/function.hpp>
25 #include <boost/scoped_ptr.hpp>
27 #include <wayland-client.h>
29 #include "windowing/DllWaylandClient.h"
30 #include "windowing/DllWaylandEgl.h"
33 #include "Compositor.h"
34 #include "OpenGLSurface.h"
37 #include "ShellSurface.h"
40 #include "windowing/WaylandProtocol.h"
41 #include "XBMCSurface.h"
47 class XBMCSurface::Private
51 Private(IDllWaylandClient &clientLibrary,
52 IDllWaylandEGL &eglLibrary,
53 const boost::scoped_ptr<Compositor> &compositor,
54 const boost::scoped_ptr<Shell> &shell,
58 typedef boost::function<struct wl_region * ()> RegionFactory;
60 IDllWaylandClient &m_clientLibrary;
61 IDllWaylandEGL &m_eglLibrary;
63 /* We only care about xbmc::Compositor's CreateRegion function
64 * and don't want to store a pointer to the compositor to create
66 RegionFactory m_regionFactory;
68 boost::scoped_ptr<Surface> m_surface;
69 boost::scoped_ptr<ShellSurface> m_shellSurface;
70 boost::scoped_ptr<OpenGLSurface> m_glSurface;
71 boost::scoped_ptr<Callback> m_frameCallback;
73 void OnFrameCallback(uint32_t);
74 void AddFrameCallback();
79 namespace xw = xbmc::wayland;
81 /* Creating a new xbmc::wayland::XBMCSurface effectively creates
82 * an OpenGL ES bindable EGL Window and a corresponding
83 * surface object for the compositor to display it on-screen. It also
84 * creates a "shell surface", which is a special extension to a normal
85 * surface which adds window-management functionality to a surface.
87 * If there are any errors in creating the surface they will be thrown
88 * as std::runtime_errors and the object that creates this one
89 * needs to handle catching them.
91 xw::XBMCSurface::Private::Private(IDllWaylandClient &clientLibrary,
92 IDllWaylandEGL &eglLibrary,
93 const boost::scoped_ptr<Compositor> &compositor,
94 const boost::scoped_ptr<Shell> &shell,
97 m_clientLibrary(clientLibrary),
98 m_eglLibrary(eglLibrary),
99 m_regionFactory(boost::bind(&Compositor::CreateRegion,
101 m_surface(new xw::Surface(m_clientLibrary,
102 compositor->CreateSurface())),
103 m_shellSurface(new xw::ShellSurface(m_clientLibrary,
104 shell->CreateShellSurface(
105 m_surface->GetWlSurface()))),
106 /* Creating a new xbmc::wayland::OpenGLSurface will manage the
107 * attach-and-commit process on eglSwapBuffers */
108 m_glSurface(new xw::OpenGLSurface(m_eglLibrary,
109 m_surface->GetWlSurface(),
113 /* SetOpaqueRegion here is an important optimization for the
114 * compositor. It effectively tells it that this window is completely
115 * opaque. This means that the window can be rendered without
116 * the use of GL_BLEND which represents a substantial rendering
117 * speedup, especially for larger surfaces. It also means that
118 * this window can be placed in an overlay plane, so it can
119 * skip compositing alltogether */
120 xw::Region region(m_clientLibrary, m_regionFactory());
122 region.AddRectangle(0, 0, 640, 480);
124 m_surface->SetOpaqueRegion(region.GetWlRegion());
127 /* The compositor is responsible for letting us know when to
128 * draw things. This is effectively to conserve battery life
129 * where drawing our surface would be a futile operation. Its not
130 * entirely applicable to the xbmc case because we use a game loop,
131 * but some compositor expect it, so we must add a frame callback
132 * as soon as the surface is ready to be rendered to */
136 xw::XBMCSurface::XBMCSurface(IDllWaylandClient &clientLibrary,
137 IDllWaylandEGL &eglLibrary,
138 const boost::scoped_ptr<Compositor> &compositor,
139 const boost::scoped_ptr<Shell> &shell,
142 priv(new Private(clientLibrary,
151 /* A defined destructor is required such that
152 * boost::scoped_ptr<Private>::~scoped_ptr is generated here */
153 xw::XBMCSurface::~XBMCSurface()
158 xw::XBMCSurface::Show()
160 protocol::CallMethodOnWaylandObject(priv->m_clientLibrary,
161 priv->m_shellSurface->GetWlShellSurface(),
162 WL_SHELL_SURFACE_SET_TOPLEVEL);
166 xw::XBMCSurface::Resize(uint32_t width, uint32_t height)
168 /* Since the xbmc::wayland::OpenGLSurface owns the buffer, it is
169 * responsible for changing its size. When the size changes, the
170 * opaque region must also change */
171 priv->m_glSurface->Resize(width, height);
173 xw::Region region(priv->m_clientLibrary,
174 priv->m_regionFactory());
176 region.AddRectangle(0, 0, width, height);
178 priv->m_surface->SetOpaqueRegion(region.GetWlRegion());
179 priv->m_surface->Commit();
182 EGLNativeWindowType *
183 xw::XBMCSurface::EGLNativeWindow() const
185 return priv->m_glSurface->GetEGLNativeWindow();
188 void xw::XBMCSurface::Private::OnFrameCallback(uint32_t time)
193 void xw::XBMCSurface::Private::AddFrameCallback()
195 m_frameCallback.reset(new xw::Callback(m_clientLibrary,
196 m_surface->CreateFrameCallback(),
197 boost::bind(&Private::OnFrameCallback,