Skip navigation.

Log in | Sign up

Opera Core Concerns

Official blog for Core developers at Opera

Automated regression testing of the browser core

, , ,

The cornerstone of all testing done on the core of the Opera browser is our automated regression testing system, named SPARTAN. The system consists of a central server and about 50 test machines running our 120 000 automated tests on all core reference builds. The purpose of this system is to help us discover any new bugs we introduce as early as possible, so that we can fix them before they cause any trouble for our users.

Step one: Preparing a build

Before SPARTAN can test anything, it will require a build to test. Our build system automatically creates builds every night and pings SPARTAN when they are ready. Developers and testers can also request their own builds from the build system, using any build tag they want, to test stuff from their own experimental branches before this is eventually merged into the stable mainline we base our products on.

Unlike other browser vendors we ship our browser on a variety of different platforms. So our core build packages do not contain just one binary, but several. One for each general product category. Each of these profiles have the same feature set and memory constraints as the platform they correspond to. The whole set of tests are run on each of these profiles.

Step two: Testing

When the SPARTAN server is informed about the existence of a new build it will add this build to its testing queue and distribute a few hundred tests to each of the test machines the next time they ask for more work. Each test machine works independently with its assigned tests. It will download the Opera binaries it has been told to use, and run its assigned tests on it. Once it has finished its batch of tests, it will pass the test results back to the SPARTAN server, and again ask what to do next.

If it ever runs out of new builds to test, for example during the weekend, it will look back at older builds and run any newly added tests on them too. This to ensure that we have a full history for each test, and at any time can determine when a fix or regression was first introduced without having to manually test things again.

We have several different types of tests:

Unit tests
Unit tests (or selftests), written by the same developers who write the running code, tests individual functions and APIs.
JavaScript tests
Our JavaScript tests test a wide array of different features on a functional level. This includes for example tests for the Selectors API, tests for common JavaScript frameworks, or any other feature we can interact with through JavaScript.
Watir tests
Many tests require some sort of user interaction. To test forms, for example, one must click buttons or checkboxes or type in text fields. To avoid having to do this manually, we have implemented support for the cross-browser Watir API. While others use this API to test their web applications, we use it to test the browser itself.
Visual tests
To test our stylesheet and graphics code, we need to test that our visual test cases look right. Some of our visual tests automatically compare two pages or two elements to determine whether they are the same. On other tests, the test machines will take a screenshot of the rendered page and pass it back to the SPARTAN server. If the SPARTAN server has seen this screenshot before, it will know whether that particular rendering means PASS or FAIL. If SPARTAN has never seen it before, the screenshot must be labeled as PASS or FAIL by a human. This is labour-intensive work we intend to further reduce through reftests.
Performance tests
A modern browser must not only pass tests for all its different features. It must also be fast. SPARTAN runs a number of different performance tests, both internally and externally developed, on our builds. If Opera becomes slower at any particular test, this will be flagged as a regression.
Crash tests
We create test cases for every single bug we analyze and fix, and SPARTAN runs most of these. Among our bug-based test cases are crash tests. If Opera can load these tests without crashing, the test has passed. If it crashes, we have reintroduced an old crash, and must fix it.

All in all, we currently run about 120 000 tests on each configuration in each build, but this number changes daily. We continuously write new test cases for bugs or test suites for new or old features, and we also copy any publicly available test suites we find useful. Right now we are also working on automating many of our previously manual tests, including memory tests.

Step three: Human intervention

Once the machines are done with their part of the job with any particular build, they will send an email to a human who will continue the work. SPARTAN will generate a report of changes between this build and the previous build. In most builds there are some tests that go from FAIL to PASS because we have fixed something. But there are also often regressions—tests that go from PASS to FAIL—because we accidentally broke something while fixing something else. This is expected, and is the reason for why we do regression testing. We know there will always be regressions, and need to find them as quickly as possible in order to fix them before they can cause any trouble for users or customers.

The human tester will analyze each regressed test. If a hundred different tests started failing at the same time, they could all have broke because of one regression, or there could be several different ones. For each unique regression identified the human tester will report a new bug and assign it to the developer responsible for the code that broke. Once a fix is ready, we will run all our tests again.

