Skip to content
This repository was archived by the owner on Jun 8, 2020. It is now read-only.

Commit 6eddb1b

Browse files
author
bors-servo
committed
Auto merge of #60 - mrobinson:gl-context, r=pcwalton
Split out GLContext from GLRasterizationContext This will allow Servo to preserve the same GLContext and GrContext between rasterization targets, thus vastly improving the performance of OpenGL rasterization. <!-- Reviewable:start --> [<img src="https://reviewable.io/review_button.png" height=40 alt="Review on Reviewable"/>](https://reviewable.io/reviews/servo/skia/60) <!-- Reviewable:end -->
2 parents b945e11 + bdaf858 commit 6eddb1b

9 files changed

+453
-230
lines changed

src/gl_context.rs

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
/*
2+
* Copyright 2015 The Servo Project Developers
3+
*
4+
* Use of this source code is governed by a BSD-style license that can be
5+
* found in the LICENSE file.
6+
*/
7+
8+
use skia;
9+
10+
use euclid::size::Size2D;
11+
use gleam::gl;
12+
use std::ptr;
13+
use std::sync::Arc;
14+
15+
#[cfg(target_os="macos")]
16+
pub use gl_context_cgl::GLPlatformContext;
17+
#[cfg(target_os="macos")]
18+
pub use gl_context_cgl::PlatformDisplayData;
19+
20+
#[cfg(target_os="linux")]
21+
pub use gl_context_glx::GLPlatformContext;
22+
#[cfg(target_os="linux")]
23+
pub use gl_context_glx::PlatformDisplayData;
24+
25+
#[cfg(target_os="android")]
26+
pub use gl_context_android::GLPlatformContext;
27+
#[cfg(target_os="android")]
28+
pub use gl_context_android::PlatformDisplayData;
29+
30+
pub struct GLContext {
31+
pub platform_context: GLPlatformContext,
32+
pub gr_context: skia::SkiaGrContextRef,
33+
pub gl_interface: skia::SkiaGrGLInterfaceRef,
34+
pub size: Size2D<i32>,
35+
}
36+
37+
impl Drop for GLContext {
38+
fn drop(&mut self) {
39+
self.platform_context.make_current();
40+
41+
unsafe {
42+
skia::SkiaGrContextRelease(self.gr_context);
43+
skia::SkiaGrGLInterfaceRelease(self.gl_interface);
44+
}
45+
}
46+
}
47+
48+
impl GLContext {
49+
pub fn new(platform_display_data: PlatformDisplayData,
50+
size: Size2D<i32>)
51+
-> Option<Arc<GLContext>> {
52+
let platform_context = GLPlatformContext::new(platform_display_data, size);
53+
let platform_context = match platform_context {
54+
Some(platform_context) => platform_context,
55+
None => return None,
56+
};
57+
58+
// The Skia GL interface needs to be created while the context is active, so we
59+
// do that immediately after setting the context as the current one.
60+
platform_context.make_current();
61+
62+
unsafe {
63+
let gl_interface = skia::SkiaGrGLCreateNativeInterface();
64+
if gl_interface == ptr::null_mut() {
65+
platform_context.drop_current_context();
66+
return None;
67+
}
68+
69+
let gr_context = skia::SkiaGrContextCreate(gl_interface);
70+
if gr_context == ptr::null_mut() {
71+
platform_context.drop_current_context();
72+
return None;
73+
}
74+
75+
Some(Arc::new(GLContext {
76+
platform_context: platform_context,
77+
gr_context: gr_context,
78+
gl_interface: gl_interface,
79+
size: size,
80+
}))
81+
}
82+
}
83+
84+
pub fn flush(&self) {
85+
self.make_current();
86+
gl::flush();
87+
}
88+
89+
pub fn make_current(&self) {
90+
self.platform_context.make_current();
91+
}
92+
93+
pub fn drop_current_context(&self) {
94+
self.platform_context.drop_current_context();
95+
}
96+
}

src/gl_context_android.rs

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
/*
2+
* Copyright 2015 The Servo Project Developers
3+
*
4+
* Use of this source code is governed by a BSD-style license that can be
5+
* found in the LICENSE file.
6+
*/
7+
8+
use euclid::size::Size2D;
9+
use egl::egl;
10+
use std::ptr;
11+
12+
pub struct PlatformDisplayData {
13+
pub display: egl::EGLDisplay,
14+
}
15+
16+
pub struct GLPlatformContext {
17+
pub display: egl::EGLDisplay,
18+
pub egl_context: egl::EGLContext,
19+
egl_surface: egl::EGLSurface,
20+
}
21+
22+
impl Drop for GLPlatformContext {
23+
fn drop(&mut self) {
24+
self.drop_current_context();
25+
egl::DestroyContext(self.display, self.egl_context);
26+
egl::DestroySurface(self.display, self.egl_surface);
27+
}
28+
}
29+
30+
impl GLPlatformContext {
31+
pub fn new(platform_display_data: PlatformDisplayData,
32+
size: Size2D<i32>)
33+
-> Option<GLPlatformContext> {
34+
let config_attributes = [
35+
egl::EGL_SURFACE_TYPE as i32, egl::EGL_PBUFFER_BIT as i32,
36+
egl::EGL_RENDERABLE_TYPE as i32, egl::EGL_OPENGL_ES2_BIT as i32,
37+
egl::EGL_RED_SIZE as i32, 8,
38+
egl::EGL_BLUE_SIZE as i32, 8,
39+
egl::EGL_ALPHA_SIZE as i32, 8,
40+
egl::EGL_NONE as i32,
41+
];
42+
43+
let display = platform_display_data.display;
44+
let mut surface_config = ptr::null_mut();
45+
let mut number_of_configs = 0;
46+
egl::ChooseConfig(display,
47+
config_attributes.as_ptr(),
48+
&mut surface_config, 1, &mut number_of_configs);
49+
if number_of_configs == 0 {
50+
return None;
51+
}
52+
53+
let context_attributes = [
54+
egl::EGL_CONTEXT_CLIENT_VERSION as i32, 2,
55+
egl::EGL_NONE as i32
56+
];
57+
let egl_context = egl::CreateContext(display,
58+
surface_config,
59+
egl::EGL_NO_CONTEXT as egl::EGLContext,
60+
context_attributes.as_ptr());
61+
if egl_context == egl::EGL_NO_CONTEXT as egl::EGLContext {
62+
return None;
63+
}
64+
65+
let mut surface_attributes = [
66+
egl::EGL_WIDTH as i32, size.width,
67+
egl::EGL_HEIGHT as i32, size.height,
68+
egl::EGL_NONE as i32,
69+
];
70+
let egl_surface = egl::CreatePbufferSurface(display,
71+
surface_config,
72+
&mut surface_attributes[0]);
73+
if egl_surface == egl::EGL_NO_SURFACE as egl::EGLSurface {
74+
egl::DestroyContext(display, egl_context);
75+
return None;
76+
}
77+
78+
79+
Some(GLPlatformContext {
80+
display: display,
81+
egl_context: egl_context,
82+
egl_surface: egl_surface,
83+
})
84+
}
85+
86+
pub fn drop_current_context(&self) {
87+
egl::MakeCurrent(self.display, ptr::null_mut(), ptr::null_mut(), ptr::null_mut());
88+
}
89+
90+
pub fn make_current(&self) {
91+
egl::MakeCurrent(self.display, self.egl_surface, self.egl_surface, self.egl_context);
92+
}
93+
}

src/gl_context_cgl.rs

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
/*
2+
* Copyright 2015 The Servo Project Developers
3+
*
4+
* Use of this source code is governed by a BSD-style license that can be
5+
* found in the LICENSE file.
6+
*/
7+
8+
use euclid::size::Size2D;
9+
use cgl;
10+
use gleam::gl;
11+
use std::ptr;
12+
13+
pub struct PlatformDisplayData {
14+
pub pixel_format: cgl::CGLPixelFormatObj,
15+
}
16+
17+
pub struct GLPlatformContext {
18+
pub cgl_context: cgl::CGLContextObj,
19+
}
20+
21+
impl Drop for GLPlatformContext {
22+
fn drop(&mut self) {
23+
unsafe {
24+
cgl::CGLDestroyContext(self.cgl_context);
25+
}
26+
}
27+
}
28+
29+
impl GLPlatformContext {
30+
pub fn new(platform_display_data: PlatformDisplayData,
31+
_: Size2D<i32>)
32+
-> Option<GLPlatformContext> {
33+
unsafe {
34+
let mut cgl_context = ptr::null_mut();
35+
let _ = cgl::CGLCreateContext(platform_display_data.pixel_format,
36+
ptr::null_mut(),
37+
&mut cgl_context);
38+
if ptr::null_mut() == cgl_context {
39+
return None;
40+
}
41+
42+
cgl::CGLSetCurrentContext(cgl_context);
43+
gl::enable(gl::TEXTURE_RECTANGLE_ARB);
44+
45+
Some(GLPlatformContext {
46+
cgl_context: cgl_context,
47+
})
48+
}
49+
}
50+
51+
pub fn drop_current_context(&self) {
52+
unsafe {
53+
cgl::CGLSetCurrentContext(ptr::null_mut());
54+
}
55+
}
56+
57+
pub fn make_current(&self) {
58+
unsafe {
59+
cgl::CGLSetCurrentContext(self.cgl_context);
60+
}
61+
}
62+
}

src/gl_context_glx.rs

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
/*
2+
* Copyright 2015 The Servo Project Developers
3+
*
4+
* Use of this source code is governed by a BSD-style license that can be
5+
* found in the LICENSE file.
6+
*/
7+
8+
use euclid::size::Size2D;
9+
use glx;
10+
use std::ptr;
11+
use x11::xlib;
12+
13+
pub struct PlatformDisplayData {
14+
pub display: *mut xlib::Display,
15+
pub visual_info: *mut xlib::XVisualInfo,
16+
}
17+
18+
pub struct GLPlatformContext {
19+
pub display: *mut xlib::Display,
20+
glx_context: xlib::XID,
21+
pub glx_pixmap: xlib::XID,
22+
pub pixmap: xlib::XID,
23+
}
24+
25+
impl Drop for GLPlatformContext {
26+
fn drop(&mut self) {
27+
// We need this thread to grab the GLX context before we can make
28+
// OpenGL calls. But glXMakeCurrent() will flush the old context,
29+
// which might have been uninitialized. Dropping the current context
30+
// first solves this problem somehow.
31+
self.drop_current_context();
32+
self.make_current();
33+
34+
unsafe {
35+
let glx_display = self.display as *mut glx::types::Display;
36+
glx::MakeCurrent(glx_display, 0 /* None */, ptr::null_mut());
37+
glx::DestroyContext(glx_display, self.glx_context as glx::types::GLXContext);
38+
glx::DestroyGLXPixmap(glx_display, self.glx_pixmap);
39+
xlib::XFreePixmap(self.display, self.pixmap);
40+
}
41+
}
42+
}
43+
44+
impl GLPlatformContext {
45+
pub fn new(platform_display_data: PlatformDisplayData,
46+
size: Size2D<i32>)
47+
-> Option<GLPlatformContext> {
48+
unsafe {
49+
let display = platform_display_data.display;
50+
let visual_info = platform_display_data.visual_info;
51+
let glx_display = display as *mut glx::types::Display;
52+
let glx_visual_info = visual_info as *mut glx::types::XVisualInfo;
53+
54+
let root_window = xlib::XRootWindow(display, xlib::XDefaultScreen(display));
55+
let pixmap = xlib::XCreatePixmap(display,
56+
root_window,
57+
size.width as u32,
58+
size.height as u32,
59+
(*visual_info).depth as u32);
60+
let glx_pixmap = glx::CreateGLXPixmap(glx_display,
61+
glx_visual_info,
62+
pixmap);
63+
64+
let glx_context = glx::CreateContext(glx_display,
65+
glx_visual_info,
66+
ptr::null_mut(),
67+
1);
68+
69+
if glx_context == ptr::null() {
70+
glx::DestroyGLXPixmap(glx_display, glx_pixmap);
71+
return None;
72+
}
73+
74+
Some(GLPlatformContext {
75+
display: display,
76+
glx_context: glx_context as xlib::XID,
77+
pixmap: pixmap,
78+
glx_pixmap: glx_pixmap as xlib::XID,
79+
})
80+
}
81+
}
82+
83+
pub fn drop_current_context(&self) {
84+
unsafe {
85+
glx::MakeCurrent(self.display as *mut glx::types::Display,
86+
0 /* None */,
87+
ptr::null_mut());
88+
}
89+
}
90+
91+
pub fn make_current(&self) {
92+
unsafe {
93+
glx::MakeCurrent(self.display as *mut glx::types::Display,
94+
self.glx_pixmap,
95+
self.glx_context as glx::types::GLXContext);
96+
}
97+
}
98+
}

0 commit comments

Comments
 (0)