mirror of
https://github.com/servo/servo.git
synced 2025-06-06 16:45:39 +00:00
This is not a complete implementation yet: It doesn't clear the contents of the renderbuffer on creation. However, Gecko's plan to only clear renderbuffers when the first FBO using them is the simplest.
111 lines
3.8 KiB
Rust
111 lines
3.8 KiB
Rust
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
|
|
|
// https://www.khronos.org/registry/webgl/specs/latest/1.0/webgl.idl
|
|
use canvas_traits::CanvasMsg;
|
|
use dom::bindings::codegen::Bindings::WebGLRenderbufferBinding;
|
|
use dom::bindings::codegen::Bindings::WebGLRenderingContextBinding::WebGLRenderingContextConstants as constants;
|
|
use dom::bindings::js::Root;
|
|
use dom::bindings::reflector::reflect_dom_object;
|
|
use dom::globalscope::GlobalScope;
|
|
use dom::webglobject::WebGLObject;
|
|
use ipc_channel::ipc::{self, IpcSender};
|
|
use std::cell::Cell;
|
|
use webrender_traits::{WebGLCommand, WebGLRenderbufferId, WebGLResult, WebGLError};
|
|
|
|
#[dom_struct]
|
|
pub struct WebGLRenderbuffer {
|
|
webgl_object: WebGLObject,
|
|
id: WebGLRenderbufferId,
|
|
ever_bound: Cell<bool>,
|
|
is_deleted: Cell<bool>,
|
|
internal_format: Cell<Option<u32>>,
|
|
#[ignore_heap_size_of = "Defined in ipc-channel"]
|
|
renderer: IpcSender<CanvasMsg>,
|
|
}
|
|
|
|
impl WebGLRenderbuffer {
|
|
fn new_inherited(renderer: IpcSender<CanvasMsg>,
|
|
id: WebGLRenderbufferId)
|
|
-> WebGLRenderbuffer {
|
|
WebGLRenderbuffer {
|
|
webgl_object: WebGLObject::new_inherited(),
|
|
id: id,
|
|
ever_bound: Cell::new(false),
|
|
is_deleted: Cell::new(false),
|
|
renderer: renderer,
|
|
internal_format: Cell::new(None),
|
|
}
|
|
}
|
|
|
|
pub fn maybe_new(global: &GlobalScope, renderer: IpcSender<CanvasMsg>)
|
|
-> Option<Root<WebGLRenderbuffer>> {
|
|
let (sender, receiver) = ipc::channel().unwrap();
|
|
renderer.send(CanvasMsg::WebGL(WebGLCommand::CreateRenderbuffer(sender))).unwrap();
|
|
|
|
let result = receiver.recv().unwrap();
|
|
result.map(|renderbuffer_id| WebGLRenderbuffer::new(global, renderer, renderbuffer_id))
|
|
}
|
|
|
|
pub fn new(global: &GlobalScope,
|
|
renderer: IpcSender<CanvasMsg>,
|
|
id: WebGLRenderbufferId)
|
|
-> Root<WebGLRenderbuffer> {
|
|
reflect_dom_object(box WebGLRenderbuffer::new_inherited(renderer, id),
|
|
global,
|
|
WebGLRenderbufferBinding::Wrap)
|
|
}
|
|
}
|
|
|
|
|
|
impl WebGLRenderbuffer {
|
|
pub fn id(&self) -> WebGLRenderbufferId {
|
|
self.id
|
|
}
|
|
|
|
pub fn bind(&self, target: u32) {
|
|
self.ever_bound.set(true);
|
|
let msg = CanvasMsg::WebGL(WebGLCommand::BindRenderbuffer(target, Some(self.id)));
|
|
self.renderer.send(msg).unwrap();
|
|
}
|
|
|
|
pub fn delete(&self) {
|
|
if !self.is_deleted.get() {
|
|
self.is_deleted.set(true);
|
|
let _ = self.renderer.send(CanvasMsg::WebGL(WebGLCommand::DeleteRenderbuffer(self.id)));
|
|
}
|
|
}
|
|
|
|
pub fn is_deleted(&self) -> bool {
|
|
self.is_deleted.get()
|
|
}
|
|
|
|
pub fn ever_bound(&self) -> bool {
|
|
self.ever_bound.get()
|
|
}
|
|
|
|
pub fn storage(&self, internal_format: u32, width: i32, height: i32) -> WebGLResult<()> {
|
|
// Validate the internal_format, and save it for completeness
|
|
// validation.
|
|
match internal_format {
|
|
constants::RGBA4 |
|
|
constants::DEPTH_STENCIL |
|
|
constants::DEPTH_COMPONENT16 |
|
|
constants::STENCIL_INDEX8 =>
|
|
self.internal_format.set(Some(internal_format)),
|
|
|
|
_ => return Err(WebGLError::InvalidEnum),
|
|
};
|
|
|
|
// FIXME: Check that w/h are < MAX_RENDERBUFFER_SIZE
|
|
|
|
// FIXME: Invalidate completeness after the call
|
|
|
|
let msg = CanvasMsg::WebGL(WebGLCommand::RenderbufferStorage(constants::RENDERBUFFER,
|
|
internal_format, width, height));
|
|
self.renderer.send(msg).unwrap();
|
|
|
|
Ok(())
|
|
}
|
|
}
|