Skip to content
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

Merged
merged 1 commit into from
Feb 26, 2017
Merged

Conversation

emilio
Copy link
Member

@emilio emilio commented Feb 13, 2017

@emilio
Copy link
Member Author

emilio commented Feb 13, 2017

Blocked on servo/gleam#106

@kvark
Copy link
Member

kvark commented Feb 14, 2017

So gl::Gl is a trait, and thus the new code works with the trait object, right?
Is there any benefit of using the unsafe raw pointers versus just Rc/Weak?

@emilio
Copy link
Member Author

emilio commented Feb 14, 2017

@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.

@emilio
Copy link
Member Author

emilio commented Feb 14, 2017

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 Gl a static table and add convenience methods to it instead? I did something similar for clang-sys for bindgen (see the functions struct in KyleMayes/clang-sys#45). It'd be a matter of adding all the glue that would be inlined and would just look like:

#[inline]
fn flush(&self) {
    (self.functions.expect("glFlush not loaded"))()
}

@sotaroikeda
Copy link
Contributor

Couldn't we make Gl a static table and add convenience methods to it instead?

It might be better for performance. But I want to handle it as another issue, since we want to enable Graphics branch soon.

@kvark
Copy link
Member

kvark commented Feb 16, 2017

@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.

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.

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.

@emilio
Copy link
Member Author

emilio commented Feb 16, 2017 via email

@kvark
Copy link
Member

kvark commented Feb 16, 2017

@emilio thanks!
I've just published gleam-0.3.0, so let's have this PR updated.

@sotaroikeda
Copy link
Contributor

@emilio, thank you!

@emilio emilio force-pushed the gleamup branch 2 times, most recently from b29c2a9 to 4d2f294 Compare February 16, 2017 10:36
@emilio
Copy link
Member Author

emilio commented Feb 16, 2017

Done, feel free to take a look, let me know when do you want to merge this.

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 _);
Copy link
Member

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

Copy link
Member Author

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.

Copy link
Member

@kvark kvark Feb 17, 2017

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.

Copy link
Member Author

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.

Copy link
Member Author

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) {
Copy link
Member

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?

Copy link
Member Author

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.

Copy link
Member

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) {
Copy link
Member

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,
Copy link
Member

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.

Copy link
Member Author

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.

Copy link
Member

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.

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 _);
Copy link
Member

@kvark kvark Feb 17, 2017

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.

@sotaroikeda
Copy link
Contributor

What is a current status?

@emilio
Copy link
Member Author

emilio commented Feb 25, 2017

Whoops, totally forgot about this, there it is.

Copy link
Member

@kvark kvark left a 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.

@@ -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!(
Copy link
Member

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

// 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
Copy link
Member

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,
Copy link
Member

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;
Copy link
Member

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

@emilio emilio force-pushed the gleamup branch 2 times, most recently from c885e6a to 23d0368 Compare February 26, 2017 12:50
@emilio
Copy link
Member Author

emilio commented Feb 26, 2017

Thanks for the review @kvark! Landed and published as 0.7.0

@emilio emilio merged commit 26096cb into master Feb 26, 2017
@emilio emilio deleted the gleamup branch February 26, 2017 12:51
@sotaroikeda
Copy link
Contributor

Thank you!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants