CSC/ECE 517 Fall 2015/M1506-Refactor-GLES2-Implementation

From Expertiza_Wiki
Jump to navigation Jump to search

' Refactor GLES2 Student Project with SERVO & RUST '

Servo is a prototype web browser engine written in the RUST language.Servo uses a variety of back-end implementations for drawing graphics depending on the operating system.One of such back-end is only compatible with Android right now, and we want to extend and refactor that back-end to enable on all Linux systems..

Introduction

Servo

ServoServo is an open source prototype web browser layout engine being developed by Mozilla, and it is written in Rust language. The main idea is to create a highly parallel environment, in which different components can be handled by fine grained, isolated tasks. The different components can be rendering, HTML parsing, etc.

Rust

Rust is an open source systems programming language developed by Mozilla. Servo is written in Rust. The main purpose behind it's design is to be thread safe and concurrent. The emphasis is also on speed, safety and control of memory layout.

Project Description

  • The project requirement initially stated that we build and Compile servo. Following are the steps for this:

Servo is built with Cargo, the Rust package manager. Mozilla's Mach tools are used to orchestrate the build and other tasks.

   git clone https://github.com/servo/servo
   cd servo
   ./mach build --dev
   ./mach run tests/html/about-mozilla.html
  • The next requirement was to build the Rust-layers independently of Servo. For this, we
  • Next, we had to over-ride cargo to use our local copy of Rust-layers, so we had to add a cargo override to it. For this, we created a .cargo folder in our home directory(same place that servo and Rust-layers reside), and added a config file to that folder. The content of that config file is a path to our local Rust-layers.
   paths = [path/to/rust_layers]
  • Next, we had to add a new command line argument in Servo, which would allow selecting the graphics background (GL or ES2). For this, we made the following changes:

- We added a command line option which lets the user enter the option -E or --es2 if the user wants to set ES2 as the graphic back end option. GL is set by default, hence if the user doesn't give any argument, Gl is selected as the graphic back end option. Example is as below

   ./mach run [url] -E
  • Next, we had to add a flag in Rust-layers. This change was made in the file Rust/src/rendergl.rs in the RenderContext::new function. For this, we did the following change:

- We defined an enum GraphicOption which defined two options GL and ES2 and then based on the boolean value from the servo opts.rs, we set a variable with the respective enum value GL or ES2.

  • Then, we had to use the new command line option to pass the selected graphics back-end option to the Rust-layers context which we created in the previous step. For this we made changes to the compositor.rs in Compositing folder which is how Servo interacts with the Rust layers. The command line option is passed through the initialize_compositing function.
  • Now we need to change the platform implementation in surface.rs and provide a generic implementation to dynamically select between GL & ES2.

Requirement Analysis

Earlier, only OpenGL implementation was supported for Android targets and we would be extending the ES2 implementation to support it for Linux targets. As a part of the final project, we accomplished the following steps:

  • Enable selection of the render api working from the command line, so the user can pick whether to use GL or ES2
  • Modify the necessary files so that the current version of GL or ES2 are returned whenever either of them are selected
  • Make the EGL libs available on Linux for rust-layers to compile rust-egl on Linux build.
  • Separate out the EGLImageNativeSurface implementation from Android and move it to EGL
  • Enable use of EGL or GLX for Linux

Implementation

Servo

 Servo/components/utils/opts.rs

added the new command line option to enable user to select the option of GL or ES2 as the rendering backend. The options of GL or ES2 are stored as an enum called RenderApi , such that running the Servo with option --render-api=chosen_option sets the corresponding Api.

 Servo/ports/glutin/window.rs

gl_version() function is modified in a way that based on what is selected as the RenderApi option by the user, the corresponding version of the Api is set. To talk more in detail, if the render api is set to GL, it returns the current value (GL 2.1) & if set to ES2, it returns OpenGlEs 2.0.

native_display() for linux target is also modified to call the specific NativeDisplay constructor based on the RenderApi option chosen by the user. Hence for the GL case, the existing NativeDisplay::new constructor is called, but if ES2 is selected, NativeDisplay::from_es2() is called, which has been introduced by us in an attempt to support ES2 for the linux platform as well.

Rust-Layers

 rust-layers/cargo.toml

In order to make the egl libraries available to the Linux too, the cargo.toml is edited which defines the different dependencies that various platforms has. Before, the dependency on rust-egl was added only for android targets but now these dependencies have been added for Linux targets as well.

 rust-layers/src/platform/egl/surface.rs

In order to support EGL for both linux and android targets, we moved the implementation of EGLImageNativeSurface from the android specific surface.rs and introduced a new folder egl which contains its own surface.rs and implements a generic EGLImageNativeSurface

 rust-layers/src/lib.rs

Since egl needs to be supported for linux too now, the extern crate egl call needs to be linked on Linux as well now. Hence in the cfg flag, the target_os="linux" is added in addition to android.

In the pub mod platform { }, introduced a new pub mod egl {} section to pull in the new egl/surface.rs implemented for both android and linux targets.

 rust-layers/src/platform/linux/surface.rs

In order to ensure that ES2 is supported for linux targets too, we need to enable the use of EGL & GLX in the linux specific surface.rs A new enum is created for NativeDisplay which has two different values of EGLDisplayInfo & GlxDisplayInfo and respectively, two constructors are created . The existing NativeDisplay::new constructor is modified to return NativeDisplay::Glx(info) for the GL version , and the NativeDisplay::from_es2() constructor introduced earlier can return NativeDisplay::::Egl(egl_info) for the ES2 version.

Useful libraries

waffle-gl/waffle: A C library for selecting an OpenGL API and window system at runtime.

Design Pattern

The aim is to use ES2 implementation of rust layers for both android and Linux. So we need to use a design pattern that will allow us to extend the current implementation to support Linux targets too and give the user the flexibility to choose between the two implementations for rendering the backend.

We propose to use Decorator pattern. The decorator pattern gives the user the ability to choose between the implementations that are desired, and attach the corresponding implementation to the target dynamically at runtime.


References

1. https://doc.rust-lang.org/stable/book/
2. https://en.wikipedia.org/wiki/Rust_(programming_language)
3. https://en.wikipedia.org/wiki/Servo_(layout_engine)
4. https://github.com/servo/servo/wiki/Refactor-GLES2-student-project
5. http://doc.crates.io/guide.html#overriding-dependencies
6. http://rustbyexample.com/
7. http://javarevisited.blogspot.com/2014/11/strategy-design-pattern-in-java-using-Enum-Example.html