Mir

Merge lp:~albaguirre/mir/make-screencast-capture-opaque into lp:mir

Proposed by Alberto Aguirre
Status: Rejected
Rejected by: Alberto Aguirre
Proposed branch: lp:~albaguirre/mir/make-screencast-capture-opaque
Merge into: lp:mir
Diff against target: 135 lines (+46/-9)
7 files modified
examples/demo-shell/demo_renderer.cpp (+0/-4)
include/test/mir_test_doubles/mock_gl.h (+1/-0)
src/server/compositor/gl_renderer.cpp (+0/-4)
src/server/compositor/screencast_display_buffer.cpp (+18/-0)
tests/mir_test_doubles/mock_gl.cpp (+6/-0)
tests/unit-tests/compositor/test_gl_renderer.cpp (+0/-1)
tests/unit-tests/compositor/test_screencast_display_buffer.cpp (+21/-0)
To merge this branch: bzr merge lp:~albaguirre/mir/make-screencast-capture-opaque
Reviewer Review Type Date Requested Status
Daniel van Vugt Needs Fixing
PS Jenkins bot (community) continuous-integration Approve
Review via email: mp+218889@code.launchpad.net

Commit message

Make screencast capture opaque.

This is an alternative fix to LP: #1301210 which also addresses LP: #1317260

Description of the change

Make screencast capture opaque.

This is an alternative fix to LP: #1301210 which also addresses LP: #1317260

To post a comment you must log in.
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Revision history for this message
Daniel van Vugt (vanvugt) wrote :

I suggest this perhaps should not be fixed. If we have any nested servers utilizing the alpha channel that's an unacceptable performance hit on anything other than high-end hardware. Fixing this bug just supports people writing very bad graphics code.

Revision history for this message
Daniel van Vugt (vanvugt) wrote :

Oh, I remember now. We agreed nested servers would sometimes need to be blended for fancy shaped transitions. But we also agreed they must not use the alpha channel during regular usage. So a fix will be required at some stage. But at the same time, it does suggest we have slow-rendering nested Mir servers around that need improving.

Revision history for this message
Daniel van Vugt (vanvugt) wrote :

(1) There's a performance issue here; glGet functions require a round-trip stalling the pipeline:
57 + glGetFloatv(GL_COLOR_CLEAR_VALUE, old_clear_color);
58 + glGetBooleanv(GL_COLOR_WRITEMASK, old_color_mask);
[http://www.opengl.org/wiki/Common_Mistakes#glGetFloatv_glGetBooleanv_glGetDoublev_glGetIntegerv]
But maybe it's OK in this case since it's immediately before glFinish() which is a definitive round-trip sync anyway.

(2) glClear() in the post_update() function looks like it's almost certainly in the wrong place. It can only work if you assume the compositor recycles the framebuffer, which is a dangerous assumption(?)
74 + make_opaque();
75 glFinish();

(3) Calling glClear() twice per frame is a major bottleneck [1] which should be avoided. How about something like:
void mc::GLRenderer::begin() const
{
    glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
    glClear(GL_COLOR_BUFFER_BIT);
    glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_FALSE);
}
...?

[1] https://bugs.launchpad.net/mir/+bug/1170243

review: Needs Fixing
Revision history for this message
Alberto Aguirre (albaguirre) wrote :

(1) Ack - but I didn't want to just change state and not restore it though.
(2) Ack - I just don't know of any better place that only appliest to screencasting though.

(3) That's what I had on the previous MP (https://code.launchpad.net/~albaguirre/mir/render-opaque-background/+merge/218712)
    Except you have to set the clear color since the default has alpha set to 0.0

However, should be messing with the alpha at all in the normal rendering path? Or should we just impose that the compositor will enforce opaqueness once it's done? I think it *NEEDS DISCUSSION* - but I'm leaning towards opaqueness.

In any case the purpose of this MP was to *FOR NOW* limit the opaqueness decision to screencasting only.

Revision history for this message
Alberto Aguirre (albaguirre) wrote :

