1use gdk::GLContext;
7use glib::translate::*;
8
9use crate::{ffi, prelude::*, subclass::prelude::*, GLArea};
10
11#[allow(clippy::upper_case_acronyms)]
12pub trait GLAreaImpl: WidgetImpl + ObjectSubclass<Type: IsA<GLArea>> {
13 fn create_context(&self) -> Option<GLContext> {
14 self.parent_create_context()
15 }
16
17 fn render(&self, context: &GLContext) -> glib::Propagation {
18 self.parent_render(context)
19 }
20
21 fn resize(&self, width: i32, height: i32) {
22 self.parent_resize(width, height)
23 }
24}
25
26#[allow(clippy::upper_case_acronyms)]
27pub trait GLAreaImplExt: GLAreaImpl {
28 fn parent_create_context(&self) -> Option<GLContext> {
29 unsafe {
30 let data = Self::type_data();
31 let parent_class = data.as_ref().parent_class() as *mut ffi::GtkGLAreaClass;
32 if let Some(f) = (*parent_class).create_context {
33 return from_glib_none(f(self.obj().unsafe_cast_ref::<GLArea>().to_glib_none().0));
34 };
35 None
36 }
37 }
38
39 fn parent_render(&self, context: &GLContext) -> glib::Propagation {
40 unsafe {
41 let data = Self::type_data();
42 let parent_class = data.as_ref().parent_class() as *mut ffi::GtkGLAreaClass;
43 let f = (*parent_class)
44 .render
45 .expect("No parent class impl for \"render\"");
46 from_glib(f(
47 self.obj().unsafe_cast_ref::<GLArea>().to_glib_none().0,
48 context.to_glib_none().0,
49 ))
50 }
51 }
52
53 fn parent_resize(&self, width: i32, height: i32) {
54 unsafe {
55 let data = Self::type_data();
56 let parent_class = data.as_ref().parent_class() as *mut ffi::GtkGLAreaClass;
57 if let Some(f) = (*parent_class).resize {
58 f(
59 self.obj().unsafe_cast_ref::<GLArea>().to_glib_none().0,
60 width,
61 height,
62 )
63 }
64 }
65 }
66}
67
68impl<T: GLAreaImpl> GLAreaImplExt for T {}
69
70unsafe impl<T: GLAreaImpl> IsSubclassable<T> for GLArea {
71 fn class_init(class: &mut glib::Class<Self>) {
72 Self::parent_class_init::<T>(class);
73
74 let klass = class.as_mut();
75 klass.create_context = Some(gl_area_create_context::<T>);
76 klass.render = Some(gl_area_render::<T>);
77 klass.resize = Some(gl_area_resize::<T>);
78 }
79}
80
81unsafe extern "C" fn gl_area_create_context<T: GLAreaImpl>(
82 ptr: *mut ffi::GtkGLArea,
83) -> *mut gdk::ffi::GdkGLContext {
84 let instance = &*(ptr as *mut T::Instance);
85 let imp = instance.imp();
86
87 imp.create_context().into_glib_ptr()
88}
89
90unsafe extern "C" fn gl_area_render<T: GLAreaImpl>(
91 ptr: *mut ffi::GtkGLArea,
92 context: *mut gdk::ffi::GdkGLContext,
93) -> glib::ffi::gboolean {
94 let instance = &*(ptr as *mut T::Instance);
95 let imp = instance.imp();
96
97 imp.render(&from_glib_borrow(context)).into_glib()
98}
99
100unsafe extern "C" fn gl_area_resize<T: GLAreaImpl>(
101 ptr: *mut ffi::GtkGLArea,
102 width: i32,
103 height: i32,
104) {
105 let instance = &*(ptr as *mut T::Instance);
106 let imp = instance.imp();
107
108 imp.resize(width, height)
109}