Merge lp:~raof/mir/check-for-surfaceless into lp:mir
- check-for-surfaceless
- Merge into development-branch
Status: | Merged |
---|---|
Approved by: | Alan Griffiths |
Approved revision: | no longer in the source branch. |
Merged at revision: | 1297 |
Proposed branch: | lp:~raof/mir/check-for-surfaceless |
Merge into: | lp:mir |
Diff against target: |
928 lines (+406/-151) 21 files modified
include/platform/mir/graphics/gl_context.h (+2/-2) include/server/mir/graphics/gl_extensions_base.h (+3/-6) include/server/mir/graphics/surfaceless_egl_context.h (+11/-10) include/test/mir_test_doubles/null_gl_context.h (+2/-2) src/platform/graphics/android/gl_context.cpp (+2/-2) src/platform/graphics/android/gl_context.h (+2/-2) src/platform/graphics/mesa/display.cpp (+2/-2) src/platform/graphics/mesa/display_helpers.cpp (+2/-2) src/platform/graphics/mesa/display_helpers.h (+2/-2) src/server/graphics/CMakeLists.txt (+2/-0) src/server/graphics/gl_extensions_base.cpp (+4/-4) src/server/graphics/nested/nested_display.cpp (+4/-45) src/server/graphics/offscreen/CMakeLists.txt (+0/-2) src/server/graphics/offscreen/display.cpp (+1/-29) src/server/graphics/offscreen/display.h (+1/-1) src/server/graphics/offscreen/display_buffer.cpp (+3/-3) src/server/graphics/offscreen/display_buffer.h (+1/-1) src/server/graphics/surfaceless_egl_context.cpp (+103/-32) tests/unit-tests/graphics/CMakeLists.txt (+1/-0) tests/unit-tests/graphics/test_surfaceless_egl_context.cpp (+254/-0) tests/unit-tests/scene/test_gl_pixel_buffer.cpp (+4/-4) |
To merge this branch: | bzr merge lp:~raof/mir/check-for-surfaceless |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
PS Jenkins bot (community) | continuous-integration | Approve | |
Daniel van Vugt | Approve | ||
Alexandros Frantzis (community) | Abstain | ||
Chris Halse Rogers | Approve | ||
Andreas Pokorny (community) | Approve | ||
Review via email: mp+198510@code.launchpad.net |
Commit message
nested: Check for, and prefer, EGL_KHR_
It seems that at least one of our Android stacks doesn't support
EGL_KHR_
Fixes nested on Mesa (LP: #1260635)
Description of the change
nested: Check for, and prefer, EGL_KHR_
It seems that at least one of our Android stacks doesn't support EGL_KHR_
and Mesa doesn't support pbuffer surfaces.
Fixes nested on Mesa
Daniel van Vugt (vanvugt) wrote : | # |
Looks good, if you ignore what C++ forces us to do with initializer lists :(
Nit: Missing an underscore:
31 + (khr_surfaceles
Andreas Pokorny (andreas-pokorny) wrote : | # |
I think
16 + khr_surfaceless
wants to be a utility function for querying egl extension existance
You could also turn
20 + egl_surface( .... )
into
egl_surface( EGLSurfaceStore
and evade control flow in the initializer list.
-> yay and that would be my first launchpad review.
Chris Halse Rogers (raof) wrote : | # |
Ok, confirmed that this doesn't break android. Time to address some reviews!
Alexandros Frantzis (afrantzis) wrote : | # |
You might also want to take a look at graphics/
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:1282
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
FAILURE: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
deb: http://
FAILURE: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:1285
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
Andreas Pokorny (andreas-pokorny) wrote : | # |
looks fine to me
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:1290
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
Chris Halse Rogers (raof) wrote : | # |
Now really tested on Android (I didn't know you could run two different mir_demo_
Daniel van Vugt (vanvugt) wrote : | # |
Verified nesting now works on desktop (LP: #1260635)
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:1291
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
FAILURE: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:1292
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
FAILURE: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
deb: http://
FAILURE: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
Daniel van Vugt (vanvugt) wrote : | # |
Only minor issues...
1. Typo:
77 + /* We have to explicitly define this, as GLContext has a deleted copy construtor */
2. constness of make_current/
3. while (parentheses_
needs_fixing
}
I prefer this style, but it's too much of an obvious deviation from the Mir project style.
4. Unreadably long identifiers:
768 +TEST_F(
787 +TEST_F(
On that theme, so are lines longer than 80 columns.
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:1295
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
FAILURE: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
deb: http://
FAILURE: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
Alexandros Frantzis (afrantzis) wrote : | # |
578 +mg::Surfaceles
587 +mg::Surfaceles
588 + EGLDisplay egl_display,
589 + EGLint const* attribs,
590 + EGLContext shared_context)
It would be clearer to implement the SurfaceEGLConte
SurfacelessEGLC
: SurfacelessEGLC
429 +mgo::DisplayBu
430 geom::Rectangle const& area)
431 - : egl_context{
432 + : egl_context{
It's better to accept a move only type (such as SurfacelessEGLC
Also, with this code, since the egl_context parameter is an rvalue reference, not a universal reference, using std::forward doesn't offer any benefits over using std::move.
613 + move.egl_display = EGL_NO_DISPLAY;
618 + release_current();
A invalidated (i.e. moved) SurfacelessEGLC
Chris Halse Rogers (raof) wrote : | # |
On Mon, 2013-12-16 at 11:40 +0000, Alexandros Frantzis wrote:
> Review: Needs Fixing
>
> 578 +mg::Surfaceles
>
> 587 +mg::Surfaceles
> 588 + EGLDisplay egl_display,
> 589 + EGLint const* attribs,
> 590 + EGLContext shared_context)
>
> It would be clearer to implement the SurfaceEGLConte
>
> SurfacelessEGLC
> : SurfacelessEGLC
>
Quite true! Fixed.
> 429 +mgo::DisplayBu
> 430 geom::Rectangle const& area)
> 431 - : egl_context{
> 432 + : egl_context{
>
> It's better to accept a move only type (such as SurfacelessEGLC
Done.
>
> 613 + move.egl_display = EGL_NO_DISPLAY;
>
> 618 + release_current();
>
> A invalidated (i.e. moved) SurfacelessEGLC
Oh, right. If there's no current context then it'll attempt to release.
Fixed.
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:1298
http://
Executed test runs:
FAILURE: http://
SUCCESS: http://
FAILURE: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
deb: http://
FAILURE: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
Alexandros Frantzis (afrantzis) wrote : | # |
Looks good overall, with the exception of some brace placement style issues in the tests.
Abstaining in order not to block this MP.
Daniel van Vugt (vanvugt) wrote : | # |
Still too many "minor issues". See my previous comment. This includes some braces still not fixed.
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:1299
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
Daniel van Vugt (vanvugt) wrote : | # |
I'm not going to block on a couple of minor issues, but there are still more than a couple. Fix half-ish and I'm happy :)
3. Braces you missed - bzr diff | egrep '^\+.*[^ ]+ {$'
+EGLint const default_attr[] = {
+namespace {
+ if (found_
+ const EGLint attribs_
+ const EGLint attribs_
+ const EGLint attribs_
+ const EGLint attribs_
+ const EGLint attribs_
2. I would prefer they're not const.
4. Use your imagination. You know more about the context than I do.
Daniel van Vugt (vanvugt) wrote : | # |
OK, enough back and forth.
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:1300
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Autolanding.
More details in the following jenkins job:
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
FAILURE: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
SUCCESS: http://
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:1301
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
Preview Diff
1 | === modified file 'include/platform/mir/graphics/gl_context.h' | |||
2 | --- include/platform/mir/graphics/gl_context.h 2013-12-17 18:24:51 +0000 | |||
3 | +++ include/platform/mir/graphics/gl_context.h 2013-12-19 09:13:25 +0000 | |||
4 | @@ -29,8 +29,8 @@ | |||
5 | 29 | public: | 29 | public: |
6 | 30 | virtual ~GLContext() = default; | 30 | virtual ~GLContext() = default; |
7 | 31 | 31 | ||
10 | 32 | virtual void make_current() = 0; | 32 | virtual void make_current() const = 0; |
11 | 33 | virtual void release_current() = 0; | 33 | virtual void release_current() const = 0; |
12 | 34 | 34 | ||
13 | 35 | protected: | 35 | protected: |
14 | 36 | GLContext() = default; | 36 | GLContext() = default; |
15 | 37 | 37 | ||
16 | === renamed file 'src/server/graphics/offscreen/gl_extensions_base.h' => 'include/server/mir/graphics/gl_extensions_base.h' | |||
17 | --- src/server/graphics/offscreen/gl_extensions_base.h 2013-11-12 17:23:53 +0000 | |||
18 | +++ include/server/mir/graphics/gl_extensions_base.h 2013-12-19 09:13:25 +0000 | |||
19 | @@ -16,15 +16,13 @@ | |||
20 | 16 | * Authored by: Alexandros Frantzis <alexandros.frantzis@canonical.com> | 16 | * Authored by: Alexandros Frantzis <alexandros.frantzis@canonical.com> |
21 | 17 | */ | 17 | */ |
22 | 18 | 18 | ||
25 | 19 | #ifndef MIR_GRAPHICS_OFFSCREEN_GL_EXTENSIONS_BASE_H_ | 19 | #ifndef MIR_GRAPHICS_GL_EXTENSIONS_BASE_H_ |
26 | 20 | #define MIR_GRAPHICS_OFFSCREEN_GL_EXTENSIONS_BASE_H_ | 20 | #define MIR_GRAPHICS_GL_EXTENSIONS_BASE_H_ |
27 | 21 | 21 | ||
28 | 22 | namespace mir | 22 | namespace mir |
29 | 23 | { | 23 | { |
30 | 24 | namespace graphics | 24 | namespace graphics |
31 | 25 | { | 25 | { |
32 | 26 | namespace offscreen | ||
33 | 27 | { | ||
34 | 28 | 26 | ||
35 | 29 | class GLExtensionsBase | 27 | class GLExtensionsBase |
36 | 30 | { | 28 | { |
37 | @@ -42,6 +40,5 @@ | |||
38 | 42 | 40 | ||
39 | 43 | } | 41 | } |
40 | 44 | } | 42 | } |
41 | 45 | } | ||
42 | 46 | 43 | ||
44 | 47 | #endif /* MIR_GRAPHICS_OFFSCREEN_GL_EXTENSIONS_BASE_H_ */ | 44 | #endif /* MIR_GRAPHICS_GL_EXTENSIONS_BASE_H_ */ |
45 | 48 | 45 | ||
46 | === renamed file 'src/server/graphics/offscreen/surfaceless_egl_context.h' => 'include/server/mir/graphics/surfaceless_egl_context.h' | |||
47 | --- src/server/graphics/offscreen/surfaceless_egl_context.h 2013-11-12 17:23:53 +0000 | |||
48 | +++ include/server/mir/graphics/surfaceless_egl_context.h 2013-12-19 09:13:25 +0000 | |||
49 | @@ -16,10 +16,11 @@ | |||
50 | 16 | * Authored by: Alexandros Frantzis <alexandros.frantzis@canonical.com> | 16 | * Authored by: Alexandros Frantzis <alexandros.frantzis@canonical.com> |
51 | 17 | */ | 17 | */ |
52 | 18 | 18 | ||
55 | 19 | #ifndef MIR_GRAPHICS_OFFSCREEN_SURFACELESS_EGL_CONTEXT_H_ | 19 | #ifndef MIR_GRAPHICS_SURFACELESS_EGL_CONTEXT_H_ |
56 | 20 | #define MIR_GRAPHICS_OFFSCREEN_SURFACELESS_EGL_CONTEXT_H_ | 20 | #define MIR_GRAPHICS_SURFACELESS_EGL_CONTEXT_H_ |
57 | 21 | 21 | ||
58 | 22 | #include "mir/graphics/egl_resources.h" | 22 | #include "mir/graphics/egl_resources.h" |
59 | 23 | #include "mir/graphics/gl_context.h" | ||
60 | 23 | 24 | ||
61 | 24 | #include <EGL/egl.h> | 25 | #include <EGL/egl.h> |
62 | 25 | 26 | ||
63 | @@ -27,17 +28,18 @@ | |||
64 | 27 | { | 28 | { |
65 | 28 | namespace graphics | 29 | namespace graphics |
66 | 29 | { | 30 | { |
67 | 30 | namespace offscreen | ||
68 | 31 | { | ||
69 | 32 | 31 | ||
71 | 33 | class SurfacelessEGLContext | 32 | class SurfacelessEGLContext : public GLContext |
72 | 34 | { | 33 | { |
73 | 35 | public: | 34 | public: |
74 | 36 | SurfacelessEGLContext(EGLDisplay egl_display, EGLContext shared_context); | 35 | SurfacelessEGLContext(EGLDisplay egl_display, EGLContext shared_context); |
76 | 37 | SurfacelessEGLContext(SurfacelessEGLContext&&) = default; | 36 | SurfacelessEGLContext(EGLDisplay egl_display, EGLint const* attribs, EGLContext shared_context); |
77 | 37 | /* We have to explicitly define this, as GLContext has a deleted copy constructor */ | ||
78 | 38 | SurfacelessEGLContext(SurfacelessEGLContext&& move); | ||
79 | 39 | virtual ~SurfacelessEGLContext() noexcept; | ||
80 | 38 | 40 | ||
83 | 39 | void make_current() const; | 41 | void make_current() const override; |
84 | 40 | void release_current() const; | 42 | void release_current() const override; |
85 | 41 | 43 | ||
86 | 42 | operator EGLContext() const; | 44 | operator EGLContext() const; |
87 | 43 | 45 | ||
88 | @@ -54,6 +56,5 @@ | |||
89 | 54 | 56 | ||
90 | 55 | } | 57 | } |
91 | 56 | } | 58 | } |
92 | 57 | } | ||
93 | 58 | 59 | ||
95 | 59 | #endif /* MIR_GRAPHICS_OFFSCREEN_SURFACELESS_EGL_SURFACE_H_ */ | 60 | #endif /* MIR_GRAPHICS_SURFACELESS_EGL_SURFACE_H_ */ |
96 | 60 | 61 | ||
97 | === modified file 'include/test/mir_test_doubles/null_gl_context.h' | |||
98 | --- include/test/mir_test_doubles/null_gl_context.h 2013-06-12 10:27:50 +0000 | |||
99 | +++ include/test/mir_test_doubles/null_gl_context.h 2013-12-19 09:13:25 +0000 | |||
100 | @@ -31,8 +31,8 @@ | |||
101 | 31 | class NullGLContext : public graphics::GLContext | 31 | class NullGLContext : public graphics::GLContext |
102 | 32 | { | 32 | { |
103 | 33 | public: | 33 | public: |
106 | 34 | void make_current() {} | 34 | void make_current() const {} |
107 | 35 | void release_current() {} | 35 | void release_current() const {} |
108 | 36 | }; | 36 | }; |
109 | 37 | 37 | ||
110 | 38 | } | 38 | } |
111 | 39 | 39 | ||
112 | === modified file 'src/platform/graphics/android/gl_context.cpp' | |||
113 | --- src/platform/graphics/android/gl_context.cpp 2013-12-17 18:24:51 +0000 | |||
114 | +++ src/platform/graphics/android/gl_context.cpp 2013-12-19 09:13:25 +0000 | |||
115 | @@ -131,7 +131,7 @@ | |||
116 | 131 | { | 131 | { |
117 | 132 | } | 132 | } |
118 | 133 | 133 | ||
120 | 134 | void mga::GLContext::make_current() | 134 | void mga::GLContext::make_current() const |
121 | 135 | { | 135 | { |
122 | 136 | if (eglMakeCurrent(egl_display, egl_surface, egl_surface, egl_context) == EGL_FALSE) | 136 | if (eglMakeCurrent(egl_display, egl_surface, egl_surface, egl_context) == EGL_FALSE) |
123 | 137 | { | 137 | { |
124 | @@ -140,7 +140,7 @@ | |||
125 | 140 | } | 140 | } |
126 | 141 | } | 141 | } |
127 | 142 | 142 | ||
129 | 143 | void mga::GLContext::release_current() | 143 | void mga::GLContext::release_current() const |
130 | 144 | { | 144 | { |
131 | 145 | eglMakeCurrent(egl_display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); | 145 | eglMakeCurrent(egl_display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); |
132 | 146 | } | 146 | } |
133 | 147 | 147 | ||
134 | === modified file 'src/platform/graphics/android/gl_context.h' | |||
135 | --- src/platform/graphics/android/gl_context.h 2013-12-17 18:24:51 +0000 | |||
136 | +++ src/platform/graphics/android/gl_context.h 2013-12-19 09:13:25 +0000 | |||
137 | @@ -48,9 +48,9 @@ | |||
138 | 48 | 48 | ||
139 | 49 | ~GLContext(); | 49 | ~GLContext(); |
140 | 50 | 50 | ||
142 | 51 | void make_current(); | 51 | void make_current() const override; |
143 | 52 | void swap_buffers(); | 52 | void swap_buffers(); |
145 | 53 | void release_current(); | 53 | void release_current() const override; |
146 | 54 | 54 | ||
147 | 55 | /* TODO: (kdub) remove these two functions once HWC1.0 construction is sorted out. */ | 55 | /* TODO: (kdub) remove these two functions once HWC1.0 construction is sorted out. */ |
148 | 56 | EGLDisplay display() | 56 | EGLDisplay display() |
149 | 57 | 57 | ||
150 | === modified file 'src/platform/graphics/mesa/display.cpp' | |||
151 | --- src/platform/graphics/mesa/display.cpp 2013-12-17 18:24:51 +0000 | |||
152 | +++ src/platform/graphics/mesa/display.cpp 2013-12-19 09:13:25 +0000 | |||
153 | @@ -58,12 +58,12 @@ | |||
154 | 58 | egl.setup(gbm, shared_context); | 58 | egl.setup(gbm, shared_context); |
155 | 59 | } | 59 | } |
156 | 60 | 60 | ||
158 | 61 | void make_current() | 61 | void make_current() const override |
159 | 62 | { | 62 | { |
160 | 63 | egl.make_current(); | 63 | egl.make_current(); |
161 | 64 | } | 64 | } |
162 | 65 | 65 | ||
164 | 66 | void release_current() | 66 | void release_current() const override |
165 | 67 | { | 67 | { |
166 | 68 | egl.release_current(); | 68 | egl.release_current(); |
167 | 69 | } | 69 | } |
168 | 70 | 70 | ||
169 | === modified file 'src/platform/graphics/mesa/display_helpers.cpp' | |||
170 | --- src/platform/graphics/mesa/display_helpers.cpp 2013-12-17 18:24:51 +0000 | |||
171 | +++ src/platform/graphics/mesa/display_helpers.cpp 2013-12-19 09:13:25 +0000 | |||
172 | @@ -357,13 +357,13 @@ | |||
173 | 357 | return (ret == EGL_TRUE); | 357 | return (ret == EGL_TRUE); |
174 | 358 | } | 358 | } |
175 | 359 | 359 | ||
177 | 360 | bool mgmh::EGLHelper::make_current() | 360 | bool mgmh::EGLHelper::make_current() const |
178 | 361 | { | 361 | { |
179 | 362 | auto ret = eglMakeCurrent(egl_display, egl_surface, egl_surface, egl_context); | 362 | auto ret = eglMakeCurrent(egl_display, egl_surface, egl_surface, egl_context); |
180 | 363 | return (ret == EGL_TRUE); | 363 | return (ret == EGL_TRUE); |
181 | 364 | } | 364 | } |
182 | 365 | 365 | ||
184 | 366 | bool mgmh::EGLHelper::release_current() | 366 | bool mgmh::EGLHelper::release_current() const |
185 | 367 | { | 367 | { |
186 | 368 | auto ret = eglMakeCurrent(egl_display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); | 368 | auto ret = eglMakeCurrent(egl_display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); |
187 | 369 | return (ret == EGL_TRUE); | 369 | return (ret == EGL_TRUE); |
188 | 370 | 370 | ||
189 | === modified file 'src/platform/graphics/mesa/display_helpers.h' | |||
190 | --- src/platform/graphics/mesa/display_helpers.h 2013-12-17 18:24:51 +0000 | |||
191 | +++ src/platform/graphics/mesa/display_helpers.h 2013-12-19 09:13:25 +0000 | |||
192 | @@ -108,8 +108,8 @@ | |||
193 | 108 | EGLContext shared_context); | 108 | EGLContext shared_context); |
194 | 109 | 109 | ||
195 | 110 | bool swap_buffers(); | 110 | bool swap_buffers(); |
198 | 111 | bool make_current(); | 111 | bool make_current() const; |
199 | 112 | bool release_current(); | 112 | bool release_current() const; |
200 | 113 | 113 | ||
201 | 114 | EGLContext context() { return egl_context; } | 114 | EGLContext context() { return egl_context; } |
202 | 115 | 115 | ||
203 | 116 | 116 | ||
204 | === modified file 'src/server/graphics/CMakeLists.txt' | |||
205 | --- src/server/graphics/CMakeLists.txt 2013-12-17 18:24:51 +0000 | |||
206 | +++ src/server/graphics/CMakeLists.txt 2013-12-19 09:13:25 +0000 | |||
207 | @@ -5,6 +5,8 @@ | |||
208 | 5 | 5 | ||
209 | 6 | default_configuration.cpp | 6 | default_configuration.cpp |
210 | 7 | default_display_configuration_policy.cpp | 7 | default_display_configuration_policy.cpp |
211 | 8 | gl_extensions_base.cpp | ||
212 | 9 | surfaceless_egl_context.cpp | ||
213 | 8 | ) | 10 | ) |
214 | 9 | 11 | ||
215 | 10 | add_subdirectory(nested/) | 12 | add_subdirectory(nested/) |
216 | 11 | 13 | ||
217 | === renamed file 'src/server/graphics/offscreen/gl_extensions_base.cpp' => 'src/server/graphics/gl_extensions_base.cpp' | |||
218 | --- src/server/graphics/offscreen/gl_extensions_base.cpp 2013-11-14 09:45:44 +0000 | |||
219 | +++ src/server/graphics/gl_extensions_base.cpp 2013-12-19 09:13:25 +0000 | |||
220 | @@ -16,16 +16,16 @@ | |||
221 | 16 | * Authored by: Alexandros Frantzis <alexandros.frantzis@canonical.com> | 16 | * Authored by: Alexandros Frantzis <alexandros.frantzis@canonical.com> |
222 | 17 | */ | 17 | */ |
223 | 18 | 18 | ||
225 | 19 | #include "gl_extensions_base.h" | 19 | #include "mir/graphics/gl_extensions_base.h" |
226 | 20 | 20 | ||
227 | 21 | #include <boost/throw_exception.hpp> | 21 | #include <boost/throw_exception.hpp> |
228 | 22 | #include <stdexcept> | 22 | #include <stdexcept> |
229 | 23 | 23 | ||
230 | 24 | #include <cstring> | 24 | #include <cstring> |
231 | 25 | 25 | ||
233 | 26 | namespace mgo = mir::graphics::offscreen; | 26 | namespace mg = mir::graphics; |
234 | 27 | 27 | ||
236 | 28 | mgo::GLExtensionsBase::GLExtensionsBase(char const* extensions) | 28 | mg::GLExtensionsBase::GLExtensionsBase(char const* extensions) |
237 | 29 | : extensions{extensions} | 29 | : extensions{extensions} |
238 | 30 | { | 30 | { |
239 | 31 | if (!extensions) | 31 | if (!extensions) |
240 | @@ -35,7 +35,7 @@ | |||
241 | 35 | } | 35 | } |
242 | 36 | } | 36 | } |
243 | 37 | 37 | ||
245 | 38 | bool mgo::GLExtensionsBase::support(char const* ext) const | 38 | bool mg::GLExtensionsBase::support(char const* ext) const |
246 | 39 | { | 39 | { |
247 | 40 | char const* ext_ptr = extensions; | 40 | char const* ext_ptr = extensions; |
248 | 41 | size_t const len = strlen(ext); | 41 | size_t const len = strlen(ext); |
249 | 42 | 42 | ||
250 | === modified file 'src/server/graphics/nested/nested_display.cpp' | |||
251 | --- src/server/graphics/nested/nested_display.cpp 2013-12-17 18:24:51 +0000 | |||
252 | +++ src/server/graphics/nested/nested_display.cpp 2013-12-19 09:13:25 +0000 | |||
253 | @@ -23,6 +23,7 @@ | |||
254 | 23 | 23 | ||
255 | 24 | #include "mir/geometry/rectangle.h" | 24 | #include "mir/geometry/rectangle.h" |
256 | 25 | #include "mir/graphics/gl_context.h" | 25 | #include "mir/graphics/gl_context.h" |
257 | 26 | #include "mir/graphics/surfaceless_egl_context.h" | ||
258 | 26 | #include "host_connection.h" | 27 | #include "host_connection.h" |
259 | 27 | 28 | ||
260 | 28 | #include <boost/throw_exception.hpp> | 29 | #include <boost/throw_exception.hpp> |
261 | @@ -275,53 +276,11 @@ | |||
262 | 275 | 276 | ||
263 | 276 | namespace | 277 | namespace |
264 | 277 | { | 278 | { |
265 | 278 | EGLint const dummy_pbuffer_attribs[] = | ||
266 | 279 | { | ||
267 | 280 | EGL_WIDTH, 1, | ||
268 | 281 | EGL_HEIGHT, 1, | ||
269 | 282 | EGL_NONE | ||
270 | 283 | }; | ||
271 | 284 | } | 279 | } |
272 | 285 | 280 | ||
273 | 286 | std::unique_ptr<mg::GLContext> mgn::NestedDisplay::create_gl_context() | 281 | std::unique_ptr<mg::GLContext> mgn::NestedDisplay::create_gl_context() |
274 | 287 | { | 282 | { |
314 | 288 | class NestedGLContext : public mg::GLContext | 283 | return std::unique_ptr<mg::GLContext>{new SurfacelessEGLContext(egl_display, |
315 | 289 | { | 284 | detail::nested_egl_config_attribs, |
316 | 290 | public: | 285 | EGL_NO_CONTEXT)}; |
278 | 291 | NestedGLContext(detail::EGLDisplayHandle const& egl_display) : | ||
279 | 292 | egl_display{egl_display}, | ||
280 | 293 | egl_config{egl_display.choose_config(detail::nested_egl_config_attribs)}, | ||
281 | 294 | egl_context{egl_display, eglCreateContext(egl_display, egl_config, EGL_NO_CONTEXT, detail::nested_egl_context_attribs)}, | ||
282 | 295 | egl_surface{egl_display, eglCreatePbufferSurface(egl_display, egl_config, dummy_pbuffer_attribs)} | ||
283 | 296 | { | ||
284 | 297 | } | ||
285 | 298 | |||
286 | 299 | ~NestedGLContext() noexcept | ||
287 | 300 | { | ||
288 | 301 | if (eglGetCurrentContext() == egl_context) | ||
289 | 302 | release_current(); | ||
290 | 303 | } | ||
291 | 304 | |||
292 | 305 | void make_current() override | ||
293 | 306 | { | ||
294 | 307 | if (eglMakeCurrent(egl_display, egl_surface, egl_surface, egl_context) == EGL_FALSE) | ||
295 | 308 | { | ||
296 | 309 | BOOST_THROW_EXCEPTION( | ||
297 | 310 | std::runtime_error("could not activate dummy surface with eglMakeCurrent\n")); | ||
298 | 311 | } | ||
299 | 312 | } | ||
300 | 313 | |||
301 | 314 | void release_current() override | ||
302 | 315 | { | ||
303 | 316 | eglMakeCurrent(egl_display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); | ||
304 | 317 | } | ||
305 | 318 | |||
306 | 319 | private: | ||
307 | 320 | EGLDisplay const egl_display; | ||
308 | 321 | EGLConfig const egl_config; | ||
309 | 322 | EGLContextStore const egl_context; | ||
310 | 323 | EGLSurfaceStore const egl_surface; | ||
311 | 324 | }; | ||
312 | 325 | |||
313 | 326 | return std::unique_ptr<mg::GLContext>{new NestedGLContext(egl_display)}; | ||
317 | 327 | } | 286 | } |
318 | 328 | 287 | ||
319 | === modified file 'src/server/graphics/offscreen/CMakeLists.txt' | |||
320 | --- src/server/graphics/offscreen/CMakeLists.txt 2013-11-12 17:23:53 +0000 | |||
321 | +++ src/server/graphics/offscreen/CMakeLists.txt 2013-12-19 09:13:25 +0000 | |||
322 | @@ -4,8 +4,6 @@ | |||
323 | 4 | display.cpp | 4 | display.cpp |
324 | 5 | display_configuration.cpp | 5 | display_configuration.cpp |
325 | 6 | display_buffer.cpp | 6 | display_buffer.cpp |
326 | 7 | surfaceless_egl_context.cpp | ||
327 | 8 | gl_extensions_base.cpp | ||
328 | 9 | ) | 7 | ) |
329 | 10 | 8 | ||
330 | 11 | target_link_libraries( | 9 | target_link_libraries( |
331 | 12 | 10 | ||
332 | === modified file 'src/server/graphics/offscreen/display.cpp' | |||
333 | --- src/server/graphics/offscreen/display.cpp 2013-11-18 12:35:14 +0000 | |||
334 | +++ src/server/graphics/offscreen/display.cpp 2013-12-19 09:13:25 +0000 | |||
335 | @@ -20,7 +20,6 @@ | |||
336 | 20 | #include "display_buffer.h" | 20 | #include "display_buffer.h" |
337 | 21 | #include "mir/graphics/basic_platform.h" | 21 | #include "mir/graphics/basic_platform.h" |
338 | 22 | #include "mir/graphics/display_configuration_policy.h" | 22 | #include "mir/graphics/display_configuration_policy.h" |
339 | 23 | #include "mir/graphics/gl_context.h" | ||
340 | 24 | #include "mir/geometry/size.h" | 23 | #include "mir/geometry/size.h" |
341 | 25 | 24 | ||
342 | 26 | #include <boost/throw_exception.hpp> | 25 | #include <boost/throw_exception.hpp> |
343 | @@ -33,33 +32,6 @@ | |||
344 | 33 | namespace | 32 | namespace |
345 | 34 | { | 33 | { |
346 | 35 | 34 | ||
347 | 36 | class OffscreenGLContext : public mg::GLContext | ||
348 | 37 | { | ||
349 | 38 | public: | ||
350 | 39 | OffscreenGLContext(mgo::SurfacelessEGLContext surfaceless_egl_context) | ||
351 | 40 | : surfaceless_egl_context{std::move(surfaceless_egl_context)} | ||
352 | 41 | { | ||
353 | 42 | } | ||
354 | 43 | |||
355 | 44 | ~OffscreenGLContext() noexcept | ||
356 | 45 | { | ||
357 | 46 | release_current(); | ||
358 | 47 | } | ||
359 | 48 | |||
360 | 49 | void make_current() | ||
361 | 50 | { | ||
362 | 51 | surfaceless_egl_context.make_current(); | ||
363 | 52 | } | ||
364 | 53 | |||
365 | 54 | void release_current() | ||
366 | 55 | { | ||
367 | 56 | surfaceless_egl_context.release_current(); | ||
368 | 57 | } | ||
369 | 58 | |||
370 | 59 | private: | ||
371 | 60 | mgo::SurfacelessEGLContext const surfaceless_egl_context; | ||
372 | 61 | }; | ||
373 | 62 | |||
374 | 63 | mgo::detail::EGLDisplayHandle | 35 | mgo::detail::EGLDisplayHandle |
375 | 64 | create_and_initialize_display(mg::BasicPlatform& basic_platform) | 36 | create_and_initialize_display(mg::BasicPlatform& basic_platform) |
376 | 65 | { | 37 | { |
377 | @@ -193,5 +165,5 @@ | |||
378 | 193 | std::unique_ptr<mg::GLContext> mgo::Display::create_gl_context() | 165 | std::unique_ptr<mg::GLContext> mgo::Display::create_gl_context() |
379 | 194 | { | 166 | { |
380 | 195 | return std::unique_ptr<GLContext>{ | 167 | return std::unique_ptr<GLContext>{ |
382 | 196 | new OffscreenGLContext{SurfacelessEGLContext{egl_display, egl_context_shared}}}; | 168 | new SurfacelessEGLContext{egl_display, egl_context_shared}}; |
383 | 197 | } | 169 | } |
384 | 198 | 170 | ||
385 | === modified file 'src/server/graphics/offscreen/display.h' | |||
386 | --- src/server/graphics/offscreen/display.h 2013-11-18 17:08:15 +0000 | |||
387 | +++ src/server/graphics/offscreen/display.h 2013-12-19 09:13:25 +0000 | |||
388 | @@ -21,7 +21,7 @@ | |||
389 | 21 | 21 | ||
390 | 22 | #include "mir/graphics/display.h" | 22 | #include "mir/graphics/display.h" |
391 | 23 | #include "display_configuration.h" | 23 | #include "display_configuration.h" |
393 | 24 | #include "surfaceless_egl_context.h" | 24 | #include "mir/graphics/surfaceless_egl_context.h" |
394 | 25 | 25 | ||
395 | 26 | #include <mutex> | 26 | #include <mutex> |
396 | 27 | #include <vector> | 27 | #include <vector> |
397 | 28 | 28 | ||
398 | === modified file 'src/server/graphics/offscreen/display_buffer.cpp' | |||
399 | --- src/server/graphics/offscreen/display_buffer.cpp 2013-12-17 18:24:51 +0000 | |||
400 | +++ src/server/graphics/offscreen/display_buffer.cpp 2013-12-19 09:13:25 +0000 | |||
401 | @@ -17,7 +17,7 @@ | |||
402 | 17 | */ | 17 | */ |
403 | 18 | 18 | ||
404 | 19 | #include "display_buffer.h" | 19 | #include "display_buffer.h" |
406 | 20 | #include "gl_extensions_base.h" | 20 | #include "mir/graphics/gl_extensions_base.h" |
407 | 21 | #include "mir/raii.h" | 21 | #include "mir/raii.h" |
408 | 22 | 22 | ||
409 | 23 | #include <boost/throw_exception.hpp> | 23 | #include <boost/throw_exception.hpp> |
410 | @@ -33,11 +33,11 @@ | |||
411 | 33 | namespace | 33 | namespace |
412 | 34 | { | 34 | { |
413 | 35 | 35 | ||
415 | 36 | class GLExtensions : public mgo::GLExtensionsBase | 36 | class GLExtensions : public mg::GLExtensionsBase |
416 | 37 | { | 37 | { |
417 | 38 | public: | 38 | public: |
418 | 39 | GLExtensions() : | 39 | GLExtensions() : |
420 | 40 | mgo::GLExtensionsBase{ | 40 | mg::GLExtensionsBase{ |
421 | 41 | reinterpret_cast<char const*>(glGetString(GL_EXTENSIONS))} | 41 | reinterpret_cast<char const*>(glGetString(GL_EXTENSIONS))} |
422 | 42 | { | 42 | { |
423 | 43 | } | 43 | } |
424 | 44 | 44 | ||
425 | === modified file 'src/server/graphics/offscreen/display_buffer.h' | |||
426 | --- src/server/graphics/offscreen/display_buffer.h 2013-11-14 09:46:02 +0000 | |||
427 | +++ src/server/graphics/offscreen/display_buffer.h 2013-12-19 09:13:25 +0000 | |||
428 | @@ -19,7 +19,7 @@ | |||
429 | 19 | #ifndef MIR_GRAPHICS_OFFSCREEN_DISPLAY_BUFFER_H_ | 19 | #ifndef MIR_GRAPHICS_OFFSCREEN_DISPLAY_BUFFER_H_ |
430 | 20 | #define MIR_GRAPHICS_OFFSCREEN_DISPLAY_BUFFER_H_ | 20 | #define MIR_GRAPHICS_OFFSCREEN_DISPLAY_BUFFER_H_ |
431 | 21 | 21 | ||
433 | 22 | #include "surfaceless_egl_context.h" | 22 | #include "mir/graphics/surfaceless_egl_context.h" |
434 | 23 | 23 | ||
435 | 24 | #include "mir/graphics/display_buffer.h" | 24 | #include "mir/graphics/display_buffer.h" |
436 | 25 | #include "mir/geometry/size.h" | 25 | #include "mir/geometry/size.h" |
437 | 26 | 26 | ||
438 | === renamed file 'src/server/graphics/offscreen/surfaceless_egl_context.cpp' => 'src/server/graphics/surfaceless_egl_context.cpp' | |||
439 | --- src/server/graphics/offscreen/surfaceless_egl_context.cpp 2013-11-18 12:58:38 +0000 | |||
440 | +++ src/server/graphics/surfaceless_egl_context.cpp 2013-12-19 09:13:25 +0000 | |||
441 | @@ -16,22 +16,23 @@ | |||
442 | 16 | * Authored by: Alexandros Frantzis <alexandros.frantzis@canonical.com> | 16 | * Authored by: Alexandros Frantzis <alexandros.frantzis@canonical.com> |
443 | 17 | */ | 17 | */ |
444 | 18 | 18 | ||
447 | 19 | #include "surfaceless_egl_context.h" | 19 | #include "mir/graphics/surfaceless_egl_context.h" |
448 | 20 | #include "gl_extensions_base.h" | 20 | #include "mir/graphics/gl_extensions_base.h" |
449 | 21 | 21 | ||
450 | 22 | #include <boost/throw_exception.hpp> | 22 | #include <boost/throw_exception.hpp> |
451 | 23 | #include <stdexcept> | 23 | #include <stdexcept> |
452 | 24 | #include <vector> | ||
453 | 24 | 25 | ||
455 | 25 | namespace mgo = mir::graphics::offscreen; | 26 | namespace mg = mir::graphics; |
456 | 26 | 27 | ||
457 | 27 | namespace | 28 | namespace |
458 | 28 | { | 29 | { |
459 | 29 | 30 | ||
461 | 30 | class EGLExtensions : public mgo::GLExtensionsBase | 31 | class EGLExtensions : public mg::GLExtensionsBase |
462 | 31 | { | 32 | { |
463 | 32 | public: | 33 | public: |
464 | 33 | EGLExtensions(EGLDisplay egl_display) : | 34 | EGLExtensions(EGLDisplay egl_display) : |
466 | 34 | mgo::GLExtensionsBase{ | 35 | mg::GLExtensionsBase{ |
467 | 35 | reinterpret_cast<char const*>(eglQueryString(egl_display, EGL_EXTENSIONS))} | 36 | reinterpret_cast<char const*>(eglQueryString(egl_display, EGL_EXTENSIONS))} |
468 | 36 | { | 37 | { |
469 | 37 | } | 38 | } |
470 | @@ -44,27 +45,62 @@ | |||
471 | 44 | return extensions.support("EGL_KHR_surfaceless_context"); | 45 | return extensions.support("EGL_KHR_surfaceless_context"); |
472 | 45 | } | 46 | } |
473 | 46 | 47 | ||
488 | 47 | EGLConfig choose_config(EGLDisplay egl_display, bool surfaceless) | 48 | std::vector<EGLint> ensure_pbuffer_set(EGLint const* attribs) |
489 | 48 | { | 49 | { |
490 | 49 | EGLint const surface_type = surfaceless ? EGL_DONT_CARE : EGL_PBUFFER_BIT; | 50 | bool has_preferred_surface = false; |
491 | 50 | 51 | std::vector<EGLint> attribs_with_surface_type; | |
492 | 51 | EGLint const config_attr[] = { | 52 | int i = 0; |
493 | 52 | EGL_SURFACE_TYPE, surface_type, | 53 | |
494 | 53 | EGL_RED_SIZE, 8, | 54 | while (attribs[i] != EGL_NONE) |
495 | 54 | EGL_GREEN_SIZE, 8, | 55 | { |
496 | 55 | EGL_BLUE_SIZE, 8, | 56 | attribs_with_surface_type.push_back(attribs[i]); |
497 | 56 | EGL_ALPHA_SIZE, 0, | 57 | if (attribs[i] == EGL_SURFACE_TYPE) |
498 | 57 | EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, | 58 | { |
499 | 58 | EGL_NONE | 59 | has_preferred_surface = true; |
500 | 59 | }; | 60 | if (attribs[i+1] == EGL_DONT_CARE) |
501 | 60 | 61 | { | |
502 | 62 | /* Need to treat EGL_DONT_CARE specially, as it is defined as all-bits-set */ | ||
503 | 63 | attribs_with_surface_type.push_back(EGL_PBUFFER_BIT); | ||
504 | 64 | } | ||
505 | 65 | else | ||
506 | 66 | { | ||
507 | 67 | attribs_with_surface_type.push_back(attribs[i+1] | EGL_PBUFFER_BIT); | ||
508 | 68 | } | ||
509 | 69 | } | ||
510 | 70 | else | ||
511 | 71 | { | ||
512 | 72 | attribs_with_surface_type.push_back(attribs[i+1]); | ||
513 | 73 | } | ||
514 | 74 | i += 2; | ||
515 | 75 | } | ||
516 | 76 | |||
517 | 77 | if (!has_preferred_surface) | ||
518 | 78 | { | ||
519 | 79 | attribs_with_surface_type.push_back(EGL_SURFACE_TYPE); | ||
520 | 80 | attribs_with_surface_type.push_back(EGL_PBUFFER_BIT); | ||
521 | 81 | } | ||
522 | 82 | |||
523 | 83 | attribs_with_surface_type.push_back(EGL_NONE); | ||
524 | 84 | |||
525 | 85 | return attribs_with_surface_type; | ||
526 | 86 | } | ||
527 | 87 | |||
528 | 88 | EGLConfig choose_config(EGLDisplay egl_display, EGLint const* attribs, bool surfaceless) | ||
529 | 89 | { | ||
530 | 61 | EGLConfig egl_config{0}; | 90 | EGLConfig egl_config{0}; |
531 | 62 | int num_egl_configs{0}; | 91 | int num_egl_configs{0}; |
534 | 63 | 92 | std::vector<EGLint> validated_attribs; | |
535 | 64 | if (eglChooseConfig(egl_display, config_attr, &egl_config, 1, &num_egl_configs) == EGL_FALSE || | 93 | |
536 | 94 | if (!surfaceless) | ||
537 | 95 | { | ||
538 | 96 | validated_attribs = ensure_pbuffer_set(attribs); | ||
539 | 97 | attribs = validated_attribs.data(); | ||
540 | 98 | } | ||
541 | 99 | |||
542 | 100 | if (eglChooseConfig(egl_display, attribs, &egl_config, 1, &num_egl_configs) == EGL_FALSE || | ||
543 | 65 | num_egl_configs != 1) | 101 | num_egl_configs != 1) |
544 | 66 | { | 102 | { |
546 | 67 | BOOST_THROW_EXCEPTION(std::runtime_error("Failed to choose ARGB EGL config")); | 103 | BOOST_THROW_EXCEPTION(std::runtime_error("Failed to choose EGL config")); |
547 | 68 | } | 104 | } |
548 | 69 | 105 | ||
549 | 70 | return egl_config; | 106 | return egl_config; |
550 | @@ -88,14 +124,32 @@ | |||
551 | 88 | EGL_NONE | 124 | EGL_NONE |
552 | 89 | }; | 125 | }; |
553 | 90 | 126 | ||
559 | 91 | } | 127 | EGLint const default_attr[] = |
560 | 92 | 128 | { | |
561 | 93 | mgo::SurfacelessEGLContext::SurfacelessEGLContext( | 129 | EGL_SURFACE_TYPE, EGL_DONT_CARE, |
562 | 94 | EGLDisplay egl_display, | 130 | EGL_RED_SIZE, 8, |
563 | 95 | EGLContext shared_context) | 131 | EGL_GREEN_SIZE, 8, |
564 | 132 | EGL_BLUE_SIZE, 8, | ||
565 | 133 | EGL_ALPHA_SIZE, 0, | ||
566 | 134 | EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, | ||
567 | 135 | EGL_NONE | ||
568 | 136 | }; | ||
569 | 137 | |||
570 | 138 | |||
571 | 139 | } | ||
572 | 140 | |||
573 | 141 | mg::SurfacelessEGLContext::SurfacelessEGLContext(EGLDisplay egl_display, EGLContext shared_context) | ||
574 | 142 | : SurfacelessEGLContext(egl_display, default_attr, shared_context) | ||
575 | 143 | { | ||
576 | 144 | } | ||
577 | 145 | |||
578 | 146 | mg::SurfacelessEGLContext::SurfacelessEGLContext( | ||
579 | 147 | EGLDisplay egl_display, | ||
580 | 148 | EGLint const* attribs, | ||
581 | 149 | EGLContext shared_context) | ||
582 | 96 | : egl_display{egl_display}, | 150 | : egl_display{egl_display}, |
583 | 97 | surfaceless{supports_surfaceless_context(egl_display)}, | 151 | surfaceless{supports_surfaceless_context(egl_display)}, |
585 | 98 | egl_config{choose_config(egl_display, surfaceless)}, | 152 | egl_config{choose_config(egl_display, attribs, surfaceless)}, |
586 | 99 | egl_surface{egl_display, | 153 | egl_surface{egl_display, |
587 | 100 | surfaceless ? EGL_NO_SURFACE : create_surface(egl_display, egl_config), | 154 | surfaceless ? EGL_NO_SURFACE : create_surface(egl_display, egl_config), |
588 | 101 | surfaceless ? EGLSurfaceStore::AllowNoSurface : | 155 | surfaceless ? EGLSurfaceStore::AllowNoSurface : |
589 | @@ -107,7 +161,24 @@ | |||
590 | 107 | { | 161 | { |
591 | 108 | } | 162 | } |
592 | 109 | 163 | ||
594 | 110 | void mgo::SurfacelessEGLContext::make_current() const | 164 | |
595 | 165 | mg::SurfacelessEGLContext::SurfacelessEGLContext(SurfacelessEGLContext&& move) | ||
596 | 166 | : egl_display(move.egl_display), | ||
597 | 167 | surfaceless(move.surfaceless), | ||
598 | 168 | egl_config(move.egl_config), | ||
599 | 169 | egl_surface{std::move(move.egl_surface)}, | ||
600 | 170 | egl_context{std::move(move.egl_context)} | ||
601 | 171 | { | ||
602 | 172 | move.egl_display = EGL_NO_DISPLAY; | ||
603 | 173 | } | ||
604 | 174 | |||
605 | 175 | mg::SurfacelessEGLContext::~SurfacelessEGLContext() noexcept | ||
606 | 176 | { | ||
607 | 177 | release_current(); | ||
608 | 178 | } | ||
609 | 179 | |||
610 | 180 | |||
611 | 181 | void mg::SurfacelessEGLContext::make_current() const | ||
612 | 111 | { | 182 | { |
613 | 112 | if (eglGetCurrentContext() == egl_context) | 183 | if (eglGetCurrentContext() == egl_context) |
614 | 113 | return; | 184 | return; |
615 | @@ -120,13 +191,13 @@ | |||
616 | 120 | } | 191 | } |
617 | 121 | } | 192 | } |
618 | 122 | 193 | ||
620 | 123 | void mgo::SurfacelessEGLContext::release_current() const | 194 | void mg::SurfacelessEGLContext::release_current() const |
621 | 124 | { | 195 | { |
623 | 125 | if (eglGetCurrentContext() == egl_context) | 196 | if (egl_context != EGL_NO_CONTEXT && eglGetCurrentContext() == egl_context) |
624 | 126 | eglMakeCurrent(egl_display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); | 197 | eglMakeCurrent(egl_display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); |
625 | 127 | } | 198 | } |
626 | 128 | 199 | ||
628 | 129 | mgo::SurfacelessEGLContext::operator EGLContext() const | 200 | mg::SurfacelessEGLContext::operator EGLContext() const |
629 | 130 | { | 201 | { |
630 | 131 | return egl_context; | 202 | return egl_context; |
631 | 132 | } | 203 | } |
632 | 133 | 204 | ||
633 | === modified file 'tests/unit-tests/graphics/CMakeLists.txt' | |||
634 | --- tests/unit-tests/graphics/CMakeLists.txt 2013-12-17 18:24:51 +0000 | |||
635 | +++ tests/unit-tests/graphics/CMakeLists.txt 2013-12-19 09:13:25 +0000 | |||
636 | @@ -6,6 +6,7 @@ | |||
637 | 6 | ${CMAKE_CURRENT_SOURCE_DIR}/test_default_display_configuration_policy.cpp | 6 | ${CMAKE_CURRENT_SOURCE_DIR}/test_default_display_configuration_policy.cpp |
638 | 7 | ${CMAKE_CURRENT_SOURCE_DIR}/test_buffer_id.cpp | 7 | ${CMAKE_CURRENT_SOURCE_DIR}/test_buffer_id.cpp |
639 | 8 | ${CMAKE_CURRENT_SOURCE_DIR}/test_buffer_properties.cpp | 8 | ${CMAKE_CURRENT_SOURCE_DIR}/test_buffer_properties.cpp |
640 | 9 | ${CMAKE_CURRENT_SOURCE_DIR}/test_surfaceless_egl_context.cpp | ||
641 | 9 | ) | 10 | ) |
642 | 10 | 11 | ||
643 | 11 | add_subdirectory(nested/) | 12 | add_subdirectory(nested/) |
644 | 12 | 13 | ||
645 | === added file 'tests/unit-tests/graphics/test_surfaceless_egl_context.cpp' | |||
646 | --- tests/unit-tests/graphics/test_surfaceless_egl_context.cpp 1970-01-01 00:00:00 +0000 | |||
647 | +++ tests/unit-tests/graphics/test_surfaceless_egl_context.cpp 2013-12-19 09:13:25 +0000 | |||
648 | @@ -0,0 +1,254 @@ | |||
649 | 1 | /* | ||
650 | 2 | * Copyright © 2013 Canonical Ltd. | ||
651 | 3 | * | ||
652 | 4 | * This program is free software: you can redistribute it and/or modify it | ||
653 | 5 | * under the terms of the GNU General Public License version 3, | ||
654 | 6 | * as published by the Free Software Foundation. | ||
655 | 7 | * | ||
656 | 8 | * This program is distributed in the hope that it will be useful, | ||
657 | 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
658 | 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
659 | 11 | * GNU General Public License for more details. | ||
660 | 12 | * | ||
661 | 13 | * You should have received a copy of the GNU General Public License | ||
662 | 14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
663 | 15 | * | ||
664 | 16 | * Authored by: | ||
665 | 17 | * Christopher James Halse Rogers <christopher.halse.rogers@canonical.com> | ||
666 | 18 | */ | ||
667 | 19 | |||
668 | 20 | #include "mir/graphics/surfaceless_egl_context.h" | ||
669 | 21 | #include "mir_test_doubles/mock_egl.h" | ||
670 | 22 | #include <stdexcept> | ||
671 | 23 | #include <list> | ||
672 | 24 | |||
673 | 25 | #include <gtest/gtest.h> | ||
674 | 26 | #include <gmock/gmock.h> | ||
675 | 27 | |||
676 | 28 | namespace mg = mir::graphics; | ||
677 | 29 | namespace mtd = mir::test::doubles; | ||
678 | 30 | |||
679 | 31 | class SurfacelessEGLContextTest : public ::testing::Test | ||
680 | 32 | { | ||
681 | 33 | public: | ||
682 | 34 | EGLDisplay const fake_display{reinterpret_cast<EGLDisplay>(0xfffaaafa)}; | ||
683 | 35 | EGLSurface const fake_surface{reinterpret_cast<EGLSurface>(0xdeadbeef)}; | ||
684 | 36 | EGLContext const fake_context{reinterpret_cast<EGLContext>(0xfaafbaaf)}; | ||
685 | 37 | |||
686 | 38 | protected: | ||
687 | 39 | virtual void SetUp() | ||
688 | 40 | { | ||
689 | 41 | using namespace testing; | ||
690 | 42 | |||
691 | 43 | ON_CALL(mock_egl, eglCreatePbufferSurface(_,_,_)) | ||
692 | 44 | .WillByDefault(Return(fake_surface)); | ||
693 | 45 | ON_CALL(mock_egl, eglCreateContext(_,_,_,_)) | ||
694 | 46 | .WillByDefault(Return(fake_context)); | ||
695 | 47 | ON_CALL(mock_egl, eglGetCurrentContext()) | ||
696 | 48 | .WillByDefault(Return(EGL_NO_CONTEXT)); | ||
697 | 49 | } | ||
698 | 50 | |||
699 | 51 | testing::NiceMock<mtd::MockEGL> mock_egl; | ||
700 | 52 | }; | ||
701 | 53 | |||
702 | 54 | namespace | ||
703 | 55 | { | ||
704 | 56 | |||
705 | 57 | MATCHER(ConfigAttribContainsPBufferFlag, "") | ||
706 | 58 | { | ||
707 | 59 | EGLint surface_type = 0; | ||
708 | 60 | bool found_surface_type = false; | ||
709 | 61 | std::list<std::string> pretty_surface; | ||
710 | 62 | |||
711 | 63 | for (int i = 0; arg[i] != EGL_NONE; ++i) | ||
712 | 64 | { | ||
713 | 65 | if (arg[i] == EGL_SURFACE_TYPE) | ||
714 | 66 | { | ||
715 | 67 | surface_type = arg[i+1]; | ||
716 | 68 | found_surface_type = true; | ||
717 | 69 | } | ||
718 | 70 | } | ||
719 | 71 | |||
720 | 72 | if (found_surface_type) | ||
721 | 73 | { | ||
722 | 74 | if (surface_type == EGL_DONT_CARE) | ||
723 | 75 | { | ||
724 | 76 | pretty_surface.push_back("EGL_DONT_CARE"); | ||
725 | 77 | } | ||
726 | 78 | else | ||
727 | 79 | { | ||
728 | 80 | if (surface_type & EGL_MULTISAMPLE_RESOLVE_BOX_BIT) | ||
729 | 81 | { | ||
730 | 82 | pretty_surface.push_back("EGL_MULTISAMPLE_RESOLVE_BOX_BIT"); | ||
731 | 83 | } | ||
732 | 84 | if (surface_type & EGL_PBUFFER_BIT) | ||
733 | 85 | { | ||
734 | 86 | pretty_surface.push_back("EGL_PBUFFER_BIT"); | ||
735 | 87 | } | ||
736 | 88 | if (surface_type & EGL_PIXMAP_BIT) | ||
737 | 89 | { | ||
738 | 90 | pretty_surface.push_back("EGL_PIXMAP_BIT"); | ||
739 | 91 | } | ||
740 | 92 | if (surface_type & EGL_SWAP_BEHAVIOR_PRESERVED_BIT) | ||
741 | 93 | { | ||
742 | 94 | pretty_surface.push_back("EGL_SWAP_BEHAVIOR_PRESERVED_BIT"); | ||
743 | 95 | } | ||
744 | 96 | if (surface_type & EGL_VG_ALPHA_FORMAT_PRE_BIT) | ||
745 | 97 | { | ||
746 | 98 | pretty_surface.push_back("EGL_VG_ALPHA_FORMAT_PRE_BIT"); | ||
747 | 99 | } | ||
748 | 100 | if (surface_type & EGL_VG_COLORSPACE_LINEAR_BIT) | ||
749 | 101 | { | ||
750 | 102 | pretty_surface.push_back("EGL_VG_COLORSPACE_LINEAR_BIT"); | ||
751 | 103 | } | ||
752 | 104 | if (surface_type & EGL_WINDOW_BIT) | ||
753 | 105 | { | ||
754 | 106 | pretty_surface.push_back("EGL_WINDOW_BIT"); | ||
755 | 107 | } | ||
756 | 108 | } | ||
757 | 109 | std::string pretty_result = pretty_surface.back(); | ||
758 | 110 | pretty_surface.pop_back(); | ||
759 | 111 | for (auto& pretty : pretty_surface) | ||
760 | 112 | { | ||
761 | 113 | pretty_result += " | " + pretty; | ||
762 | 114 | } | ||
763 | 115 | *result_listener << "surface type is "<< pretty_result; | ||
764 | 116 | } | ||
765 | 117 | else | ||
766 | 118 | { | ||
767 | 119 | *result_listener << "no surface type set"; | ||
768 | 120 | } | ||
769 | 121 | |||
770 | 122 | return found_surface_type && | ||
771 | 123 | (surface_type != EGL_DONT_CARE) && | ||
772 | 124 | (surface_type & EGL_PBUFFER_BIT); | ||
773 | 125 | } | ||
774 | 126 | |||
775 | 127 | } | ||
776 | 128 | |||
777 | 129 | TEST_F(SurfacelessEGLContextTest, UsesPBufferContainingAttribsListByDefault) | ||
778 | 130 | { | ||
779 | 131 | using namespace testing; | ||
780 | 132 | |||
781 | 133 | ON_CALL(mock_egl, eglQueryString(_,_)) | ||
782 | 134 | .WillByDefault(Return("")); | ||
783 | 135 | |||
784 | 136 | EXPECT_CALL(mock_egl, eglChooseConfig(_, ConfigAttribContainsPBufferFlag(), _,_,_)) | ||
785 | 137 | .WillOnce(DoAll(SetArgPointee<4>(1), Return(EGL_TRUE))); | ||
786 | 138 | |||
787 | 139 | mg::SurfacelessEGLContext ctx_noattrib(fake_display, EGL_NO_CONTEXT); | ||
788 | 140 | } | ||
789 | 141 | |||
790 | 142 | TEST_F(SurfacelessEGLContextTest, KeepsPBufferInAttribsList) | ||
791 | 143 | { | ||
792 | 144 | using namespace testing; | ||
793 | 145 | |||
794 | 146 | const EGLint attribs_with_pbuffer[] = | ||
795 | 147 | { | ||
796 | 148 | EGL_SURFACE_TYPE, EGL_PBUFFER_BIT | EGL_WINDOW_BIT, | ||
797 | 149 | EGL_NONE | ||
798 | 150 | }; | ||
799 | 151 | |||
800 | 152 | ON_CALL(mock_egl, eglQueryString(_,_)) | ||
801 | 153 | .WillByDefault(Return("")); | ||
802 | 154 | |||
803 | 155 | EXPECT_CALL(mock_egl, eglChooseConfig(_, ConfigAttribContainsPBufferFlag(), _,_,_)) | ||
804 | 156 | .WillOnce(DoAll(SetArgPointee<4>(1), Return(EGL_TRUE))); | ||
805 | 157 | |||
806 | 158 | mg::SurfacelessEGLContext ctx_attribs_with_pbuffer(fake_display, attribs_with_pbuffer, EGL_NO_CONTEXT); | ||
807 | 159 | } | ||
808 | 160 | |||
809 | 161 | TEST_F(SurfacelessEGLContextTest, AddsPBufferToAttribList) | ||
810 | 162 | { | ||
811 | 163 | using namespace testing; | ||
812 | 164 | |||
813 | 165 | const EGLint attribs_without_surface_type[] = | ||
814 | 166 | { | ||
815 | 167 | EGL_ALPHA_SIZE, 8, | ||
816 | 168 | EGL_CLIENT_APIS, EGL_OPENGL_ES2_BIT, | ||
817 | 169 | EGL_NONE | ||
818 | 170 | }; | ||
819 | 171 | |||
820 | 172 | ON_CALL(mock_egl, eglQueryString(_,_)) | ||
821 | 173 | .WillByDefault(Return("")); | ||
822 | 174 | |||
823 | 175 | EXPECT_CALL(mock_egl, eglChooseConfig(_, ConfigAttribContainsPBufferFlag(), _,_,_)) | ||
824 | 176 | .WillOnce(DoAll(SetArgPointee<4>(1), Return(EGL_TRUE))); | ||
825 | 177 | |||
826 | 178 | mg::SurfacelessEGLContext ctx_attribs_without_surface_type(fake_display, attribs_without_surface_type, EGL_NO_CONTEXT); | ||
827 | 179 | } | ||
828 | 180 | |||
829 | 181 | TEST_F(SurfacelessEGLContextTest, AddsPBufferWhenNonPBufferSurfaceTypeRequested) | ||
830 | 182 | { | ||
831 | 183 | using namespace testing; | ||
832 | 184 | |||
833 | 185 | const EGLint attribs_without_pbuffer[] = | ||
834 | 186 | { | ||
835 | 187 | EGL_SURFACE_TYPE, EGL_DONT_CARE, | ||
836 | 188 | EGL_ALPHA_SIZE, 8, | ||
837 | 189 | EGL_CLIENT_APIS, EGL_OPENGL_ES2_BIT, | ||
838 | 190 | EGL_NONE | ||
839 | 191 | }; | ||
840 | 192 | |||
841 | 193 | ON_CALL(mock_egl, eglQueryString(_,_)) | ||
842 | 194 | .WillByDefault(Return("")); | ||
843 | 195 | |||
844 | 196 | EXPECT_CALL(mock_egl, eglChooseConfig(_, ConfigAttribContainsPBufferFlag(), _,_,_)) | ||
845 | 197 | .WillOnce(DoAll(SetArgPointee<4>(1), Return(EGL_TRUE))); | ||
846 | 198 | |||
847 | 199 | mg::SurfacelessEGLContext ctx_attribs_without_pbuffer(fake_display, attribs_without_pbuffer, EGL_NO_CONTEXT); | ||
848 | 200 | } | ||
849 | 201 | |||
850 | 202 | TEST_F(SurfacelessEGLContextTest, DoesNotRequestPBufferWithNoAttrib) | ||
851 | 203 | { | ||
852 | 204 | using namespace testing; | ||
853 | 205 | |||
854 | 206 | ON_CALL(mock_egl, eglQueryString(_,_)) | ||
855 | 207 | .WillByDefault(Return("EGL_KHR_surfaceless_context")); | ||
856 | 208 | |||
857 | 209 | EXPECT_CALL(mock_egl, eglChooseConfig(_, Not(ConfigAttribContainsPBufferFlag()), _,_,_)) | ||
858 | 210 | .WillOnce(DoAll(SetArgPointee<4>(1), Return(EGL_TRUE))); | ||
859 | 211 | |||
860 | 212 | mg::SurfacelessEGLContext ctx_noattrib(fake_display, EGL_NO_CONTEXT); | ||
861 | 213 | } | ||
862 | 214 | |||
863 | 215 | TEST_F(SurfacelessEGLContextTest, DoesNotAddPBufferToAttribList) | ||
864 | 216 | { | ||
865 | 217 | using namespace testing; | ||
866 | 218 | |||
867 | 219 | const EGLint attribs_without_surface_type[] = | ||
868 | 220 | { | ||
869 | 221 | EGL_ALPHA_SIZE, 8, | ||
870 | 222 | EGL_CLIENT_APIS, EGL_OPENGL_ES2_BIT, | ||
871 | 223 | EGL_NONE | ||
872 | 224 | }; | ||
873 | 225 | |||
874 | 226 | ON_CALL(mock_egl, eglQueryString(_,_)) | ||
875 | 227 | .WillByDefault(Return("EGL_KHR_surfaceless_context")); | ||
876 | 228 | |||
877 | 229 | EXPECT_CALL(mock_egl, eglChooseConfig(_, Not(ConfigAttribContainsPBufferFlag()), _,_,_)) | ||
878 | 230 | .WillOnce(DoAll(SetArgPointee<4>(1), Return(EGL_TRUE))); | ||
879 | 231 | |||
880 | 232 | mg::SurfacelessEGLContext ctx_attribs_without_surface_type(fake_display, attribs_without_surface_type, EGL_NO_CONTEXT); | ||
881 | 233 | } | ||
882 | 234 | |||
883 | 235 | TEST_F(SurfacelessEGLContextTest, DoesNotAddPBufferToSurfaceTypeRequest) | ||
884 | 236 | { | ||
885 | 237 | using namespace testing; | ||
886 | 238 | |||
887 | 239 | const EGLint attribs_with_surface_type[] = | ||
888 | 240 | { | ||
889 | 241 | EGL_SURFACE_TYPE, EGL_WINDOW_BIT, | ||
890 | 242 | EGL_ALPHA_SIZE, 8, | ||
891 | 243 | EGL_CLIENT_APIS, EGL_OPENGL_ES2_BIT, | ||
892 | 244 | EGL_NONE | ||
893 | 245 | }; | ||
894 | 246 | |||
895 | 247 | ON_CALL(mock_egl, eglQueryString(_,_)) | ||
896 | 248 | .WillByDefault(Return("EGL_KHR_surfaceless_context")); | ||
897 | 249 | |||
898 | 250 | EXPECT_CALL(mock_egl, eglChooseConfig(_, Not(ConfigAttribContainsPBufferFlag()), _,_,_)) | ||
899 | 251 | .WillOnce(DoAll(SetArgPointee<4>(1), Return(EGL_TRUE))); | ||
900 | 252 | |||
901 | 253 | mg::SurfacelessEGLContext ctx_attribs_with_surface_type(fake_display, attribs_with_surface_type, EGL_NO_CONTEXT); | ||
902 | 254 | } | ||
903 | 0 | 255 | ||
904 | === modified file 'tests/unit-tests/scene/test_gl_pixel_buffer.cpp' | |||
905 | --- tests/unit-tests/scene/test_gl_pixel_buffer.cpp 2013-12-17 18:24:51 +0000 | |||
906 | +++ tests/unit-tests/scene/test_gl_pixel_buffer.cpp 2013-12-19 09:13:25 +0000 | |||
907 | @@ -38,8 +38,8 @@ | |||
908 | 38 | struct MockGLContext : public mg::GLContext | 38 | struct MockGLContext : public mg::GLContext |
909 | 39 | { | 39 | { |
910 | 40 | ~MockGLContext() noexcept {} | 40 | ~MockGLContext() noexcept {} |
913 | 41 | MOCK_METHOD0(make_current, void()); | 41 | MOCK_CONST_METHOD0(make_current, void()); |
914 | 42 | MOCK_METHOD0(release_current, void()); | 42 | MOCK_CONST_METHOD0(release_current, void()); |
915 | 43 | }; | 43 | }; |
916 | 44 | 44 | ||
917 | 45 | struct WrappingGLContext : public mg::GLContext | 45 | struct WrappingGLContext : public mg::GLContext |
918 | @@ -49,8 +49,8 @@ | |||
919 | 49 | { | 49 | { |
920 | 50 | } | 50 | } |
921 | 51 | ~WrappingGLContext() noexcept {} | 51 | ~WrappingGLContext() noexcept {} |
924 | 52 | void make_current() { wrapped.make_current(); } | 52 | void make_current() const { wrapped.make_current(); } |
925 | 53 | void release_current() { wrapped.release_current(); } | 53 | void release_current() const { wrapped.release_current(); } |
926 | 54 | 54 | ||
927 | 55 | mg::GLContext& wrapped; | 55 | mg::GLContext& wrapped; |
928 | 56 | }; | 56 | }; |
Note: I'm in the process of testing nested on Android. Although I don't see how this would fail on Android, it'd be courteous to check that nested still works before top approving this :)