Opera's site patching

,

You know the complexity of web technology is getting out of hand when every website needs some special treatment. Imagine driving a car if you had to change the engine slightly or replace wheels every time you turned a corner and entered a new street? Browser development is a lot like that these days.

Nearly every modern browser has site patching features, to grease the wheels where the nuts and bolts of standards are exposed to the unpredictable elements of the web:

Treating every site differently? That sounds insane. It's clearly impossible. For starters, there are billions of websites, all different. And they keep changing with millions of lines of code being added or changed every day. Who can possibly keep up with that? Besides, aren't standards supposed to be the answer?

Standards

I commend the standardisation efforts and the evangelists at The Web Standards Project and elsewhere. Without you we would be far, far worse off. The future might even be on your side - more and more sites validating and cleaning up their standards story. Power to you!

Various Opera teams take part in the standards work too, including doing education and outreach. Our Open The Web team contacts web sites with advice on cross-browser compatibility and standards compliance.

But the browser is the user's agent. Across all sites breaking the rules and standards in different ways, we owe the user to do anything we can to make them all work whenever possible. Often a broken site is not our fault, but it's most definitely our problem. And we must make it work today. Not in 2022..

Hence, we patch.

Since we see various more or less ad-hoc approaches to site patching develop among our fellow browser vendors, it seems like a good time to share some of our experiences - what I think are the strengths and constraints of our particular implementation.

Strengths

Experience

Opera has more experience with site-specific patches than other browser vendors, since we've been patching the web since Opera 8.01. I believe our solution is also by far the most advanced one. Special commands available to User JavaScripts make up a simple yet powerful API for modifying and correcting a website. With getters and setters and DOM interfaces we can change Opera's behaviour to match most standard deviations the script expects. Sometimes we add a specific missing style or even remove some object or policy that gets in the way. And when a web site uses browser sniffing we can often dig in and repair the exact line of code that is broken! Some random examples:

  • We can add the single missing class name when AOL Japan abuses browser detection and doesn't apply correct styles, and correct AOL webmail's spelling mistake when they spell dojoType as dojotype.
  • We can fall back to a graceful postMessage() call when E*Trade tries to violate the security policy against navigating another site's frame when it loads encrypted content

We can also override settings like what browser we identify as and what rendering mode (quirks or standards) we should use for a specific site through downloadable preferences.

Bugfixes

Given the power to change websites and change Opera, we can sometimes even work around our own bugs.

  • When the menu on weather.com disappears because mouse events happen in the wrong order, I can re-order them
  • When search results on Google Codesearch appear as white-on-white I can re-style them

Now there's a thought. Opera - the browser that works around its bugs so you don't have to? This is like a time machine - we can fix our past sins for already released versions.

In the long term, this is a very important and subtle effect of browser.js: there will be less Opera-specific hacks to worry about. Both IE8's upgrade woes and our own experience tells us that workarounds against our own old bugs are among our worst problems. We did the wrong thing, sites did the wrong thing in response. We fixed it on our side, but the web never forgets your old bugs.

The difference with browser.js? When we release a new version with bug fixes, corresponding browser.js patches are secretly dropped as obsolete. What used to work because of browser.js hacks keeps working because the new version supports it, making the upgrade experience smoother for users and web developers alike, and a lot simpler for us. I can almost feel the envy of the IE8 team across the Atlantic.

Another interesting effect is that we can implement new standards with less worries. When HTML5's <input required> feature breaks Barnes & Noble because the user name field in the login form isn't really required input after all when you click the "create account" button - we can first patch it, and later tell the spec editor about our problems and discuss if the spec can be made more web-compatible.

Transparency

From the very beginning, one of the main concerns was that our fixes would prevent webmasters from finding and correcting problems. We might even end up creating problems if our patches linger on while the site changes.

To make things as transparent as possible, the patches are documented, we try to keep the file itself readable and reasonably well commented (though we also try to avoid unnecessary download bloat). And every patch applied will output a message in Opera's error console trying to make it obvious what is going on.

