Merge lp:~ubuntu-sdk-team/ubuntu-ui-toolkit/no-dFdy-trunk into lp:ubuntu-ui-toolkit
- no-dFdy-trunk
- Merge into trunk
Status: | Merged | ||||
---|---|---|---|---|---|
Approved by: | Florian Boucault | ||||
Approved revision: | 1218 | ||||
Merged at revision: | 1217 | ||||
Proposed branch: | lp:~ubuntu-sdk-team/ubuntu-ui-toolkit/no-dFdy-trunk | ||||
Merge into: | lp:ubuntu-ui-toolkit | ||||
Diff against target: |
316 lines (+258/-3) 6 files modified
src/Ubuntu/Components/plugin/plugin.pri (+3/-1) src/Ubuntu/Components/plugin/plugin.qrc (+2/-0) src/Ubuntu/Components/plugin/shaders/shape_no_dfdy.frag (+112/-0) src/Ubuntu/Components/plugin/shaders/shapeoverlay_no_dfdy.frag (+121/-0) src/Ubuntu/Components/plugin/ucubuntushape.cpp (+10/-1) src/Ubuntu/Components/plugin/ucubuntushapeoverlay.cpp (+10/-1) |
||||
To merge this branch: | bzr merge lp:~ubuntu-sdk-team/ubuntu-ui-toolkit/no-dFdy-trunk | ||||
Related bugs: |
|
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
PS Jenkins bot | continuous-integration | Approve | |
Tim Peeters | Abstain | ||
Review via email: mp+268405@code.launchpad.net |
Commit message
Do not use the GL_OES_
Description of the change
Do not use the GL_OES_
This will make the rendering less pretty on systems that do not support the extension.
Tim Peeters (tpeeters) wrote : | # |
Tim Peeters (tpeeters) wrote : | # |
^The image is ugly because I made it inside a vm that scales the screen resolution, but dropbox made it even uglier. Use this link to download the png https:/
Tim Peeters (tpeeters) wrote : | # |
I did not yet verify that this works on the emulator and that it does not break the rendering on devices. We need to do that before landing this.
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:1217
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
deb: http://
Click here to trigger a rebuild:
http://
- 1218. By Tim Peeters
-
remove incorrect inset and dropshadow
Tim Peeters (tpeeters) wrote : | # |
The visual issues mentioned above are now avoided by disabling inset and dropshadows when the required extension is not available.
Tim Peeters (tpeeters) : | # |
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:1218
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
deb: http://
Click here to trigger a rebuild:
http://
Preview Diff
1 | === modified file 'src/Ubuntu/Components/plugin/plugin.pri' |
2 | --- src/Ubuntu/Components/plugin/plugin.pri 2015-08-12 09:54:40 +0000 |
3 | +++ src/Ubuntu/Components/plugin/plugin.pri 2015-08-19 13:59:00 +0000 |
4 | @@ -143,5 +143,7 @@ |
5 | OTHER_FILES += \ |
6 | $$PWD/shaders/shape.vert \ |
7 | $$PWD/shaders/shape.frag \ |
8 | + $$PWD/shaders/shape_no_dfdy.frag \ |
9 | $$PWD/shaders/shapeoverlay.vert \ |
10 | - $$PWD/shaders/shapeoverlay.frag |
11 | + $$PWD/shaders/shapeoverlay.frag \ |
12 | + $$PWD/shaders/shapeoverlay_no_dfdy.frag |
13 | |
14 | === modified file 'src/Ubuntu/Components/plugin/plugin.qrc' |
15 | --- src/Ubuntu/Components/plugin/plugin.qrc 2014-12-01 19:26:16 +0000 |
16 | +++ src/Ubuntu/Components/plugin/plugin.qrc 2015-08-19 13:59:00 +0000 |
17 | @@ -1,8 +1,10 @@ |
18 | <RCC> |
19 | <qresource prefix="/uc"> |
20 | <file>shaders/shape.frag</file> |
21 | + <file>shaders/shape_no_dfdy.frag</file> |
22 | <file>shaders/shape.vert</file> |
23 | <file>shaders/shapeoverlay.frag</file> |
24 | + <file>shaders/shapeoverlay_no_dfdy.frag</file> |
25 | <file>shaders/shapeoverlay.vert</file> |
26 | </qresource> |
27 | </RCC> |
28 | |
29 | === added file 'src/Ubuntu/Components/plugin/shaders/shape_no_dfdy.frag' |
30 | --- src/Ubuntu/Components/plugin/shaders/shape_no_dfdy.frag 1970-01-01 00:00:00 +0000 |
31 | +++ src/Ubuntu/Components/plugin/shaders/shape_no_dfdy.frag 2015-08-19 13:59:00 +0000 |
32 | @@ -0,0 +1,112 @@ |
33 | +// Copyright © 2015 Canonical Ltd. |
34 | +// |
35 | +// This program is free software; you can redistribute it and/or modify |
36 | +// it under the terms of the GNU Lesser General Public License as published by |
37 | +// the Free Software Foundation; version 3. |
38 | +// |
39 | +// This program is distributed in the hope that it will be useful, |
40 | +// but WITHOUT ANY WARRANTY; without even the implied warranty of |
41 | +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
42 | +// GNU Lesser General Public License for more details. |
43 | +// |
44 | +// You should have received a copy of the GNU Lesser General Public License |
45 | +// along with this program. If not, see <http://www.gnu.org/licenses/>. |
46 | +// |
47 | +// Author: Loïc Molinari <loic.molinari@canonical.com> |
48 | + |
49 | +// Static flow control (branching on a uniform value) is fast on most GPUs (including ultra-low |
50 | +// power ones) because it allows to use the same shader execution path for an entire draw call. We |
51 | +// rely on that technique here (also known as "uber-shader" solution) to avoid the complexity of |
52 | +// dealing with a multiple shaders solution. |
53 | +// FIXME(loicm) Validate GPU behavior with regards to static flow control. |
54 | + |
55 | +uniform sampler2D shapeTexture; |
56 | +uniform sampler2D sourceTexture; |
57 | +uniform lowp vec2 opacityFactors; |
58 | +uniform lowp float dfdtFactor; |
59 | +uniform lowp float sourceOpacity; |
60 | +uniform lowp float distanceAA; |
61 | +uniform bool textured; |
62 | +uniform mediump int aspect; |
63 | + |
64 | +varying mediump vec2 shapeCoord; |
65 | +varying mediump vec4 sourceCoord; |
66 | +varying lowp vec4 backgroundColor; |
67 | + |
68 | +const mediump int FLAT = 0x08; // 1 << 3 |
69 | +const mediump int INSET = 0x10; // 1 << 4 |
70 | +const mediump int DROP_SHADOW = 0x20; // 1 << 5 |
71 | + |
72 | +void main(void) |
73 | +{ |
74 | + lowp vec4 shapeData = texture2D(shapeTexture, shapeCoord); |
75 | + lowp vec4 color = backgroundColor; |
76 | + |
77 | + // FIXME(loicm) Would be better to use a bitfield but bitwise ops have only been integrated in |
78 | + // GLSL 1.3 (OpenGL 3) and GLSL ES 3 (OpenGL ES 3). |
79 | + if (textured) { |
80 | + // Blend the source over the current color. |
81 | + // FIXME(loicm) sign() is far from optimal. Call texture2D() at beginning of scope. |
82 | + lowp vec2 axisMask = -sign((sourceCoord.zw * sourceCoord.zw) - vec2(1.0)); |
83 | + lowp float mask = clamp(axisMask.x + axisMask.y, 0.0, 1.0); |
84 | + lowp vec4 source = texture2D(sourceTexture, sourceCoord.st) * vec4(sourceOpacity * mask); |
85 | + color = vec4(1.0 - source.a) * color + source; |
86 | + } |
87 | + |
88 | + // FIXME: Workaround for systems that do not support dFdy() |
89 | + lowp float dfdt = -0.0285; |
90 | + |
91 | +#define NO_DFDY 1 |
92 | + // only FLAT aspect is supported when the dFdy function is not available because |
93 | + // dFdy() is used to determine on which side (top or bottom) in the shape we are. |
94 | + |
95 | +#ifndef NO_DFDY |
96 | + if (aspect == FLAT) { |
97 | +#endif |
98 | + // Mask the current color with an anti-aliased and resolution independent shape mask built |
99 | + // from distance fields. |
100 | + lowp float distanceMin = abs(dfdt) * -distanceAA + 0.5; |
101 | + lowp float distanceMax = abs(dfdt) * distanceAA + 0.5; |
102 | + color *= smoothstep(distanceMin, distanceMax, shapeData.b); |
103 | +#ifndef NO_DFDY |
104 | + |
105 | + } else if (aspect == INSET) { |
106 | + // The vertex layout of the shape is made so that the derivative is negative from top to |
107 | + // middle and positive from middle to bottom. |
108 | + lowp float shapeSide = dfdt * dfdtFactor <= 0.0 ? 0.0 : 1.0; |
109 | + // Blend the shape inner shadow over the current color. The shadow color is black, its |
110 | + // translucency is stored in the texture. |
111 | + lowp float shadow = shapeData[int(shapeSide)]; |
112 | + color = vec4(1.0 - shadow) * color + vec4(0.0, 0.0, 0.0, shadow); |
113 | + // Get the anti-aliased and resolution independent shape mask using distance fields. |
114 | + lowp float distanceMin = abs(dfdt) * -distanceAA + 0.5; |
115 | + lowp float distanceMax = abs(dfdt) * distanceAA + 0.5; |
116 | + lowp vec2 mask = smoothstep(distanceMin, distanceMax, shapeData.ba); |
117 | + // Get the bevel color. The bevel is made of the top mask masked with the bottom mask. A |
118 | + // gradient from the bottom (1) to the middle (0) of the shape is used to factor out values |
119 | + // resulting from the mask anti-aliasing. The bevel color is white with 60% opacity. |
120 | + lowp float bevel = (mask.x * -mask.y) + mask.x; // -ab + a = a(1 - b) |
121 | + lowp float gradient = clamp((shapeSide * -shapeCoord.t) + shapeSide, 0.0, 1.0); |
122 | + bevel *= gradient * 0.6; |
123 | + // Mask the current color then blend the bevel over the resulting color. We simply use |
124 | + // additive blending since the bevel has already been masked. |
125 | + color = (color * vec4(mask[int(shapeSide)])) + vec4(bevel); |
126 | + |
127 | + } else if (aspect == DROP_SHADOW) { |
128 | + // The vertex layout of the shape is made so that the derivative is negative from top to |
129 | + // middle and positive from middle to bottom. |
130 | + lowp int shapeSide = dfdt * dfdtFactor <= 0.0 ? 0 : 1; |
131 | + // Get the anti-aliased and resolution independent shape mask using distance fields. |
132 | + lowp float distanceMin = abs(dfdt) * -distanceAA + 0.5; |
133 | + lowp float distanceMax = abs(dfdt) * distanceAA + 0.5; |
134 | + lowp float mask = smoothstep(distanceMin, distanceMax, shapeData[shapeSide]); |
135 | + // Get the shadow color outside of the shape mask. |
136 | + lowp float shadow = (shapeData.b * -mask) + shapeData.b; // -ab + a = a(1 - b) |
137 | + // Mask the current color then blend the shadow over the resulting color. We simply use |
138 | + // additive blending since the shadow has already been masked. |
139 | + color = (color * vec4(mask)) + vec4(0.0, 0.0, 0.0, shadow); |
140 | + } |
141 | +#endif |
142 | + |
143 | + gl_FragColor = color * opacityFactors.xxxy; |
144 | +} |
145 | |
146 | === added file 'src/Ubuntu/Components/plugin/shaders/shapeoverlay_no_dfdy.frag' |
147 | --- src/Ubuntu/Components/plugin/shaders/shapeoverlay_no_dfdy.frag 1970-01-01 00:00:00 +0000 |
148 | +++ src/Ubuntu/Components/plugin/shaders/shapeoverlay_no_dfdy.frag 2015-08-19 13:59:00 +0000 |
149 | @@ -0,0 +1,121 @@ |
150 | +// Copyright © 2015 Canonical Ltd. |
151 | +// |
152 | +// This program is free software; you can redistribute it and/or modify |
153 | +// it under the terms of the GNU Lesser General Public License as published by |
154 | +// the Free Software Foundation; version 3. |
155 | +// |
156 | +// This program is distributed in the hope that it will be useful, |
157 | +// but WITHOUT ANY WARRANTY; without even the implied warranty of |
158 | +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
159 | +// GNU Lesser General Public License for more details. |
160 | +// |
161 | +// You should have received a copy of the GNU Lesser General Public License |
162 | +// along with this program. If not, see <http://www.gnu.org/licenses/>. |
163 | +// |
164 | +// Author: Loïc Molinari <loic.molinari@canonical.com> |
165 | + |
166 | +// Static flow control (branching on a uniform value) is fast on most GPUs (including ultra-low |
167 | +// power ones) because it allows to use the same shader execution path for an entire draw call. We |
168 | +// rely on that technique here (also known as "uber-shader" solution) to avoid the complexity of |
169 | +// dealing with a multiple shaders solution. |
170 | +// FIXME(loicm) Validate GPU behavior with regards to static flow control. |
171 | + |
172 | +uniform sampler2D shapeTexture; |
173 | +uniform sampler2D sourceTexture; |
174 | +uniform lowp vec2 opacityFactors; |
175 | +uniform lowp float dfdtFactor; |
176 | +uniform lowp float sourceOpacity; |
177 | +uniform lowp float distanceAA; |
178 | +uniform bool textured; |
179 | +uniform mediump int aspect; |
180 | + |
181 | +varying mediump vec2 shapeCoord; |
182 | +varying mediump vec4 sourceCoord; |
183 | +varying lowp vec4 backgroundColor; |
184 | +varying mediump vec2 overlayCoord; |
185 | +varying lowp vec4 overlayColor; |
186 | + |
187 | +const mediump int FLAT = 0x08; // 1 << 3 |
188 | +const mediump int INSET = 0x10; // 1 << 4 |
189 | +const mediump int DROP_SHADOW = 0x20; // 1 << 5 |
190 | + |
191 | +void main(void) |
192 | +{ |
193 | + lowp vec4 shapeData = texture2D(shapeTexture, shapeCoord); |
194 | + lowp vec4 color = backgroundColor; |
195 | + |
196 | + // FIXME(loicm) Would be better to use a bitfield but bitwise ops have only been integrated in |
197 | + // GLSL 1.3 (OpenGL 3) and GLSL ES 3 (OpenGL ES 3). |
198 | + if (textured) { |
199 | + // Blend the source over the current color. |
200 | + // FIXME(loicm) sign() is far from optimal. Call texture2D() at beginning of scope. |
201 | + lowp vec2 axisMask = -sign((sourceCoord.zw * sourceCoord.zw) - vec2(1.0)); |
202 | + lowp float mask = clamp(axisMask.x + axisMask.y, 0.0, 1.0); |
203 | + lowp vec4 source = texture2D(sourceTexture, sourceCoord.st) * vec4(sourceOpacity * mask); |
204 | + color = vec4(1.0 - source.a) * color + source; |
205 | + } |
206 | + |
207 | + // Blend the overlay over the current color. |
208 | + // FIXME(loicm) sign() is far from optimal. |
209 | + lowp vec2 overlayAxisMask = -sign((overlayCoord * overlayCoord) - vec2(1.0)); |
210 | + lowp float overlayMask = clamp(overlayAxisMask.x + overlayAxisMask.y, 0.0, 1.0); |
211 | + lowp vec4 overlay = overlayColor * vec4(overlayMask); |
212 | + color = vec4(1.0 - overlay.a) * color + overlay; |
213 | + |
214 | + // FIXME: Workaround for systems that do not support dFdy() |
215 | + lowp float dfdt = -0.0285; |
216 | + |
217 | +#define NO_DFDY 1 |
218 | + // only FLAT aspect is supported when the dFdy function is not available because |
219 | + // dFdy() is used to determine on which side (top or bottom) in the shape we are. |
220 | + |
221 | +#ifndef NO_DFDY |
222 | + if (aspect == FLAT) { |
223 | +#endif |
224 | + // Mask the current color with an anti-aliased and resolution independent shape mask built |
225 | + // from distance fields. |
226 | + lowp float distanceMin = abs(dfdt) * -distanceAA + 0.5; |
227 | + lowp float distanceMax = abs(dfdt) * distanceAA + 0.5; |
228 | + color *= smoothstep(distanceMin, distanceMax, shapeData.b); |
229 | + |
230 | +#ifndef NO_DFDY |
231 | + } else if (aspect == INSET) { |
232 | + // The vertex layout of the shape is made so that the derivative is negative from top to |
233 | + // middle and positive from middle to bottom. |
234 | + lowp float shapeSide = dfdt * dfdtFactor <= 0.0 ? 0.0 : 1.0; |
235 | + // Blend the shape inner shadow over the current color. The shadow color is black, its |
236 | + // translucency is stored in the texture. |
237 | + lowp float shadow = shapeData[int(shapeSide)]; |
238 | + color = vec4(1.0 - shadow) * color + vec4(0.0, 0.0, 0.0, shadow); |
239 | + // Get the anti-aliased and resolution independent shape mask using distance fields. |
240 | + lowp float distanceMin = abs(dfdt) * -distanceAA + 0.5; |
241 | + lowp float distanceMax = abs(dfdt) * distanceAA + 0.5; |
242 | + lowp vec2 mask = smoothstep(distanceMin, distanceMax, shapeData.ba); |
243 | + // Get the bevel color. The bevel is made of the top mask masked with the bottom mask. A |
244 | + // gradient from the bottom (1) to the middle (0) of the shape is used to factor out values |
245 | + // resulting from the mask anti-aliasing. The bevel color is white with 60% opacity. |
246 | + lowp float bevel = (mask.x * -mask.y) + mask.x; // -ab + a = a(1 - b) |
247 | + lowp float gradient = clamp((shapeSide * -shapeCoord.t) + shapeSide, 0.0, 1.0); |
248 | + bevel *= gradient * 0.6; |
249 | + // Mask the current color then blend the bevel over the resulting color. We simply use |
250 | + // additive blending since the bevel has already been masked. |
251 | + color = (color * vec4(mask[int(shapeSide)])) + vec4(bevel); |
252 | + |
253 | + } else if (aspect == DROP_SHADOW) { |
254 | + // The vertex layout of the shape is made so that the derivative is negative from top to |
255 | + // middle and positive from middle to bottom. |
256 | + lowp int shapeSide = dfdt * dfdtFactor <= 0.0 ? 0 : 1; |
257 | + // Get the anti-aliased and resolution independent shape mask using distance fields. |
258 | + lowp float distanceMin = abs(dfdt) * -distanceAA + 0.5; |
259 | + lowp float distanceMax = abs(dfdt) * distanceAA + 0.5; |
260 | + lowp float mask = smoothstep(distanceMin, distanceMax, shapeData[shapeSide]); |
261 | + // Get the shadow color outside of the shape mask. |
262 | + lowp float shadow = (shapeData.b * -mask) + shapeData.b; // -ab + a = a(1 - b) |
263 | + // Mask the current color then blend the shadow over the resulting color. We simply use |
264 | + // additive blending since the shadow has already been masked. |
265 | + color = (color * vec4(mask)) + vec4(0.0, 0.0, 0.0, shadow); |
266 | + } |
267 | +#endif |
268 | + |
269 | + gl_FragColor = color * opacityFactors.xxxy; |
270 | +} |
271 | |
272 | === modified file 'src/Ubuntu/Components/plugin/ucubuntushape.cpp' |
273 | --- src/Ubuntu/Components/plugin/ucubuntushape.cpp 2015-08-06 13:16:24 +0000 |
274 | +++ src/Ubuntu/Components/plugin/ucubuntushape.cpp 2015-08-19 13:59:00 +0000 |
275 | @@ -52,8 +52,17 @@ |
276 | |
277 | ShapeShader::ShapeShader() |
278 | { |
279 | + QOpenGLContext* context = QOpenGLContext::currentContext(); |
280 | setShaderSourceFile(QOpenGLShader::Vertex, QStringLiteral(":/uc/shaders/shape.vert")); |
281 | - setShaderSourceFile(QOpenGLShader::Fragment, QStringLiteral(":/uc/shaders/shape.frag")); |
282 | + |
283 | + if ( context->isOpenGLES() && |
284 | + !context->hasExtension(QByteArrayLiteral("GL_OES_standard_derivatives")) ) { |
285 | + // dFdy function is not available in fragment shaders |
286 | + qWarning() << "GL_OES_standard_derivatives not available. Using fallback shader for shape."; |
287 | + setShaderSourceFile(QOpenGLShader::Fragment, QStringLiteral(":/uc/shaders/shape_no_dfdy.frag")); |
288 | + } else { |
289 | + setShaderSourceFile(QOpenGLShader::Fragment, QStringLiteral(":/uc/shaders/shape.frag")); |
290 | + } |
291 | } |
292 | |
293 | char const* const* ShapeShader::attributeNames() const |
294 | |
295 | === modified file 'src/Ubuntu/Components/plugin/ucubuntushapeoverlay.cpp' |
296 | --- src/Ubuntu/Components/plugin/ucubuntushapeoverlay.cpp 2015-04-30 19:51:26 +0000 |
297 | +++ src/Ubuntu/Components/plugin/ucubuntushapeoverlay.cpp 2015-08-19 13:59:00 +0000 |
298 | @@ -26,8 +26,17 @@ |
299 | |
300 | ShapeOverlayShader::ShapeOverlayShader() |
301 | { |
302 | + QOpenGLContext* context = QOpenGLContext::currentContext(); |
303 | setShaderSourceFile(QOpenGLShader::Vertex, QStringLiteral(":/uc/shaders/shapeoverlay.vert")); |
304 | - setShaderSourceFile(QOpenGLShader::Fragment, QStringLiteral(":/uc/shaders/shapeoverlay.frag")); |
305 | + |
306 | + if ( context->isOpenGLES() && |
307 | + !context->hasExtension(QByteArrayLiteral("GL_OES_standard_derivatives")) ) { |
308 | + // dFdy function is not available in fragment shaders |
309 | + qWarning() << "GL_OES_standard_derivatives not available. Using fallback shader for shape overlay."; |
310 | + setShaderSourceFile(QOpenGLShader::Fragment, QStringLiteral(":/uc/shaders/shapeoverlay_no_dfdy.frag")); |
311 | + } else { |
312 | + setShaderSourceFile(QOpenGLShader::Fragment, QStringLiteral(":/uc/shaders/shapeoverlay.frag")); |
313 | + } |
314 | } |
315 | |
316 | char const* const* ShapeOverlayShader::attributeNames() const |
I discovered a problem with this MR, see this screenshot: https:/ /www.dropbox. com/s/uy6sro2sp myiq53/ Screenshot% 202015- 08-19%2000. 32.46.png? dl=0
On the left you see the rendering without the extension (you would see that in the emulator), and on the right, the rendering with extension. The fix that we have for rendering without the extension has a shadow at the bottom of the shape that the correct one only has at the top.