-
Notifications
You must be signed in to change notification settings - Fork 84
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Update gleam, and use a dynamic GL function table. #81
Conversation
Blocked on servo/gleam#106 |
So |
@kvark That's right. It avoids some refcount churn. In this case it seemed easy enough to do it, but I'd be fine also with Rc. It may make sense to share gl function tables across threads though, that's something that Rc would prevent, but we don't use that at all I think so it may be ok. |
Oh, and I hadn't been following the gleam PR btw, the generic proposal looks ok to me. It's kind of sad to use dynamic dispatch, but I was taking that for granted already. Couldn't we make #[inline]
fn flush(&self) {
(self.functions.expect("glFlush not loaded"))()
} |
It might be better for performance. But I want to handle it as another issue, since we want to enable Graphics branch soon. |
The extra refcount work would only apply to resource creation/deletion, right? I wouldn't be too concerned and preferred the code clarity (and less unsafety) instead.
Could you explain why we'd need that? It sounds like a hack.
Possible, although I'd rather want to see static dispatch here in the first place. Considering the deadlines, this will have to wait. |
On Wed, Feb 15, 2017 at 09:43:07PM -0800, Dzmitry Malyshau wrote:
@emilio
> It avoids some refcount churn.
The extra refcount work would only apply to resource creation/deletion, right? I wouldn't be too concerned and preferred the code clarity (and less unsafety) instead.
Right, and that's a fair point.
> It may make sense to share gl function tables across threads though
Could you explain why we'd need that? It sounds like a hack.
Didn't have a specific use case in mind, but yeah, I guess context
creation time is not a big deal.
I could imagine us sharing the same function hooks or something, but
yeah, as I said I don't expect it to be super-useful.
> Couldn't we make Gl a static table and add convenience methods to it instead?
Possible, although I'd rather want to see static dispatch here in the
first place. Considering the deadlines, this will have to wait.
That's fair, as I said I don't love dynamic dispatch, but we can
probably live with it.
|
@emilio thanks! |
@emilio, thank you! |
b29c2a9
to
4d2f294
Compare
Done, feel free to take a look, let me know when do you want to merge this. |
src/gl_context.rs
Outdated
let native_context = try!(Native::create_shared_with_dispatcher(shared_with, dispatcher)); | ||
// XXX how to handle GLES instantiation? | ||
let gl_ = gl::GlFns::load_with(|s| GLContext::<Native>::get_proc_address(s) as *const _); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
it appears that we need to sort this out before merging
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh, right, I just grabbed that from the original Sotaro's patch. I guess the idea here would be doing so per-backend (that is, the egl back-end would load gles functions, etc). That being said, in which case would it make a difference? I guess we can provide only the GLES-like interface given this is primarily for WebGL and we create compat contexts, alternatively, I can make it generic, but that cries to avoid the virtual dispatch then.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
alternatively, I can make it generic, but that cries to avoid the virtual dispatch then
Well, doing static dispatch is still on the table, just for a different time frame - servo/gleam#107
So maybe it's not the worst idea to be ready for that ;)
Really though, If this newly created context is shared with some existing one, we should use Gl function loader if that existing one is GL, and GLES correspondingly. If it's an entirely new one (shared_with.is_none() == true
), this is probably where we want the gleam::GlType
flag to be passed in for run-time context type selection.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That sounds reasonable, though probably for WebGL
it's enough with loading unconditionally just the gles functions.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
tl;dr; I'll prepare a patch with that.
match *self { | ||
ColorAttachment::Renderbuffer(id) => gl::delete_renderbuffers(&[id]), | ||
ColorAttachment::Texture(tex_id) => gl::delete_textures(&[tex_id]), | ||
fn destroy(self, gl: &gl::Gl) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why do we need to destroy
now instead of drop
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Didn't want to grow them by an extra pointer given we only create one per draw buffer, but I can definitely do it I guess.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, you are passing gl
in, I see. And the function is not public, so there is no concern about calling it twice.
Let's leave it with destroy
then :)
match *self { | ||
ColorAttachment::Renderbuffer(id) => gl::delete_renderbuffers(&[id]), | ||
ColorAttachment::Texture(tex_id) => gl::delete_textures(&[tex_id]), | ||
fn destroy(self, gl: &gl::Gl) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, you are passing gl
in, I see. And the function is not public, so there is no concern about calling it twice.
Let's leave it with destroy
then :)
-> Result<GLContext<Native>, &'static str> { | ||
Self::new_shared_with_dispatcher(size, attributes, color_attachment_type, shared_with, None) | ||
-> Result<Self, &'static str> { | ||
Self::new_shared_with_dispatcher(size, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm a bit confused about this. create_shared_with_dispatcher
calls new_shared_with_dispatcher
, and new_shared_with_dispatcher
calls create_shared_with_dispatcher
, both seem unconditional.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It... doesn't? create_shared_with_dispatcher
calls the relevant method on the underlying platform-dependent context.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I see now, you are correct.
src/gl_context.rs
Outdated
let native_context = try!(Native::create_shared_with_dispatcher(shared_with, dispatcher)); | ||
// XXX how to handle GLES instantiation? | ||
let gl_ = gl::GlFns::load_with(|s| GLContext::<Native>::get_proc_address(s) as *const _); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
alternatively, I can make it generic, but that cries to avoid the virtual dispatch then
Well, doing static dispatch is still on the table, just for a different time frame - servo/gleam#107
So maybe it's not the worst idea to be ready for that ;)
Really though, If this newly created context is shared with some existing one, we should use Gl function loader if that existing one is GL, and GLES correspondingly. If it's an entirely new one (shared_with.is_none() == true
), this is probably where we want the gleam::GlType
flag to be passed in for run-time context type selection.
What is a current status? |
Whoops, totally forgot about this, there it is. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks @emilio , looks good!
I got a few minor things, which are fine to address separately, if you wish.
src/draw_buffer.rs
Outdated
@@ -113,8 +116,9 @@ impl DrawBuffer { | |||
|
|||
try!(draw_buffer.init(context, color_attachment_type)); | |||
|
|||
debug_assert!(gl::check_frame_buffer_status(gl::FRAMEBUFFER) == gl::FRAMEBUFFER_COMPLETE); | |||
debug_assert!(gl::get_error() == gl::NO_ERROR); | |||
debug_assert!( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
debug_assert_eq!
would be much better here since it would print the actual error/status
src/draw_buffer.rs
Outdated
// ColorAttachment | ||
gl::delete_renderbuffers(&[self.stencil_renderbuffer, self.depth_renderbuffer]); | ||
fn gl(&self) -> &gl::Gl { | ||
// See the comment on top the GLContext field to see why our usage of |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
perhaps, there is no longer a point in this comment? There is no unsafe
here, so safety is assumed by default
-> Result<GLContext<Native>, &'static str> { | ||
Self::new_shared_with_dispatcher(size, attributes, color_attachment_type, shared_with, None) | ||
-> Result<Self, &'static str> { | ||
Self::new_shared_with_dispatcher(size, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I see now, you are correct.
src/tests.rs
Outdated
#[cfg(not(target_os="android"))] | ||
static LOAD_GL: Once = ONCE_INIT; | ||
#[cfg(target_os = "android")] | ||
const GL_API_TYPE: gl::GlType = gl::GlType::Gles; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
could use default()
, which is already implemented on GlType
c885e6a
to
23d0368
Compare
Thanks for the review @kvark! Landed and published as 0.7.0 |
Thank you! |
cc @sotaroikeda