Scope

Site patching is cross-platform. Actually, that's an understatement. Did you know we have site patches for Nintendo Wii? And for the DSi? For Opera on Windows Mobile, Symbian, BREW and Archos's portable media players? Heck, we even have patches for Opera Mini!

  • When Hotmail and Yahoo mail require rich text editing to compose E-mail we can fake rich text support even on devices with input and CPU limitations where rich text support is impossible
  • If Facebook's fancy animations take too long to run for the Opera Mini server - it needs to pass content on to the actual client after all - we can cut them short and yet perform the important actions Facebook saved for the end of the animation.

It's an ambitious scope, probably much more ambitious than it might seem from the outside. The devices and platforms have very different requirements and problems. For example:

  • On the Wii we have a minimum font size to keep things readable - but this often causes unexpected widths, wrapping and repositioning content in ways that don't happen on a Desktop browser. We patch several sites that have too rigid positioning to accomodate a slightly larger font size.
  • Using an on-screen keyboard on the Wii and many mobile phones means the window resizes itself every time you focus a form element - to make room for the keyboard. When British Airways re-loads the booking page every time you resize it, booking a ticket with a virtual keyboard becomes pretty hard...
  • ..and when eBay in France tries to count your keydown events to make sure you don't cheat and paste your e-mail address into the registration form's "re-type E-mail" field it won't work with on-screen keyboards either. Some of them just don't support key events. Come on eBay, I really did type it in. I mean, REALLY! On hardware where cut-and-paste isn't even AVAILABLE!...

When dealing with such a range of problems the true and magic potential of browser.js becomes apparent.

Infrastructure

To support all this, we need some nifty download servers picking the correct file for any client that asks for one. We have a database of patches and meta data like what versions and platforms a patch applies to. But did you know we also have a script spidering sites to check if broken parts are still there? When a patched site changes a relevant piece of code, I want to know about it. I love the sound patches make when they hit the virtual "obsolete" bin.

Constraints

Time

So much power, so little time.. Analysing sites and developing patches takes a lot of time. We are nowhere near IE8's overwhelming list of 2400+ sites. (Actually, browsing the IE8 list is a Déjà vu experience. Many familiar names, many sites we need to patch or contact for various reasons too.)

Nevertheless, our list is shorter - fortunately! Technical analysis with the level of detail required to support our site patching can be very time consuming, so I hope we'll remain smaller and more focused than the IE list. We will however scale the efforts up - we're at 600+ entries in the database and there is room for plenty of more - and we welcome contributions.

Performance

I just said there is room for plenty of more patches. But how far can we scale site patching before performance suffers too much?

Apparently we can keep going for quite a while. Some profiling work we did recently indicates that we can patch upwards of 10 000 specific sites without slowing Opera down by more than a couple of percentage points. And frankly, by the time we've written patches for 10 000 sites you've probably bought a more powerful computer..

Security

Isn't it unsafe? Can't a virus or malicious server fake your browser.js file and gain instant control of your Opera browsing?

The short answer is: no.

The longer answer is that this would be possible without our security precautions, but it is in fact all taken care of. Every file is signed, so Opera can check that it is a genuine file and that it has not been tampered with. Such a signature is very, very hard to fake. If a malicious server or virus alters the file, Opera will stop using it and try to download a fresh version from the server.

Conclusions

One of the things that surprised me most about browser.js work is how quickly the web changes. By paying such close attention to specific sites we see the web as a whole evolve, and it's iterating faster than I would have dared to expect. And contrary to what you might expect, we do see sites change to become more Opera-friendly after we've patched them!

That means site patcing works. It works because it improves compatibility, thereby giving users a real choice in browsers and - as weird as it may sound - as a direct effect of that, it gives webmasters incentives to make sure their sites are Opera- and cross-browser-compatible.

Welcome to the future - made of and with standards, openness and site patching.


About the author

Hallvord R. M. Steen works for Opera's core team on quality assurance, testing and web compatibility. He maintains the browser.js file and can break all websites worldwide with a minor typo.

Geolocation-enabled build

