Skip to content

Commit

Permalink
Auto merge of #21335 - servo:webgl, r=emilio
Browse files Browse the repository at this point in the history
Merge code from Draw* and Draw*Instanced methods

<!-- Reviewable:start -->
This change is [<img src="https://reviewable.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/servo/servo/21335)
<!-- Reviewable:end -->
  • Loading branch information
bors-servo committed Aug 3, 2018
2 parents c5aaae7 + 04c81c5 commit 025ba5c
Show file tree
Hide file tree
Showing 3 changed files with 30 additions and 128 deletions.
10 changes: 6 additions & 4 deletions components/canvas/webgl_thread.rs
Expand Up @@ -701,10 +701,6 @@ impl WebGLImpl {
ctx.gl().front_face(mode),
WebGLCommand::DisableVertexAttribArray(attrib_id) =>
ctx.gl().disable_vertex_attrib_array(attrib_id),
WebGLCommand::DrawArrays(mode, first, count) =>
ctx.gl().draw_arrays(mode, first, count),
WebGLCommand::DrawElements(mode, count, type_, offset) =>
ctx.gl().draw_elements(mode, count, type_, offset as u32),
WebGLCommand::EnableVertexAttribArray(attrib_id) =>
ctx.gl().enable_vertex_attrib_array(attrib_id),
WebGLCommand::Hint(name, val) =>
Expand Down Expand Up @@ -957,9 +953,15 @@ impl WebGLImpl {
WebGLCommand::UseProgram(program_id) => {
ctx.gl().use_program(program_id.map_or(0, |p| p.get()))
}
WebGLCommand::DrawArrays { mode, first, count } => {
ctx.gl().draw_arrays(mode, first, count)
}
WebGLCommand::DrawArraysInstanced { mode, first, count, primcount } => {
ctx.gl().draw_arrays_instanced(mode, first, count, primcount)
}
WebGLCommand::DrawElements { mode, count, type_, offset } => {
ctx.gl().draw_elements(mode, count, type_, offset)
}
WebGLCommand::DrawElementsInstanced { mode, count, type_, offset, primcount } => {
ctx.gl().draw_elements_instanced(mode, count, type_, offset, primcount)
}
Expand Down
4 changes: 2 additions & 2 deletions components/canvas_traits/webgl.rs
Expand Up @@ -201,8 +201,6 @@ pub enum WebGLCommand {
BindRenderbuffer(u32, Option<WebGLRenderbufferId>),
BindTexture(u32, Option<WebGLTextureId>),
DisableVertexAttribArray(u32),
DrawArrays(u32, i32, i32),
DrawElements(u32, i32, u32, i64),
EnableVertexAttribArray(u32),
FramebufferRenderbuffer(u32, u32, u32, Option<WebGLRenderbufferId>),
FramebufferTexture2D(u32, u32, u32, Option<WebGLTextureId>, i32),
Expand Down Expand Up @@ -278,7 +276,9 @@ pub enum WebGLCommand {
GetTexParameterInt(u32, TexParameterInt, WebGLSender<i32>),
TexParameteri(u32, u32, i32),
TexParameterf(u32, u32, f32),
DrawArrays { mode: u32, first: i32, count: i32 },
DrawArraysInstanced { mode: u32, first: i32, count: i32, primcount: i32 },
DrawElements { mode: u32, count: i32, type_: u32, offset: u32 },
DrawElementsInstanced { mode: u32, count: i32, type_: u32, offset: u32, primcount: i32 },
VertexAttribDivisor { index: u32, divisor: u32 },
GetUniformBool(WebGLProgramId, i32, WebGLSender<bool>),
Expand Down
144 changes: 22 additions & 122 deletions components/script/dom/webglrenderingcontext.rs
Expand Up @@ -1180,9 +1180,15 @@ impl WebGLRenderingContext {
return;
}

self.send_command(
WebGLCommand::DrawArraysInstanced { mode, first, count, primcount },
);
if count == 0 || primcount == 0 {
return;
}

self.send_command(if primcount == 1 {
WebGLCommand::DrawArrays { mode, first, count }
} else {
WebGLCommand::DrawArraysInstanced { mode, first, count, primcount }
});
self.mark_as_dirty();
}

Expand Down Expand Up @@ -1210,6 +1216,7 @@ impl WebGLRenderingContext {
let type_size = match type_ {
constants::UNSIGNED_BYTE => 1,
constants::UNSIGNED_SHORT => 2,
constants::UNSIGNED_INT if self.extension_manager.is_element_index_uint_enabled() => 4,
_ => return self.webgl_error(InvalidEnum),
};
if offset % type_size != 0 {
Expand All @@ -1224,17 +1231,12 @@ impl WebGLRenderingContext {

if count > 0 && primcount > 0 {
if let Some(array_buffer) = self.current_vao().element_array_buffer().get() {
// WebGL Spec: check buffer overflows, must be a valid multiple of the size.
// This operation cannot overflow in u64 and we know all those values are nonnegative.
let val = offset as u64 + (count as u64 * type_size as u64);
if val > array_buffer.capacity() as u64 {
return self.webgl_error(InvalidOperation);
}
} else {
// From the WebGL spec
//
// a non-null WebGLBuffer must be bound to the ELEMENT_ARRAY_BUFFER binding point
// or an INVALID_OPERATION error will be generated.
//
return self.webgl_error(InvalidOperation);
}
}
Expand All @@ -1250,12 +1252,15 @@ impl WebGLRenderingContext {
return;
}

self.send_command(WebGLCommand::DrawElementsInstanced {
mode,
count,
type_,
offset: offset as u32,
primcount,
if count == 0 || primcount == 0 {
return;
}

let offset = offset as u32;
self.send_command(if primcount == 1 {
WebGLCommand::DrawElements { mode, count, type_, offset }
} else {
WebGLCommand::DrawElementsInstanced { mode, count, type_, offset, primcount }
});
self.mark_as_dirty();
}
Expand Down Expand Up @@ -2411,117 +2416,12 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext {

// https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.11
fn DrawArrays(&self, mode: u32, first: i32, count: i32) {
match mode {
constants::POINTS | constants::LINE_STRIP |
constants::LINE_LOOP | constants::LINES |
constants::TRIANGLE_STRIP | constants::TRIANGLE_FAN |
constants::TRIANGLES => {},
_ => {
return self.webgl_error(InvalidEnum);
}
}
if first < 0 || count < 0 {
return self.webgl_error(InvalidValue);
}

let current_program = handle_potential_webgl_error!(
self,
self.current_program.get().ok_or(InvalidOperation),
return
);

let required_len = if count > 0 {
handle_potential_webgl_error!(
self,
first.checked_add(count).map(|len| len as u32).ok_or(InvalidOperation),
return
)
} else {
0
};

handle_potential_webgl_error!(
self,
self.current_vao().validate_for_draw(required_len, 1, &current_program.active_attribs()),
return
);

if !self.validate_framebuffer_complete() {
return;
}

self.send_command(WebGLCommand::DrawArrays(mode, first, count));
self.mark_as_dirty();
self.draw_arrays_instanced(mode, first, count, 1);
}

// https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.11
fn DrawElements(&self, mode: u32, count: i32, type_: u32, offset: i64) {
match mode {
constants::POINTS | constants::LINE_STRIP |
constants::LINE_LOOP | constants::LINES |
constants::TRIANGLE_STRIP | constants::TRIANGLE_FAN |
constants::TRIANGLES => {},
_ => return self.webgl_error(InvalidEnum),
}

// From the GLES 2.0.25 spec, page 21:
//
// "type must be one of UNSIGNED_BYTE or UNSIGNED_SHORT"
let type_size = match type_ {
constants::UNSIGNED_BYTE => 1,
constants::UNSIGNED_SHORT => 2,
constants::UNSIGNED_INT if self.extension_manager.is_element_index_uint_enabled() => 4,
_ => return self.webgl_error(InvalidEnum),
};

if offset % type_size != 0 {
return self.webgl_error(InvalidOperation);
}

if count < 0 {
return self.webgl_error(InvalidValue);
}

if offset < 0 {
return self.webgl_error(InvalidValue);
}

let current_program = handle_potential_webgl_error!(
self,
self.current_program.get().ok_or(InvalidOperation),
return
);

if count > 0 {
if let Some(array_buffer) = self.current_vao().element_array_buffer().get() {
// WebGL Spec: check buffer overflows, must be a valid multiple of the size.
let val = offset as u64 + (count as u64 * type_size as u64);
if val > array_buffer.capacity() as u64 {
return self.webgl_error(InvalidOperation);
}
} else {
// From the WebGL spec
//
// a non-null WebGLBuffer must be bound to the ELEMENT_ARRAY_BUFFER binding point
// or an INVALID_OPERATION error will be generated.
//
return self.webgl_error(InvalidOperation);
}
}

// TODO(nox): Pass the correct number of vertices required.
handle_potential_webgl_error!(
self,
self.current_vao().validate_for_draw(0, 1, &current_program.active_attribs()),
return
);

if !self.validate_framebuffer_complete() {
return;
}

self.send_command(WebGLCommand::DrawElements(mode, count, type_, offset));
self.mark_as_dirty();
self.draw_elements_instanced(mode, count, type_, offset, 1);
}

// https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.10
Expand Down

0 comments on commit 025ba5c

Please sign in to comment.