OK, after some more thought I do think the previous MP (https://code.launchpad.net/~albaguirre/mir/render-opaque-background/+merge/218712) is a better solution.

Currently mir does not support transparent framebuffers properly anyway (per-pixel alpha in resulting framebuffer is not correct).

Unmerged revisions

1613. By Alberto Aguirre

Make screencast capture opaque.

This is an alternative fix to LP: #1301210 which also addresses LP: #1317260

1612. By Alberto Aguirre

Revert r1581.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'examples/demo-shell/demo_renderer.cpp'
2--- examples/demo-shell/demo_renderer.cpp 2014-05-05 03:36:45 +0000
3+++ examples/demo-shell/demo_renderer.cpp 2014-05-08 22:14:30 +0000
4@@ -156,10 +156,6 @@
5 {
6 glClearColor(0.2f, 0.2f, 0.2f, 1.0f);
7 glClear(GL_COLOR_BUFFER_BIT);
8-
9- // Ensure we don't change the framebuffer's alpha components (if any)
10- // as that would ruin the appearance of screengrabs. (LP: #1301210)
11- glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_FALSE);
12 }
13
14 void DemoRenderer::tessellate(std::vector<Primitive>& primitives,
15
16=== modified file 'include/test/mir_test_doubles/mock_gl.h'
17--- include/test/mir_test_doubles/mock_gl.h 2014-05-05 03:36:45 +0000
18+++ include/test/mir_test_doubles/mock_gl.h 2014-05-08 22:14:30 +0000
19@@ -47,6 +47,7 @@
20 void(GLenum, GLsizeiptr, const GLvoid *, GLenum));
21 MOCK_METHOD1(glCheckFramebufferStatus, GLenum(GLenum));
22 MOCK_METHOD1(glClear, void(GLbitfield));
23+ MOCK_METHOD4(glClearColor, void(GLclampf, GLclampf, GLclampf, GLclampf));
24 MOCK_METHOD4(glColorMask, void(GLboolean, GLboolean, GLboolean, GLboolean));
25 MOCK_METHOD1(glCompileShader, void(GLuint));
26 MOCK_METHOD0(glCreateProgram, GLuint());
27
28=== modified file 'src/server/compositor/gl_renderer.cpp'
29--- src/server/compositor/gl_renderer.cpp 2014-05-06 03:33:05 +0000
30+++ src/server/compositor/gl_renderer.cpp 2014-05-08 22:14:30 +0000
31@@ -290,10 +290,6 @@
32 void mc::GLRenderer::begin() const
33 {
34 glClear(GL_COLOR_BUFFER_BIT);
35-
36- // Ensure we don't change the framebuffer's alpha components (if any)
37- // as that would ruin the appearance of screengrabs. (LP: #1301210)
38- glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_FALSE);
39 }
40
41 void mc::GLRenderer::end() const
42
43=== modified file 'src/server/compositor/screencast_display_buffer.cpp'
44--- src/server/compositor/screencast_display_buffer.cpp 2014-03-26 05:48:59 +0000
45+++ src/server/compositor/screencast_display_buffer.cpp 2014-05-08 22:14:30 +0000
46@@ -24,6 +24,23 @@
47 namespace mc = mir::compositor;
48 namespace mg = mir::graphics;
49 namespace geom = mir::geometry;
50+namespace
51+{
52+void make_opaque()
53+{
54+ // Ensure screen captures are opaque (LP: #1301210)
55+ GLfloat old_clear_color[4] {0.0f, 0.0f, 0.0f, 0.0f};
56+ GLboolean old_color_mask[4] {GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE};
57+ glGetFloatv(GL_COLOR_CLEAR_VALUE, old_clear_color);
58+ glGetBooleanv(GL_COLOR_WRITEMASK, old_color_mask);
59+
60+ glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
61+ glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_TRUE);
62+ glClear(GL_COLOR_BUFFER_BIT);
63+ glClearColor(old_clear_color[0], old_clear_color[1], old_clear_color[2], old_clear_color[3]);
64+ glColorMask(old_color_mask[0], old_color_mask[1], old_color_mask[2], old_color_mask[3]);
65+}
66+}
67
68 mc::ScreencastDisplayBuffer::ScreencastDisplayBuffer(
69 geom::Rectangle const& rect,
70@@ -97,6 +114,7 @@
71
72 void mc::ScreencastDisplayBuffer::post_update()
73 {
74+ make_opaque();
75 glFinish();
76 }
77
78
79=== modified file 'tests/mir_test_doubles/mock_gl.cpp'
80--- tests/mir_test_doubles/mock_gl.cpp 2014-05-05 03:36:45 +0000
81+++ tests/mir_test_doubles/mock_gl.cpp 2014-05-08 22:14:30 +0000
82@@ -90,6 +90,12 @@
83 global_mock_gl->glColorMask(r, g, b, a);
84 }
85
86+void glClearColor(GLclampf r, GLclampf g, GLclampf b, GLclampf a)
87+{
88+ CHECK_GLOBAL_VOID_MOCK();
89+ global_mock_gl->glClearColor(r, g, b, a);
90+}
91+
92 void glEnable(GLenum func)
93 {
94 CHECK_GLOBAL_VOID_MOCK();
95
96=== modified file 'tests/unit-tests/compositor/test_gl_renderer.cpp'
97--- tests/unit-tests/compositor/test_gl_renderer.cpp 2014-05-06 03:33:05 +0000
98+++ tests/unit-tests/compositor/test_gl_renderer.cpp 2014-05-08 22:14:30 +0000
99@@ -167,7 +167,6 @@
100 InSequence seq;
101
102 EXPECT_CALL(mock_gl, glClear(_));
103- EXPECT_CALL(mock_gl, glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_FALSE));
104 EXPECT_CALL(mock_gl, glUseProgram(stub_program));
105 EXPECT_CALL(*renderable, shaped())
106 .WillOnce(Return(true));
107
108=== modified file 'tests/unit-tests/compositor/test_screencast_display_buffer.cpp'
109--- tests/unit-tests/compositor/test_screencast_display_buffer.cpp 2014-03-05 07:02:29 +0000
110+++ tests/unit-tests/compositor/test_screencast_display_buffer.cpp 2014-05-08 22:14:30 +0000
111@@ -184,3 +184,24 @@
112
113 db.render_and_post_update(renderables, std::ref(mock_render_functor));
114 }
115+
116+TEST_F(ScreencastDisplayBufferTest, makes_capture_opaque)
117+{
118+ using namespace testing;
119+
120+ geom::Rectangle const rect{{100,100}, {800,600}};
121+ mtd::StubBuffer stub_buffer;
122+
123+ mc::ScreencastDisplayBuffer db{rect, stub_buffer};
124+
125+ Mock::VerifyAndClearExpectations(&mock_gl);
126+
127+ InSequence s;
128+ EXPECT_CALL(mock_gl, glClearColor(_, _, _, 1.0f));
129+ EXPECT_CALL(mock_gl, glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_TRUE));
130+ EXPECT_CALL(mock_gl, glClear(GL_COLOR_BUFFER_BIT));
131+ EXPECT_CALL(mock_gl, glClearColor(_, _, _, _));
132+ EXPECT_CALL(mock_gl, glColorMask(_, _, _, _));
133+
134+ db.post_update();
135+}

Subscribers

People subscribed via source and target branches