, ,

We are delighted to release the first build of Opera with geolocation support. The geolocation Working Group of the W3C has recently relased the first Working Draft of the geolocation API specification, and we are now releasing the first Labs build with support for the API.

The API is used in a web page's Javascript code to retrieve the current latitude and longitude of the browser. The following snippet shows how a web page would request the browser's location:

// One-shot position request:
navigator.geolocation.getCurrentPosition(showMapCallback);

function showMapCallback(position) {
  // Show a map centered at (position.coords.latitude, position.coords.longitude).
}

As you can see, the API is very simple, and doesn't get much more complicated with more advanced functionalities (see more examples from the specification)

Geolocation on the web is not new. Many sites already use the IP address of the browser to serve targetted content, mostly ads (you will have seen the 'Find a Friend in [your city]' banners). However, that method is notoriously inaccurate and cannot be reliably used for more advanced geolocation services. On the other hand, the device which the browser is running on is more likely to have an accurate idea of its location if it has a GPS unit or can triangulate the wireless access points or cell towers, or look up its IP address. Even if the device doesn't have the right hardware, a location provider web service can be used. This build uses the Skyhook service, and therefore you will need to register your site on loki.com in order for your geo-enabled web application to be allowed to request the locations of users. Additionally, if you're running Windows XP you will also need to run svcsetup.exe, which ensures that wifi scanning will not be affected by various "wifi managers" that are shipped with many laptops. All this won't be necessary in future releases, but for now if you experience crashes, it is likely because you need to run svcsetup.exe first.

More importantly, leaving it to the browser to transmit its location means that the user can remain in control of their privacy. This build will prompt the user if they agree to send their location, every time a site requests it. While the UI in this build is experimental, it provides one possible way of protecting the user's privacy.

The W3C Geolocation API is likely to become a widely adopted standard, and Opera is providing this early implementation of the API to let developers and users start experimenting with it. We would be very grateful for feedback from both developers and users, on the API itself and on what functionality and level of privacy control you would like to see exposed in the user interface.

Once you have installed this build, you can go and test it out on our geolocation demo page, which will show were you are on a map, and will display scheduled near you.

Test automation with OperaWatir

, ,

To make sure new versions of our browser core are of sufficient quality before making their way into any of our products, we run more than 100,000 automated tests on a number of different reference configurations every time we have a new build.

We run automated visual tests, JavaScript tests, selftests, performance tests, stability tests, memory tests and a lot more. One thing we have been missing, however, is automated tests for the things that require some sort of user interaction--clicking links, filling out forms, interacting with complex Web applications.

That is ... until now.

We are working on adding support for driving the browser through our scope protocol, which is the same protocol we use for the Opera Dragonfly debugger. Through a simple script, we can instruct the browser to automatically to search Google, log into Hotmail and send a message, buy books at Amazon or find plane tickets at Expedia.

Here's an example of what such a script can look like:

require "operawatir"

browser = OperaWatir::Opera.new
browser.goto("http://www.google.com")
browser.text_field(:name, "q").value = "Wikipedia"
browser.button(:name, "btnG").click

browser.link(:text, "Wikipedia").click

puts "PASS" if browser.text.include? "Wikipedia"

The syntax above is that of the Watir API, a Ruby test tool originally developed for Internet Explorer that is now being ported to Opera and other browsers.

Below is a video of the script running in the desktop version of our browser. We've had to slow it down significantly for you to be able to see what's going on - the test normally takes a few hundred milliseconds.

Through scripts like these, we can automatically test many of the things our millions of users do every day. If we break anything and a test fails, our scripts will instantly notify us so that we can fix it.

But testing these things on our x86 test builds is not enough. We ship on hundreds of different devices every year and need to run the same tests on many different platforms to make sure everything is still working after porting.

When using the scope protocol, it doesn't really matter if you're talking to an Opera instance locally or remotely; it was built for working on any device. Here's the exact same script running on a mobile phone:

Shortly after we started working on this tool, we figured that this might not just be useful for us testing our browser engine, but for Web developers testing their own Web applications, too. Our new tools are still in a pre-alpha stage, but as they mature over the coming months, we would like to make them available to all of you as well.

