Daniel, relying on HW texture minification (or magnification) filters is fast but quite ugly in terms of contour anti-aliasing quality. Using distance fields instead allows for instance to have a 16x16 contour texture that can be rendered at 256x256 at perfect quality. It just requires a texture lookup and a smoothstep(). Retrieving the standard derivatives is almost free since the 4 texels required for the subtraction have already been fetched during the texture lookup (so still cached). It is the perfect thing for the shape since we need to get the shape mask under any scale factor as required by our grid unit system.
This technique has been used for a decade now and is efficient, easy to implement and lightweigth in terms of texture usage. This is for instance also used by QML for text rendering. More info can be found there : http://www.valvesoftware.com/publications/2007/SIGGRAPH2007_AlphaTestedMagnification.pdf -- You received this bug notification because you are a member of Ubuntu Touch seeded packages, which is subscribed to mir in Ubuntu. https://bugs.launchpad.net/bugs/1458694 Title: [vivid-overlay] unity8 fails to start on the emulator Status in Canonical System Image: Confirmed Status in Mir: Invalid Status in mir package in Ubuntu: Invalid Status in ubuntu-ui-toolkit package in Ubuntu: Triaged Bug description: phablet@ubuntu-phablet:~$ system-image-cli -i current build number: 140 device name: generic_x86 channel: ubuntu-touch/rc-proposed/ubuntu last update: 2015-05-25 12:02:10 version version: 140 version ubuntu: 20150525 version device: 20150210 version custom: 20150525 When starting unity8 (this started at image 136, probably when mir 0.13 landed): phablet@ubuntu-phablet:~$ cat ./.cache/upstart/unity8.log () [1432595001.896139] mirplatform: Found graphics driver: dummy [1432595001.898447] mirplatform: Found graphics driver: android qtmir.mir: MirServer created [1432595003.675225] Server: Starting [1432595003.679331] Loader: Loading modules from: /usr/lib/i386-linux-gnu/mir/server-platform [1432595003.679501] Loader: Loading module: /usr/lib/i386-linux-gnu/mir/server-platform/graphics-dummy.so [1432595003.680673] Loader: Loading module: /usr/lib/i386-linux-gnu/mir/server-platform/input-stub.so [1432595003.681107] <WARNING> Loader: Failed to load module: /usr/lib/i386-linux-gnu/mir/server-platform/input-stub.so (error was:/usr/lib/i386-linux-gnu/mir/server-platform/input-stub.so: undefined symbol: _ZN3mir6events10make_eventExx17MirKeyboardActionjij) [1432595003.684868] Loader: Loading module: /usr/lib/i386-linux-gnu/mir/server-platform/graphics-android.so.2 [1432595003.685014] mirplatform: Found graphics driver: dummy [1432595003.685211] mirplatform: Found graphics driver: android [1432595003.685416] Platform Loader: Selected driver: android (version 0.13.0) qtmir.mir: PromptSessionListener::PromptSessionListener - this= PromptSessionListener(0x9679764) qtmir.mir: SessionListener::SessionListener - this= SessionListener(0x9676d24) qtmir.mir: MirShell::MirShell [1432595003.883766] DisplayServer: Mir version 0.13.0 QtCompositor::setAllWindowsExposed true qtmir.clipboard: D-Bus registration successful. Mode argument was not provided or was set to an illegal value. Using default value of --mode= "full-greeter" Cannot create window: no screens available With version 135 it starts fine, but not fully functional, giving this error: QOpenGLShader::compile(Fragment): 0:2(12): warning: extension `GL_OES_standard_derivatives' unsupported in fragment shader 0:2(1): error: #extension directive is not allowed in the middle of a shader *** Problematic Fragment shader source code *** #extension GL_OES_standard_derivatives : enable // Enable dFdy() on OpenGL ES 2. #define lowp #define mediump #define highp // Copyright © 2015 Canonical Ltd. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU Lesser General Public License as published by // the Free Software Foundation; version 3. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public License // along with this program. If not, see <http://www.gnu.org/licenses/>. // // Author: Loïc Molinari <loic.molin...@canonical.com> // Static flow control (branching on a uniform value) is fast on most GPUs (including ultra-low // power ones) because it allows to use the same shader execution path for an entire draw call. We // rely on that technique here (also known as "uber-shader" solution) to avoid the complexity of // dealing with a multiple shaders solution. // FIXME(loicm) Validate GPU behavior with regards to static flow control. uniform sampler2D shapeTexture; uniform sampler2D sourceTexture; uniform lowp vec2 dfdtFactors; uniform lowp vec2 opacityFactors; uniform lowp float sourceOpacity; uniform lowp float distanceAA; uniform bool textured; uniform mediump int aspect; varying mediump vec2 shapeCoord; varying mediump vec4 sourceCoord; varying lowp vec4 backgroundColor; const mediump int FLAT = 0x08; // 1 << 3 const mediump int INSET = 0x10; // 1 << 4 void main(void) { lowp vec4 shapeData = texture2D(shapeTexture, shapeCoord); lowp vec4 color = backgroundColor; // FIXME(loicm) Would be better to use a bitfield but bitwise ops have only been integrated in // GLSL 1.3 (OpenGL 3) and GLSL ES 3 (OpenGL ES 3). if (textured) { // Blend the source over the current color. // FIXME(loicm) sign() is far from optimal. Call texture2D() at beginning of scope. lowp vec2 axisMask = -sign((sourceCoord.zw * sourceCoord.zw) - vec2(1.0)); lowp float mask = clamp(axisMask.x + axisMask.y, 0.0, 1.0); lowp vec4 source = texture2D(sourceTexture, sourceCoord.st) * vec4(sourceOpacity * mask); color = vec4(1.0 - source.a) * color + source; } // Get screen-space derivative of texture coordinate t representing the normalized distance // between 2 pixels. dFd*() unfortunately have to be called outside of branches in order to work // correctly with VMware's "Gallium 0.4 on SVGA3D". lowp vec2 derivatives = vec2(dFdx(shapeCoord.t), dFdy(shapeCoord.t)); lowp float dfdt = dfdtFactors.x != 0.0 ? derivatives.x : derivatives.y; if (aspect == FLAT) { // Mask the current color with an anti-aliased and resolution independent shape mask built // from distance fields. lowp float distanceMin = abs(dfdt) * -distanceAA + 0.5; lowp float distanceMax = abs(dfdt) * distanceAA + 0.5; color *= smoothstep(distanceMin, distanceMax, shapeData.b); } else if (aspect == INSET) { // The vertex layout of the shape is made so that the derivative is negative from top to // middle and positive from middle to bottom. lowp float shapeSide = dfdt * dfdtFactors.y <= 0.0 ? 0.0 : 1.0; // Blend the shape inner shadow over the current color. The shadow color is black, its // translucency is stored in the texture. lowp float shadow = shapeData[int(shapeSide)]; color = vec4(1.0 - shadow) * color + vec4(0.0, 0.0, 0.0, shadow); // Get the anti-aliased and resolution independent shape mask using distance fields. lowp float distanceMin = abs(dfdt) * -distanceAA + 0.5; lowp float distanceMax = abs(dfdt) * distanceAA + 0.5; lowp vec2 mask = smoothstep(distanceMin, distanceMax, shapeData.ba); // Get the bevel color. The bevel is made of the top mask masked with the bottom mask. A // gradient from the bottom (1) to the middle (0) of the shape is used to factor out values // resulting from the mask anti-aliasing. The bevel color is white with 60% opacity. lowp float bevel = (mask.x * -mask.y) + mask.x; // -ab + a = a(1 - b) lowp float gradient = clamp((shapeSide * -shapeCoord.t) + shapeSide, 0.0, 1.0); bevel *= gradient * 0.6; // Mask the current color then blend the bevel over the resulting color. We simply use // additive blending since the bevel has already been masked. color = (color * vec4(mask[int(shapeSide)])) + vec4(bevel); } gl_FragColor = color * opacityFactors.xxxy; } *** shader compilation failed: "" Adb is broken because of bug 1458043, so use the following workaround to get it to work again: $ sudo ubuntu-emulator create --channel=ubuntu-touch/rc-proposed/ubuntu test_x86 --use-raw-disk $ mkdir -p /tmp/mount1 /tmp/mount2 $ sudo mount ~/.local/share/ubuntu-emulator/test_x86/sdcard.img /tmp/mount1 $ sudo mount /tmp/mount1/system.img /tmp/mount2 $ sudo vi /tmp/mount2/var/lib/lxc/android/pre-start.d/20-no-default-prop-adb #! /bin/sh # Avoid changing the the property when running on the emulator if ! grep -q "qemu=1" /proc/cmdline; then sed -i '/^persist.sys.usb.config=.*/d' $LXC_ROOTFS_PATH/default.prop || true fi $ sudo umount /tmp/mount2 $ sudo umount /tmp/mount1 To manage notifications about this bug go to: https://bugs.launchpad.net/canonical-devices-system-image/+bug/1458694/+subscriptions -- Mailing list: https://launchpad.net/~touch-packages Post to : touch-packages@lists.launchpad.net Unsubscribe : https://launchpad.net/~touch-packages More help : https://help.launchpad.net/ListHelp