Gamp v0.0.8
Gamp: Graphics, Audio, Multimedia and Processing
Loading...
Searching...
No Matches
Surface.hpp
Go to the documentation of this file.
1/*
2 * Author: Sven Gothel <sgothel@jausoft.com>
3 * Copyright Gothel Software e.K.
4 *
5 * SPDX-License-Identifier: MIT
6 *
7 * This Source Code Form is subject to the terms of the MIT License
8 * If a copy of the MIT was not distributed with this file,
9 * you can obtain one at https://opensource.org/license/mit/.
10 */
11#ifndef GAMP_WTSURFACE_HPP_
12#define GAMP_WTSURFACE_HPP_
13
14#include <jau/fraction_type.hpp>
15#include <jau/int_types.hpp>
16#include <jau/locks.hpp>
17
18#include <gamp/GampTypes.hpp>
21
22namespace gamp::wt {
23 /** \addtogroup Gamp_WT
24 *
25 * @{
26 */
27 class Window;
28 class Surface;
29 typedef std::shared_ptr<Surface> SurfaceSRef;
30
31 using namespace jau::fractions_i64_literals;
32 using namespace jau::math;
33
34 //
35 // TODO: GraphicsConfiguration: Screen + Device?
36 //
37
38 class Surface : public std::enable_shared_from_this<Surface> {
39 public:
40 static constexpr const jau::fraction_i64 TIMEOUT = 5_s;
41
46 static constexpr bool is_locked(const lock_status_t ls) noexcept {
47 return static_cast<uint16_t>(lock_status_t::not_ready) < static_cast<uint16_t>(ls);
48 }
49
50 private:
51 int m_swapInterval = -1;
52 handle_t m_surface_handle;
53 /// Surface client-area size in pixel units
54 Vec2i m_surface_size;
55 CapabilitiesPtr m_capsptr_req;
56 CapabilitiesPtr m_capsptr_chosen;
57 gamp::render::RenderContextPtr m_renderContext;
58
59 jau::RecursiveLock m_surface_lock;
60
61 void disposeImpl(handle_t) noexcept {}
62 bool setSwapIntervalImpl(int v) noexcept;
63 static CapabilitiesPtr retrieveCaps(const wt::SurfaceSRef& surface) noexcept;
64
65 protected:
66 static void setCaps(handle_t surface_handle, const Capabilities& requested) noexcept;
67 struct Private{ explicit Private() = default; };
68
69 template <typename ChildT>
70 std::shared_ptr<ChildT> shared_from_base() {
71 return std::static_pointer_cast<ChildT>(shared_from_this());
72 }
73
74 void setSurfaceSize(const Vec2i& sz) noexcept { m_surface_size = sz; }
75
77 virtual void nativeSurfaceUnlock() noexcept { }
78
79 public:
80 /** Private ctor for single Surface::create() method w/o public ctor. */
81 Surface(Private, handle_t surface_handle, const Vec2i& surface_size, const Capabilities &requested)
82 : m_surface_handle(surface_handle), m_surface_size(surface_size), m_capsptr_req(requested.clone()) { }
83
84 static SurfaceSRef create(handle_t surface_handle, const Vec2i& surface_size, const Capabilities &requested) {
85 return std::make_shared<Surface>(Private(), surface_handle, surface_size, requested);
86 }
87
88 Surface(const Surface&) = delete;
89 void operator=(const Surface&) = delete;
90
91 /**
92 * Releases this instance.
93 */
94 virtual ~Surface() noexcept {
95 if( m_surface_lock.isOwner() ) {
97 }
98 }
99
100 virtual void disposedNotify(const jau::fraction_timespec&) noexcept {
101 m_surface_handle = 0;
102 m_renderContext = nullptr;
103 }
104 virtual void dispose(const jau::fraction_timespec&) noexcept {
105 if( m_renderContext ) {
106 m_renderContext->dispose();
107 m_renderContext = nullptr;
108 }
109 if( m_surface_handle ) {
110 disposeImpl(m_surface_handle);
111 m_surface_handle = 0;
112 }
113 }
114
115 const SurfaceSRef shared() { return shared_from_this(); }
116
118 gamp::render::RenderContextPtr rc = createContext(shared(), profile, contextFlags, nullptr);
119 if( rc && rc->isValid() ) {
120 m_renderContext = std::move(rc);
121 m_capsptr_chosen = retrieveCaps(shared());
122 return true;
123 }
124 return false;
125 }
127 const gamp::render::RenderProfile& profile,
128 const gamp::render::RenderContextFlags& contextFlags,
129 gamp::render::RenderContext* shareWith) noexcept;
130
132 return m_renderContext ? m_renderContext.get() : nullptr;
133 }
135 return m_renderContext ? m_renderContext.get() : nullptr;
136 }
137
138 /// Returns the chosen (retrieved) capabilities of a realized surface
139 const Capabilities* capabilities() const noexcept { return m_capsptr_chosen ? m_capsptr_chosen.get() : nullptr; }
140
141 /// Sets the requested capabilities for a surface to be realized
142 void setRequestedCapabilities(CapabilitiesPtr &&req) noexcept { m_capsptr_req = std::move(req); }
143
144 /**
145 * Returns desired or determined swap interval. Defaults to -1, i.e. adaptive swap interval.
146 *
147 * Use setSwapInterval() to set the swap interval.
148 *
149 * * [1..n] denotes the swap interval
150 * * 0 indicates no swap interval, e.g. by failed setSwapInterval()
151 * * -1 indicates adaptive swap interval
152 */
153 constexpr int swapInterval() const noexcept { return m_swapInterval; }
154
155 /** Returns true if swap interval could be set with the native toolkit post createContext(). See swapInterval(). */
156 bool setSwapInterval(int v) noexcept {
157 if( m_renderContext && m_renderContext->isValid() ) {
158 return setSwapIntervalImpl(v);
159 }
160 m_swapInterval=v;
161 return false;
162 }
163
164 /**
165 * Returns <code>true</code> if this surface is rendered in
166 * OpenGL's coordinate system, <i>origin at bottom left</i>.
167 * Otherwise returns <code>false</code>, i.e. <i>origin at top left</i>.
168 *
169 * Default impl. is <code>true</code>, i.e. OpenGL bottom-left coordinate system.
170 *
171 * Currently only MS-Windows bitmap offscreen drawable uses a non OpenGL orientation and hence returns <code>false</code>.<br/>
172 * This removes the need of a vertical flip when used in AWT or Windows applications.
173 */
174 constexpr bool isBLOriented() const noexcept { return true; }
175
176 /** Returns the surface size of the client area excluding insets (window decorations) in pixel units. */
177 constexpr const Vec2i& surfaceSize() const noexcept { return m_surface_size; }
178
179 /**
180 * Returns the handle to the surface for this NativeSurface. <P>
181 *
182 * The surface handle should be set/update by {@link #lockSurface()},
183 * where {@link #unlockSurface()} is not allowed to modify it.
184 * After {@link #unlockSurface()} it is no more guaranteed
185 * that the surface handle is still valid.
186 *
187 * The surface handle shall reflect the platform one
188 * for all drawable surface operations, e.g. opengl, swap-buffer. <P>
189 *
190 * On X11 this returns an entity of type Window,
191 * since there is no differentiation of surface and window there. <BR>
192 * On Microsoft Windows this returns an entity of type HDC.
193 */
194 constexpr handle_t surfaceHandle() const noexcept { return m_surface_handle; }
195
196 virtual bool isValid() const noexcept { return 0 != m_surface_handle; }
197
198 /**
199 * Provide a mechanism to utilize custom (pre-) swap surface
200 * code. This method is called before the render toolkit (e.g. JOGL)
201 * swaps the buffer/surface if double buffering is enabled.
202 *
203 * The implementation may itself apply the swapping,
204 * in which case true shall be returned.
205 *
206 * @return true if this method completed swapping the surface,
207 * otherwise false, in which case eg the GLDrawable
208 * implementation has to swap the code.
209 */
210 virtual bool surfaceSwap() noexcept { return true; }
211
212 /**
213 * Lock the surface of this native window.
214 *
215 * The surface handle shall be valid after a successfull call,
216 * i.e. return a value other than lock_status_t::unlocked and lock_status_t::not_ready.
217 *
218 * The caller may need to take care of the result lock_status_t::locked_changed,
219 * where the surface handle is valid but has changed.
220 *
221 * This call is blocking until the surface has been locked
222 * or a timeout is reached. The latter will throw a runtime exception.
223 *
224 * This call allows recursion from the same thread.
225 *
226 * The implementation may want to aquire the
227 * application level {@link com.jogamp.common.util.locks.RecursiveLock}
228 * first before proceeding with a native surface lock.
229 *
230 * The implementation shall also invoke {@link AbstractGraphicsDevice#lock()}
231 * for the initial lock (recursive count zero).
232 *
233 * @return Surface::lock_status_t
234 *
235 * @throws RuntimeException after timeout when waiting for the surface lock
236 * @throws NativeWindowException if native locking failed, maybe platform related
237 */
239 if( !m_surface_lock.tryLock(TIMEOUT) ) {
240 throw jau::RuntimeException("Waited "+TIMEOUT.toString()+"s for: "+toString()+" - "+jau::threadName(std::this_thread::get_id()), E_FILE_LINE);
241 }
242 if (1 == m_surface_lock.holdCount()) {
243 const lock_status_t res = nativeSurfaceLock();
244 if( !is_locked(res) ) {
245 m_surface_lock.unlock();
246 }
247 return res;
248 } else {
250 }
251 }
252
253 /**
254 * Unlock the surface of this native window
255 *
256 * Shall not modify the surface handle, see lockSurface().
257 *
258 * The implementation shall also invoke GraphicsDevice::unlock()
259 * for the final unlock (recursive count zero).
260 *
261 * The implementation shall be fail safe, i.e. tolerant in case the native resources
262 * are already released / unlocked. In this case the implementation shall simply ignore the call.
263 *
264 * @see lockSurface()
265 */
267 m_surface_lock.validateLocked();
268 if (1 == m_surface_lock.holdCount()) {
270 }
271 m_surface_lock.unlock();
272 }
273
274 std::string toString() const noexcept {
275 std::string res = "Surface[";
276 res.append("handle ").append(jau::toHexString(m_surface_handle))
277 .append(", ").append(m_renderContext ? m_renderContext->toString() : "nil-ctx")
278 .append(", size ").append(m_surface_size.toString())
279 .append(", caps[req ").append(m_capsptr_req->toString())
280 .append(", chosen ").append(m_capsptr_chosen?m_capsptr_chosen->toString():"nocaps")
281 .append("]");
282 return res;
283 }
284 };
285 /**@}*/
286} // namespace gamp::wt
287
288#endif /* GAMP_WTSURFACE_HPP_ */
Specifies the render profile.
Specifies a set of capabilities that a window's rendering context must support, such as color depth p...
void operator=(const Surface &)=delete
gamp::render::RenderContext * renderContext() noexcept
Definition Surface.hpp:134
static constexpr bool is_locked(const lock_status_t ls) noexcept
Definition Surface.hpp:46
static SurfaceSRef create(handle_t surface_handle, const Vec2i &surface_size, const Capabilities &requested)
Definition Surface.hpp:84
constexpr handle_t surfaceHandle() const noexcept
Returns the handle to the surface for this NativeSurface.
Definition Surface.hpp:194
lock_status_t lockSurface()
Lock the surface of this native window.
Definition Surface.hpp:238
const SurfaceSRef shared()
Definition Surface.hpp:115
const gamp::render::RenderContext * renderContext() const noexcept
Definition Surface.hpp:131
Surface(const Surface &)=delete
void setSurfaceSize(const Vec2i &sz) noexcept
Definition Surface.hpp:74
void unlockSurface()
Unlock the surface of this native window.
Definition Surface.hpp:266
std::string toString() const noexcept
Definition Surface.hpp:274
Surface(Private, handle_t surface_handle, const Vec2i &surface_size, const Capabilities &requested)
Private ctor for single Surface::create() method w/o public ctor.
Definition Surface.hpp:81
virtual ~Surface() noexcept
Releases this instance.
Definition Surface.hpp:94
virtual bool isValid() const noexcept
Definition Surface.hpp:196
static void setCaps(handle_t surface_handle, const Capabilities &requested) noexcept
virtual void nativeSurfaceUnlock() noexcept
Definition Surface.hpp:77
constexpr int swapInterval() const noexcept
Returns desired or determined swap interval.
Definition Surface.hpp:153
std::shared_ptr< ChildT > shared_from_base()
Definition Surface.hpp:70
constexpr bool isBLOriented() const noexcept
Returns true if this surface is rendered in OpenGL's coordinate system, origin at bottom left.
Definition Surface.hpp:174
virtual bool surfaceSwap() noexcept
Provide a mechanism to utilize custom (pre-) swap surface code.
Definition Surface.hpp:210
void setRequestedCapabilities(CapabilitiesPtr &&req) noexcept
Sets the requested capabilities for a surface to be realized.
Definition Surface.hpp:142
const Capabilities * capabilities() const noexcept
Returns the chosen (retrieved) capabilities of a realized surface.
Definition Surface.hpp:139
virtual void dispose(const jau::fraction_timespec &) noexcept
Definition Surface.hpp:104
static constexpr const jau::fraction_i64 TIMEOUT
Definition Surface.hpp:40
virtual void disposedNotify(const jau::fraction_timespec &) noexcept
Definition Surface.hpp:100
constexpr const Vec2i & surfaceSize() const noexcept
Returns the surface size of the client area excluding insets (window decorations) in pixel units.
Definition Surface.hpp:177
bool setSwapInterval(int v) noexcept
Returns true if swap interval could be set with the native toolkit post createContext().
Definition Surface.hpp:156
virtual lock_status_t nativeSurfaceLock() noexcept
Definition Surface.hpp:76
bool createContext(const gamp::render::RenderProfile &profile, const gamp::render::RenderContextFlags &contextFlags)
Definition Surface.hpp:117
#define E_FILE_LINE
fraction< int64_t > fraction_i64
fraction using int64_t as integral type
std::unique_ptr< RenderContext > RenderContextPtr
RenderContextFlags
OpenGL context flags.
std::shared_ptr< Surface > SurfaceSRef
std::unique_ptr< Capabilities > CapabilitiesPtr
uintptr_t handle_t
A native handle type, big enough to store a pointer.
Definition GampTypes.hpp:52
Vector2I< int > Vec2i
Definition vec2i.hpp:321
std::string toHexString(const void *data, const nsize_t length, const lb_endian_t byteOrder=lb_endian_t::big, const LoUpCase capitalization=LoUpCase::lower, const PrefixOpt prefix=PrefixOpt::prefix) noexcept
Produce a hexadecimal string representation of the given lsb-first byte values.
Requirement (concept) Definitions.
std::string threadName(const std::thread::id id) noexcept
Timespec structure using int64_t for its components in analogy to struct timespec_t on 64-bit platfor...