There are several different browser drivers out there, and we would like to support the most popular ones. The script above was using the Watir API. The following script is doing the same thing through Webdriver, which will be used in the next version of Selenium:

public class OperaDriverExample  {
    public static void main(String[] args) {
        WebDriver driver = new OperaDriver();
        driver.get("http://www.google.com");
        WebElement element = driver.findElement(By.name("q"));
        element.sendKeys("Wikipedia");
        element.submit();
        WebElement wikipediaLink = driver.findElement(By.linkText("Wikipedia"));
        wikipediaLink.click();
        System.out.println("Page title is: " + driver.getTitle());
    }
}

New in Opera Presto 2.2: TLS 1.2 Support

, , , ...

One of the new, but less obvious, features in Opera Presto 2.2 and Opera 10 is support for version 1.2 of the Transport Layer Security (TLS) protocol, the protocol formerly known as SSL.

TLS 1.2 was released as RFC 5246 last August, replacing TLS 1.1 (RFC 4346).

What is new in TLS 1.2?

This version of the protocol has several new features:

  • The way calculation of encryption keys is performed is made more dynamic, and new ciphersuites (set of encryption methods used by a connection) can define their own method, rather than having only the default one. This was necessary because some suites, such as a russian one, could not be used with the default method.
  • The default digest method is now SHA-256, offering stronger security.
  • Several new cipher suites (using existing encryption methods) also use SHA-256.
  • It has better ways to negotiate what signature algorithms the client supports.


Using SHA-256 as the digest method means we are using a more secure method for all the important calculations, and it removes TLS's dependency on MD5. While MD5 is used in a fashion that should reduce the impact of, if not eliminate, the problems the MD5 method is now encountering, the fact that the method is crumbling is, at best, problematic for TLS 1.1 and TLS 1.0.

Additionally, the document now includes the TLS extensions specification. This means that developers no longer need two documents to get all details about the formats used for these.

The document also added an implementor's checklist, making it easier for developers to catch mistakes early. This was added in part due to Opera's findings about the lack of interoperability between many clients and servers, often due to server-side implementation errors.

There are currently few, if any, production servers using TLS 1.2, which is to be expected for a new protocol version, but there are a couple of test servers available.

What is new in Opera relating to TLS?

Adapting Opera's TLS stack to support TLS 1.2 required some significant changes, mostly caused by the new flexibility in the key calculation.

The TLS feature testing, which determines the highest version of TLS supported by the server, was also slightly modified, and it will now always require TLS Extensions for TLS 1.1 and higher. We will also, in future upgrades, assume that any server supporting TLS 1.1 or higher will not panic if the client offers a protocol version newer than it supports, and will, in the future, test TLS 1.0, TLS 1.0+extenstion, TLS 1.1
(w/extenstion) and then the highest TLS version we support. A few years down the road we may also remove this cumbersome method, and offer our highest version in the first connection.

These changes resulted in a redesign with so many deep changes that the dormant support for SSL v2 was removed completely from the source code. Although the binary formats of TLS 1.2 and SSL v2 are incompatible, it is possible for them to co-exist, but the cost of making sure the inactive code actually worked would be too high. SSL v2 has been disabled by default in Opera since v8.0, and the actual functionality was disabled completely in 9.5. It would just not be economical to make sure this protocol version still works, along with the associated internal structure changes, when we have no intention of reactivating the code again. Instead, it was much easier to just "tear out" the code.

Testing

If you want to test TLS 1.2, Michael D'Errico, who's developing his own TLS toolkit, has graciously agreed to let you test against his server at https://www.mikestoolbox.net/. This server is using two private Root Certificates, <1> and <2> which you may want to import into your test configuration (it may be necessary to reload after a negotiation error once if you don't install it). When importing the certificates, after saving them to disk, you must remember to click "View" to go to the details dialog, and uncheck the "Warn about" checkbox, before completing the installation. When connecting to Michael's server you should get a page that includes these two lines:


TLS version: 1.2
Cipher suite: TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 (006B)



