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

Split out GLContext from GLRasterizationContext #60

Merged
merged 1 commit into from
Jul 28, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
96 changes: 96 additions & 0 deletions src/gl_context.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
/*
* Copyright 2015 The Servo Project Developers
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/

use skia;

use euclid::size::Size2D;
use gleam::gl;
use std::ptr;
use std::sync::Arc;

#[cfg(target_os="macos")]
pub use gl_context_cgl::GLPlatformContext;
#[cfg(target_os="macos")]
pub use gl_context_cgl::PlatformDisplayData;

#[cfg(target_os="linux")]
pub use gl_context_glx::GLPlatformContext;
#[cfg(target_os="linux")]
pub use gl_context_glx::PlatformDisplayData;

#[cfg(target_os="android")]
pub use gl_context_android::GLPlatformContext;
#[cfg(target_os="android")]
pub use gl_context_android::PlatformDisplayData;

pub struct GLContext {
pub platform_context: GLPlatformContext,
pub gr_context: skia::SkiaGrContextRef,
pub gl_interface: skia::SkiaGrGLInterfaceRef,
pub size: Size2D<i32>,
}

impl Drop for GLContext {
fn drop(&mut self) {
self.platform_context.make_current();

unsafe {
skia::SkiaGrContextRelease(self.gr_context);
skia::SkiaGrGLInterfaceRelease(self.gl_interface);
}
}
}

impl GLContext {
pub fn new(platform_display_data: PlatformDisplayData,
size: Size2D<i32>)
-> Option<Arc<GLContext>> {
let platform_context = GLPlatformContext::new(platform_display_data, size);
let platform_context = match platform_context {
Some(platform_context) => platform_context,
None => return None,
};

// The Skia GL interface needs to be created while the context is active, so we
// do that immediately after setting the context as the current one.
platform_context.make_current();

unsafe {
let gl_interface = skia::SkiaGrGLCreateNativeInterface();
if gl_interface == ptr::null_mut() {
platform_context.drop_current_context();
return None;
}

let gr_context = skia::SkiaGrContextCreate(gl_interface);
if gr_context == ptr::null_mut() {
platform_context.drop_current_context();
return None;
}

Some(Arc::new(GLContext {
platform_context: platform_context,
gr_context: gr_context,
gl_interface: gl_interface,
size: size,
}))
}
}

pub fn flush(&self) {
self.make_current();
gl::flush();
}

pub fn make_current(&self) {
self.platform_context.make_current();
}

pub fn drop_current_context(&self) {
self.platform_context.drop_current_context();
}
}
93 changes: 93 additions & 0 deletions src/gl_context_android.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
/*
* Copyright 2015 The Servo Project Developers
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/

use euclid::size::Size2D;
use egl::egl;
use std::ptr;

pub struct PlatformDisplayData {
pub display: egl::EGLDisplay,
}

pub struct GLPlatformContext {
pub display: egl::EGLDisplay,
pub egl_context: egl::EGLContext,
egl_surface: egl::EGLSurface,
}

impl Drop for GLPlatformContext {
fn drop(&mut self) {
self.drop_current_context();
egl::DestroyContext(self.display, self.egl_context);
egl::DestroySurface(self.display, self.egl_surface);
}
}

impl GLPlatformContext {
pub fn new(platform_display_data: PlatformDisplayData,
size: Size2D<i32>)
-> Option<GLPlatformContext> {
let config_attributes = [
egl::EGL_SURFACE_TYPE as i32, egl::EGL_PBUFFER_BIT as i32,
egl::EGL_RENDERABLE_TYPE as i32, egl::EGL_OPENGL_ES2_BIT as i32,
egl::EGL_RED_SIZE as i32, 8,
egl::EGL_BLUE_SIZE as i32, 8,
egl::EGL_ALPHA_SIZE as i32, 8,
egl::EGL_NONE as i32,
];

let display = platform_display_data.display;
let mut surface_config = ptr::null_mut();
let mut number_of_configs = 0;
egl::ChooseConfig(display,
config_attributes.as_ptr(),
&mut surface_config, 1, &mut number_of_configs);
if number_of_configs == 0 {
return None;
}

let context_attributes = [
egl::EGL_CONTEXT_CLIENT_VERSION as i32, 2,
egl::EGL_NONE as i32
];
let egl_context = egl::CreateContext(display,
surface_config,
egl::EGL_NO_CONTEXT as egl::EGLContext,
context_attributes.as_ptr());
if egl_context == egl::EGL_NO_CONTEXT as egl::EGLContext {
return None;
}

let mut surface_attributes = [
egl::EGL_WIDTH as i32, size.width,
egl::EGL_HEIGHT as i32, size.height,
egl::EGL_NONE as i32,
];
let egl_surface = egl::CreatePbufferSurface(display,
surface_config,
&mut surface_attributes[0]);
if egl_surface == egl::EGL_NO_SURFACE as egl::EGLSurface {
egl::DestroyContext(display, egl_context);
return None;
}


Some(GLPlatformContext {
display: display,
egl_context: egl_context,
egl_surface: egl_surface,
})
}

pub fn drop_current_context(&self) {
egl::MakeCurrent(self.display, ptr::null_mut(), ptr::null_mut(), ptr::null_mut());
}

pub fn make_current(&self) {
egl::MakeCurrent(self.display, self.egl_surface, self.egl_surface, self.egl_context);
}
}
62 changes: 62 additions & 0 deletions src/gl_context_cgl.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
/*
* Copyright 2015 The Servo Project Developers
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/

use euclid::size::Size2D;
use cgl;
use gleam::gl;
use std::ptr;

pub struct PlatformDisplayData {
pub pixel_format: cgl::CGLPixelFormatObj,
}

pub struct GLPlatformContext {
pub cgl_context: cgl::CGLContextObj,
}

impl Drop for GLPlatformContext {
fn drop(&mut self) {
unsafe {
cgl::CGLDestroyContext(self.cgl_context);
}
}
}

impl GLPlatformContext {
pub fn new(platform_display_data: PlatformDisplayData,
_: Size2D<i32>)
-> Option<GLPlatformContext> {
unsafe {
let mut cgl_context = ptr::null_mut();
let _ = cgl::CGLCreateContext(platform_display_data.pixel_format,
ptr::null_mut(),
&mut cgl_context);
if ptr::null_mut() == cgl_context {
return None;
}

cgl::CGLSetCurrentContext(cgl_context);
gl::enable(gl::TEXTURE_RECTANGLE_ARB);

Some(GLPlatformContext {
cgl_context: cgl_context,
})
}
}

pub fn drop_current_context(&self) {
unsafe {
cgl::CGLSetCurrentContext(ptr::null_mut());
}
}

pub fn make_current(&self) {
unsafe {
cgl::CGLSetCurrentContext(self.cgl_context);
}
}
}
98 changes: 98 additions & 0 deletions src/gl_context_glx.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
/*
* Copyright 2015 The Servo Project Developers
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/

use euclid::size::Size2D;
use glx;
use std::ptr;
use x11::xlib;

pub struct PlatformDisplayData {
pub display: *mut xlib::Display,
pub visual_info: *mut xlib::XVisualInfo,
}

pub struct GLPlatformContext {
pub display: *mut xlib::Display,
glx_context: xlib::XID,
pub glx_pixmap: xlib::XID,
pub pixmap: xlib::XID,
}

impl Drop for GLPlatformContext {
fn drop(&mut self) {
// We need this thread to grab the GLX context before we can make
// OpenGL calls. But glXMakeCurrent() will flush the old context,
// which might have been uninitialized. Dropping the current context
// first solves this problem somehow.
self.drop_current_context();
self.make_current();

unsafe {
let glx_display = self.display as *mut glx::types::Display;
glx::MakeCurrent(glx_display, 0 /* None */, ptr::null_mut());
glx::DestroyContext(glx_display, self.glx_context as glx::types::GLXContext);
glx::DestroyGLXPixmap(glx_display, self.glx_pixmap);
xlib::XFreePixmap(self.display, self.pixmap);
}
}
}

