Mir

Merge lp:~vanvugt/mir/fix-1259887 into lp:mir

Proposed by Daniel van Vugt
Status: Merged
Approved by: Daniel van Vugt
Approved revision: no longer in the source branch.
Merged at revision: 1508
Proposed branch: lp:~vanvugt/mir/fix-1259887
Merge into: lp:mir
Prerequisite: lp:~vanvugt/mir/shadow
Diff against target: 134 lines (+32/-10)
5 files modified
examples/demo-shell/demo_renderer.cpp (+3/-2)
examples/demo-shell/demo_renderer.h (+2/-1)
include/server/mir/compositor/gl_renderer.h (+7/-1)
src/server/compositor/gl_renderer.cpp (+12/-6)
tests/unit-tests/compositor/test_gl_renderer.cpp (+8/-0)
To merge this branch: bzr merge lp:~vanvugt/mir/fix-1259887
Reviewer Review Type Date Requested Status
Alberto Aguirre (community) Approve
PS Jenkins bot (community) continuous-integration Approve
Alexandros Frantzis (community) Needs Fixing
Daniel van Vugt Abstain
Alan Griffiths Approve
Review via email: mp+211244@code.launchpad.net

Commit message

Ensure surface contents don't appear to stretch during resizing while
the client buffer size catches up to the surface size. (LP: #1259887)

The disadvantage to this approach is that edge pixels on the right and
bottom get clamped and repeated linearly. This is a restriction of OpenGL|ES
as it lacks GL_CLAMP_TO_BORDER support found in full OpenGL. Although
not having a separate border colour might actually be a good thing.

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
Alan Griffiths (alan-griffiths) wrote :

Hmm. I guess this is as good a solution as any - I can't think of anything that has no downside. (I have to admit that my first reaction was "why not draw the same size that the client drew?" but that would not be responsive.)

review: Approve
Revision history for this message
Alexandros Frantzis (afrantzis) wrote :

> Ensure surface contents don't appear to stretch during rapid resizing while the client buffer size catches up to the surface size.

This fix assumes that the upper left corner of the surface is using the texel at (0,0) (i.e., the upper left corner is a stable point), but since we have an overridable tessellation method that may not be true (although it's usually the case).

I think that this should be handled in the tessellate() method, which knows all the details of UV mapping.

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

Alexandros,

Initially I planned to do this in tessellate, certainly. And then I couldn't because it doesn't have a reference to the buffer, and it can't get one right now without also knowing the compositor frameno either. I hope to resolve that in future, but this approach is the one which can be made to work now without waiting for larger changes. You can block waiting for those larger changes, or just trust that "it will get better in future".

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

Actually, I now think there's still a little too much jiggling. Possibly due to lack of floating point precision. That coupled with the visible texture clamping could actually cause more complaints.

review: Needs Fixing
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 :

Changed my mind. This is still a dramatic visual improvement on current resize behaviour. Particularly if you're looking at your window contents during the resize.

review: Abstain
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Revision history for this message
Alexandros Frantzis (afrantzis) wrote :

> I hope to resolve that in future, but this approach is the one which can be made to work now
> without waiting for larger changes. You can block waiting for those larger changes, or just
> trust that "it will get better in future".

I am OK with waiting until we get a proper fix, but it would be good to document this with a TODO and a description with the restriction that this puts on the tessellate function. For example, "For now, if you want sane visual behavior during resize, top left needs to use the surface texel (0pix,0pix)".

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

OK, I've moved the texcoord fiddling back into tessellate() where it belongs. Unfortunately this does mean tessellate() gets another parameter, for now.

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Revision history for this message
Alberto Aguirre (albaguirre) wrote :

LGTM

review: Approve

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-03-21 02:49:38 +0000
3+++ examples/demo-shell/demo_renderer.cpp 2014-03-25 03:43:02 +0000
4@@ -173,9 +173,10 @@
5 }
6
7 void DemoRenderer::tessellate(std::vector<Primitive>& primitives,
8- graphics::Renderable const& renderable) const
9+ graphics::Renderable const& renderable,
10+ geometry::Size const& buf_size) const
11 {
12- GLRenderer::tessellate(primitives, renderable);
13+ GLRenderer::tessellate(primitives, renderable, buf_size);
14 tessellate_shadow(primitives, renderable, 80.0f);
15 tessellate_frame(primitives, renderable, 30.0f);
16 }
17
18=== modified file 'examples/demo-shell/demo_renderer.h'
19--- examples/demo-shell/demo_renderer.h 2014-03-21 02:49:38 +0000
20+++ examples/demo-shell/demo_renderer.h 2014-03-25 03:43:02 +0000
21@@ -34,7 +34,8 @@
22
23 void begin() const override;
24 void tessellate(std::vector<Primitive>& primitives,
25- graphics::Renderable const& renderable) const override;
26+ graphics::Renderable const& renderable,
27+ geometry::Size const& buf_size) const override;
28 void tessellate_shadow(std::vector<Primitive>& primitives,
29 graphics::Renderable const& renderable,
30 float radius) const;
31
32=== modified file 'include/server/mir/compositor/gl_renderer.h'
33--- include/server/mir/compositor/gl_renderer.h 2014-03-21 02:49:38 +0000
34+++ include/server/mir/compositor/gl_renderer.h 2014-03-25 03:43:02 +0000
35@@ -70,6 +70,11 @@
36 * \param [in,out] primitives The list of rendering primitives to be
37 * grown and/or modified.
38 * \param [in] renderable The renderable surface being tessellated.
39+ * \param [in] buf_size The dimensions of the buffer being rendered,
40+ * which can be particularly useful in
41+ * calculating texcoords for a surface being
42+ * actively resized (as the buf_size doesn't
43+ * yet match renderable.size()).
44 *
45 * \note The cohesion of this function to GLRenderer is quite loose and it
46 * does not strictly need to reside here.
47@@ -78,7 +83,8 @@
48 * tessellation is very much OpenGL-specific.
49 */
50 virtual void tessellate(std::vector<Primitive>& primitives,
51- graphics::Renderable const& renderable) const;
52+ graphics::Renderable const& renderable,
53+ geometry::Size const& buf_size) const;
54
55 /**
56 * Load the texture for a surface any which way you like. The default
57
58=== modified file 'src/server/compositor/gl_renderer.cpp'
59--- src/server/compositor/gl_renderer.cpp 2014-03-21 02:49:38 +0000
60+++ src/server/compositor/gl_renderer.cpp 2014-03-25 03:43:02 +0000
61@@ -185,7 +185,8 @@
62 }
63
64 void mc::GLRenderer::tessellate(std::vector<Primitive>& primitives,
65- graphics::Renderable const& renderable) const
66+ graphics::Renderable const& renderable,
67+ geometry::Size const& buf_size) const
68 {
69 auto const& rect = renderable.screen_position();
70 GLfloat left = rect.top_left.x.as_int();
71@@ -198,12 +199,17 @@
72 client.tex_id = 0;
73 client.type = GL_TRIANGLE_STRIP;
74
75+ GLfloat tex_right = static_cast<GLfloat>(rect.size.width.as_int()) /
76+ buf_size.width.as_int();
77+ GLfloat tex_bottom = static_cast<GLfloat>(rect.size.height.as_int()) /
78+ buf_size.height.as_int();
79+
80 auto& vertices = client.vertices;
81 vertices.resize(4);
82- vertices[0] = {{left, top, 0.0f}, {0.0f, 0.0f}};
83- vertices[1] = {{left, bottom, 0.0f}, {0.0f, 1.0f}};
84- vertices[2] = {{right, top, 0.0f}, {1.0f, 0.0f}};
85- vertices[3] = {{right, bottom, 0.0f}, {1.0f, 1.0f}};
86+ vertices[0] = {{left, top, 0.0f}, {0.0f, 0.0f}};
87+ vertices[1] = {{left, bottom, 0.0f}, {0.0f, tex_bottom}};
88+ vertices[2] = {{right, top, 0.0f}, {tex_right, 0.0f}};
89+ vertices[3] = {{right, bottom, 0.0f}, {tex_right, tex_bottom}};
90 }
91
92 void mc::GLRenderer::render(mg::Renderable const& renderable, mg::Buffer& buffer) const
93@@ -239,7 +245,7 @@
94 glEnableVertexAttribArray(texcoord_attr_loc);
95
96 std::vector<Primitive> primitives;
97- tessellate(primitives, renderable);
98+ tessellate(primitives, renderable, buffer.size());
99
100 for (auto const& p : primitives)
101 {
102
103=== modified file 'tests/unit-tests/compositor/test_gl_renderer.cpp'
104--- tests/unit-tests/compositor/test_gl_renderer.cpp 2014-03-21 02:49:38 +0000
105+++ tests/unit-tests/compositor/test_gl_renderer.cpp 2014-03-25 03:43:02 +0000
106@@ -329,6 +329,9 @@
107 EXPECT_CALL(mock_gl, glEnableVertexAttribArray(position_attr_location));
108 EXPECT_CALL(mock_gl, glEnableVertexAttribArray(texcoord_attr_location));
109
110+ EXPECT_CALL(mock_buffer, size())
111+ .WillOnce(Return(mir::geometry::Size{123, 456}));
112+
113 EXPECT_CALL(mock_gl, glBindTexture(GL_TEXTURE_2D, stub_texture));
114 EXPECT_CALL(mock_gl, glVertexAttribPointer(position_attr_location, 3,
115 GL_FLOAT, GL_FALSE, _, _));
116@@ -372,6 +375,8 @@
117 EXPECT_CALL(mock_gl, glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, _));
118
119 EXPECT_CALL(mock_buffer, bind_to_texture());
120+ EXPECT_CALL(mock_buffer, size())
121+ .WillOnce(Return(mir::geometry::Size{123, 456}));
122
123 EXPECT_CALL(mock_gl, glBindTexture(GL_TEXTURE_2D, stub_texture));
124 EXPECT_CALL(mock_gl, glDeleteTextures(1, Pointee(stub_texture)));
125@@ -389,6 +394,9 @@
126 {
127 mtd::MockBuffer mock_buffer;
128
129+ EXPECT_CALL(mock_buffer, size())
130+ .WillRepeatedly(Return(mir::geometry::Size{123, 456}));
131+
132 InSequence seq;
133
134 // First render() - texture generated and uploaded

Subscribers

People subscribed via source and target branches