Mike was quite helpful while we were debugging our implementation and helped clear up several mistakes. We also use his server in our automatic regression tests, and we thank him for the assistance.

First Root Certificate for Mikes Toolbox
Second Root Certificate for Mikes Toolbox (needed in 10.0)

Carakan

, ,

Over the past few months, a small team of developers and testers have been working on implementing a new ECMAScript/JavaScript engine for Opera. When Opera's current ECMAScript engine, called Futhark, was first released in a public version, it was the fastest engine on the market. That engine was developed to minimize code footprint and memory usage, rather than to achieve maximum execution speed. This has traditionally been a correct trade-off on many of the platforms Opera runs on. The Web is a changing environment however, and tomorrow's advanced web applications will require faster ECMAScript execution, so we have now taken on the challenge to once again develop the fastest ECMAScript engine on the market.

The name Carakan, like the names of Opera's previous ECMAScript engines, Futhark, Linear A and Linear B, is the name of a writing system, or "script".

We have focused our efforts to improve upon our previous engine in three main areas:

Register-based bytecode

The last couple of generations of Opera's ECMAScript engine have used a stack-based bytecode instruction set. This type of instruction set is based around a stack of values, where most instructions "pop" input operands from the value stack, process them, and "push" the result back onto the value stack. Some instructions simply push values onto the value stack, and others rearrange the values on the stack. This gives compact bytecode programs and is easy to generate bytecode for.

In the new engine, we've instead opted for a register-based bytecode instruction set. In a register-based machine, instead of a dynamically sized stack of values, there's a fixed size block of them, called "registers". Instead of only looking at the values at the top of the stack, each instruction can access any register. Since there is no need to copy values to and from the top of the stack to work on them, fewer instructions need to be executed, and less data needs to be copied.

Native code generation

Although our new engine's bytecode instruction set permits the implementation of a significantly faster bytecode execution engine, there is still significant overhead involved in executing simple ECMAScript code, such as loops performing integer arithmetics, in a bytecode interpreter. To get rid of this overhead we are implementing compilation of whole or parts of ECMAScript programs and functions into native code.