impl GLPlatformContext {
pub fn new(platform_display_data: PlatformDisplayData,
size: Size2D<i32>)
-> Option<GLPlatformContext> {
unsafe {
let display = platform_display_data.display;
let visual_info = platform_display_data.visual_info;
let glx_display = display as *mut glx::types::Display;
let glx_visual_info = visual_info as *mut glx::types::XVisualInfo;

let root_window = xlib::XRootWindow(display, xlib::XDefaultScreen(display));
let pixmap = xlib::XCreatePixmap(display,
root_window,
size.width as u32,
size.height as u32,
(*visual_info).depth as u32);
let glx_pixmap = glx::CreateGLXPixmap(glx_display,
glx_visual_info,
pixmap);

let glx_context = glx::CreateContext(glx_display,
glx_visual_info,
ptr::null_mut(),
1);

if glx_context == ptr::null() {
glx::DestroyGLXPixmap(glx_display, glx_pixmap);
return None;
}

Some(GLPlatformContext {
display: display,
glx_context: glx_context as xlib::XID,
pixmap: pixmap,
glx_pixmap: glx_pixmap as xlib::XID,
})
}
}

pub fn drop_current_context(&self) {
unsafe {
glx::MakeCurrent(self.display as *mut glx::types::Display,
0 /* None */,
ptr::null_mut());
}
}

pub fn make_current(&self) {
unsafe {
glx::MakeCurrent(self.display as *mut glx::types::Display,
self.glx_pixmap,
self.glx_context as glx::types::GLXContext);
}
}
}
Loading