This native code compilation is based on static type analysis (with an internal type system that is richer than ECMAScript's ordinary one) to eliminte unnecessary type-checks, speculative specialization (with regards to statically indeterminate types) where appropriate, and a relatively ambitious register allocator that allows generation of compact native code with as few unnecessary inter-register moves and memory accesses as possible.

On ECMAScript code that is particularly well-suited for native code conversion, our generated native code looks more or less like assembly code someone could have written by hand, trying to keep everything in registers.

The register allocator is designed to be architecture independent, and so is the code generation "frontend" where most of the complicated decisions are made. We have initially implemented a backend for 32- and 64-bit x86, but some preliminary work has already started to generate native code for other CPU architectures, such as ARM.

In addition to generating native code from regular ECMAScript code, we also generate native code that performs the matching of simple regular expressions. This improves performance a lot when searching for matches of simple regular expressions in long strings. For sufficiently long strings, this actually makes searching for a substring using a regular expression faster than the same search using String.prototype.indexOf. For shorter strings, the speed is limited by the overhead of compiling the regular expression.

For more complex regular expressions, native code generation becomes more involved, and improves performance less since the regular expression engine is already reasonably fast. The base regular expression engine is a newly developed one, but it's already made its debut in Presto 2.2 (the browser engine used in Opera 10 Alpha). It's fundamentally a typical backtracking regular expression engine, but does some tricks to avoid redundant backtracking, which usually avoids the severe performance issues a backtracking regular expression engine can have on specific regular expressions.

Automatic object classification

Another area of major improvement over our current engine is in the representation of ECMAScript objects. In the new engine, each object is assigned a class that collects various information about the object, such as its prototype and the order and names of some or all of its properties. Class assignment is naturally very dynamic, since ECMAScript is a very dynamic language, but it is organized such that objects with the same prototype and the same set of properties are assigned the same class.

This representation allows compact storage of individual objects, since most of the complicated structures representing the object's properties are stored in the class, where they are shared with all other objects with the same class. In real-world programs with many objects of the same classes, this can save significant amounts of memory. It can be expected that most programs that do create many objects still only have a few different classes of objects.

The shared lookup structures for properties also allow us to share the result of looking up a property between different objects. For two objects with the same class, if the lookup of a property "X" on the first object gave the result Y, we know that the same lookup on the second object will also give the result Y. We use this to cache the result of individual property lookups in ECMAScript programs, which greatly speeds up code that contains many property reads or writes.

Performance

So how fast is Carakan? Using a regular cross-platform switch dispatch mechanism (without any generated native code) Carakan is currently about two and a half times faster at the SunSpider benchmark than the ECMAScript engine in Presto 2.2 (Opera 10 Alpha). Since Opera is ported to many different hardware architectures, this cross-platform improvement is on its own very important.

The native code generation in Carakan is not yet ready for full-scale testing, but the few individual benchmark tests that it is already compatible with runs between 5 and 50 times faster, so it is looking promising so far.

Vega - Opera's vector graphics library

, , , ...

In my previous post here at Core concerns I wrote a bit about hardware acceleration of Opera's vector graphics library. In this post I will go into some more details about our vector graphics library.

The history of Vega

Vega was created shortly after we started working on SVG support. When we added SVG support in Opera we needed a vector graphics library. We looked into what was available to use and met our requirements (fast, low memory usage and works on platforms ranging from phones to TVs and desktop computers). We did not find and good match for our needs, so we decided to write our own.

Shortly after we created Vega we added <canvas> support, which also uses Vega.

The most recent addition to Vega is the ability to use a hardware accelerated back-end. The back-ends we are using at the moment are OpenGL and Direct3D.

HTML rendering

In the core version we are currently developing, Presto 2.3, we have made it possible to use Vega for all rendering in Opera. This means that we can replace the platform specific code for rendering with Vega. In the future it might be mandatory to use Vega for rendering, but in Presto 2.3 it is still possible to use the old rendering back-ends.

There are three reasons for doing this. The first reason is that the new CSS3 background and borders standard is much easier to implement using a vector graphics library. Presto 2.3 adds partial support for CSS3 backgrounds and borders, but only when using Vega for rendering.

The second reason is to support hardware acceleration of our vector graphics. In order to be able to render SVG and <canvas> in hardware we must also be able to directly draw the rendered vector graphics to the screen since reading back the rendered image from the graphics card is usually slower than rendering in software.

The final reason is that it enables us to easily add advanced graphical effects to our UI and to web pages.

Hardware requirements

The hardware back-end of Vega will unfortunately not work on all graphics cards. The good news is that we detect at runtime if your graphics card is supported or not and fallback to the software back-end of Vega if the graphics card is not supported. This means that everything will work regardless of your graphics cards capabilities.

The first requirement of you graphics card is that it has fast stencil buffers. If you are on a desktop computer that will not be a problem, but on some mobile phones that will be a problem. The reason for this requirement is that we use the stencil buffer for rendering some complex shapes instead of tessellating them and render triangles.

Since some web standards (for example opacity, SVG and <canvas>) require us to render to an off-screen buffer which is composited onto the screen we also require some kind of render to texture to be able to use Vega hardware back-end. This means a DirectX 9 compatible graphics card, or support for the framebuffer object (FBO) extension in OpenGL. It would be possible to do the same thing with pbuffers in OpenGL, but we need to do many render target switches and with pbuffers that is too slow.

The final requirement is pixel shaders 2.0, or fragment shaders 2.0 as it is called in OpenGL. We also require GLSL support on OpenGL. The shaders are required for filters. Filters is a part of SVG which performs an operation such as blur or color transforms on an image. Filters are also used in <canvas> and to support text shadows and box shadows in HTML.

For a PC user these requirements are met by any DirectX 9 compatible graphics card. So with the correct drivers you should be able to use the hardware back-end of Vega if you have a DirectX 9 compatible graphics card.

Update 2009-02-05:

I was not very clear about the multiple back-ends of Vega. If the graphics card is not capable of running the hardware back-end of Vega the software back-end will be used as a fallback and all features will still work. No features depends on hardware acceleration. All of them, including CSS3 backgrounds and borders, will work in the software back-end of Vega which does not depend on hardware accelerated graphics.

Presto 2.1.1 Web standards support

, ,

Thanks to Frank Palinkas, a technical writer here at Opera Software, Web standards support in Presto 2.1.1 is now documented: Web specifications supported in Opera Presto 2.1.1. Presto 2.1.1 corresponds to Opera 9.6 for the Desktop. We hope this is of use to you!

Presto in the the Opera User-Agent string

, , , ...

As previously explained, Opera has a common foundation on every platform and release Opera ships on called the core, which consists of all the platform-independent bits and pieces that make the browser, such as the layout engine or ECMAScript engine.

The Opera Core, called Presto, is released internally at Opera at a schedule independent of any product releases, including Opera on desktop, Opera Mobile, Mini or Opera for devices. Normally, core makes three to four releases every year.

In the past, a developer could not directly determine which core version of Opera shipped with a particular release of Opera, but this changed with Opera 9.5 on desktop, where the User-Agent string changed.

In the past, a typical Opera User-Agent string would look like this:

Opera/8.54 (Windows NT 6.0; U; nl)

Starting with the previous release of Presto, the Opera core, we started identifying the version of Opera core in the User-Agent string:

Opera/9.62 (X11; Linux i686; U; en) Presto/2.1.1

The Presto components of the User-Agent string are on the format Presto/[Major version].[Minor version].[Maintenance version].

What to expect?

When developing against Opera, you can generally expect features to have the same level of support and issues, regardless of on which device. For instance, you can expect SVG, ECMAScript, CSS or DOM across all Opera releases shipping with a certain Presto version to behave the same.

This does not, however, mean that you should expect that all features from any given core release are available. Through a set of tweaks, a given shipment of an Opera product might disable or enable a certain feature. A good example of this is the web fonts feature for Presto 2.2.0 - it may be disabled for certain platforms, due to constraints on these platforms, such as low bandwith or low memory.

As for the maintenance versions: They are usually released a relatively short time after the minor version, and contain bug fixes that have surfaced since the release. In general, these versions will not affect any APIs or compatibility.

If you want to play with the latest and greatest Opera core, Opera 10 alpha 1 is shipping with the brand new Presto 2.2.0 release - an overview of the new features are to be found at dev.opera.com. A more detailed changelog can be found from our desktop team's announcment.

Graphics demos

My name is Tim Johansson, I am a core technology developer at Opera. I work in the core graphics team which is responsible for all the rendering (of web pages, SVG and <canvas>) and image decoding in Opera.

In the middle of December Opera had an engineering seminar outside Oslo in Norway. At the seminar there were a few presentations. I gave a presentation about graphics in Opera and showed a few demos. In this post I will write about two of the demos, and link to videos of them.

Opera Flashlight

One of the first assignments I had at Opera was to work on a technology for platform independent graphics, which is now used in some of Operas products including the Opera SDK.
When working on it I quickly realized that this technology would make it easy to upload Opera to a texture in a 3d application.
Since I had been working on a 3d engine for fun in my spare time I spent a late evening integrating Opera into my 3d engine. The place I thought sounded most fun to add it was as the projective texture used for the flashlight in the 3d engine.

This video demonstrates the result of that late night hack more than 3 years ago.

Hardware acceleration

One of the things I have been working on lately is hardware acceleration of the vector graphics library used for SVG and <canvas> in Opera using 3d hardware (through OpenGL and Direct3D).

In order to get the most performance from rendering SVG/<canvas> in hardware it is good to avoid reading the rendered image back from the graphics card to system memory since that is a slow operation.
This can be solved by rendering all of Opera (including UI and web pages) in hardware. Rendering Opera in hardware also makes it possible to add visual effects without any additional CPU cost.

This video shows a demo of Opera running fully hardware accelerated. The demo build used in this video is an interal Opera core technology reference build with hardware acceleration enabled. Hardware acceleration is still experimental and is not in any released or soon to be released products.