1use {
2 self::super::gl_sys,
3 gl_sys::LibGl,
4 crate::{
5 cx::{Cx, OsType},
6 draw_list::DrawListId,
7 draw_shader::{CxDrawShaderMapping, DrawShaderTextureInput},
8 event::{Event, TextureHandleReadyEvent},
9 makepad_live_id::*,
10 makepad_math::{DVec2, Vec4},
11 makepad_shader_compiler::generate_glsl,
12 pass::{PassClearColor, PassClearDepth, PassId},
13 texture::{CxTexture, Texture, TextureFormat, TexturePixel, TextureUpdated}
14 },
15 std::{
16 ffi::{c_char, CStr}, fs::{remove_file, File}, io::prelude::*, mem, ptr
17 }
18};
19
20impl Cx {
21
22 pub (crate) fn render_view(
23 &mut self,
24 pass_id: PassId,
25 draw_list_id: DrawListId,
26 zbias: &mut f32,
27 zbias_step: f32,
28 ) {
29 let mut to_dispatch = Vec::new();
30 let draw_items_len = self.draw_lists[draw_list_id].draw_items.len();
33
34 #[cfg(use_gles_3)]
35 {
36 let draw_list = &mut self.draw_lists[draw_list_id];
37 draw_list.os.draw_list_uniforms.update_uniform_buffer(self.os.gl(), draw_list.draw_list_uniforms.as_slice());
38 }
39
40 for draw_item_id in 0..draw_items_len {
41 if let Some(sub_list_id) = self.draw_lists[draw_list_id].draw_items[draw_item_id].kind.sub_list() {
42 self.render_view(
43 pass_id,
44 sub_list_id,
45 zbias,
46 zbias_step,
47 );
48 }
49 else {
50 let gl = self.os.gl();
51
52 let draw_list = &mut self.draw_lists[draw_list_id];
53 let draw_item = &mut draw_list.draw_items[draw_item_id];
54
55 let draw_call = if let Some(draw_call) = draw_item.kind.draw_call_mut() {
56 draw_call
57 }else {
58 continue;
59 };
60
61 let sh = &self.draw_shaders.shaders[draw_call.draw_shader.draw_shader_id];
62 if sh.os_shader_id.is_none() { continue;
64 }
65 if sh.mapping.uses_time {
66 self.demo_time_repaint = true;
67 }
68 let shp = &mut self.draw_shaders.os_shaders[sh.os_shader_id.unwrap()];
69
70 let shader_variant = self.passes[pass_id].os.shader_variant;
71
72 if shp.gl_shader[shader_variant].is_none(){
73 shp.gl_shader[shader_variant] = Some(GlShader::new(
74 self.os.gl(),
75 &shp.vertex[shader_variant],
76 &shp.pixel[shader_variant],
77 &sh.mapping,
78 &self.os_type,
79 ));
80 }
81 let shgl = shp.gl_shader[shader_variant].as_ref().unwrap();
82
83 if draw_call.instance_dirty || draw_item.os.inst_vb.gl_buffer.is_none(){
84 draw_call.instance_dirty = false;
85 draw_item.os.inst_vb.update_array_buffer(gl,draw_item.instances.as_ref().unwrap());
86 }
87
88 draw_call.draw_call_uniforms.set_zbias(*zbias);
90 *zbias += zbias_step;
91
92 #[cfg(use_gles_3)]
93 draw_item.os.draw_call_uniforms.update_uniform_buffer(gl, draw_call.draw_call_uniforms.as_slice());
94
95 let instances = (draw_item.instances.as_ref().unwrap().len() / sh.mapping.instances.total_slots) as u64;
96
97 if instances == 0 {
98 continue;
99 }
100
101 let geometry_id = if let Some(geometry_id) = draw_call.geometry_id {geometry_id}
102 else {
103 continue;
104 };
105
106 let geometry = &mut self.geometries[geometry_id];
107 if geometry.dirty || geometry.os.vb.gl_buffer.is_none() || geometry.os.ib.gl_buffer.is_none() {
108 geometry.os.vb.update_array_buffer(gl,&geometry.vertices);
109 geometry.os.ib.update_index_buffer(gl,&geometry.indices);
110 geometry.dirty = false;
111 }
112
113 let indices = geometry.indices.len();
114
115 if draw_call.uniforms_dirty {
116 draw_call.uniforms_dirty = false;
117 #[cfg(use_gles_3)]
118 if draw_call.user_uniforms.len() != 0 {
119 draw_item.os.user_uniforms.update_uniform_buffer(gl, &mut draw_call.user_uniforms);
120 }
121 }
122
123 let geometry = &mut self.geometries[geometry_id];
125
126 if draw_item.os.vao.is_none() {
128 draw_item.os.vao = Some(CxOsDrawCallVao {
129 vao: None,
130 shader_id: None,
131 inst_vb: None,
132 geom_vb: None,
133 geom_ib: None,
134 });
135 }
136
137 let vao = draw_item.os.vao.as_mut().unwrap();
138 if vao.inst_vb != draw_item.os.inst_vb.gl_buffer
139 || vao.geom_vb != geometry.os.vb.gl_buffer
140 || vao.geom_ib != geometry.os.ib.gl_buffer
141 || vao.shader_id != Some(draw_call.draw_shader.draw_shader_id) {
142
143 if let Some(vao) = vao.vao.take(){
144 unsafe{(gl.glDeleteVertexArrays)(1, &vao)};
145 }
146
147 vao.vao = Some(unsafe {
148 let mut vao = 0u32;
149 (gl.glGenVertexArrays)(1, &mut vao);
150 vao
151 });
152
153 vao.shader_id = Some(draw_call.draw_shader.draw_shader_id);
154 vao.inst_vb = draw_item.os.inst_vb.gl_buffer;
155 vao.geom_vb = geometry.os.vb.gl_buffer;
156 vao.geom_ib = geometry.os.ib.gl_buffer;
157 unsafe {
158 (gl.glBindVertexArray)(vao.vao.unwrap());
159 (gl.glBindBuffer)(gl_sys::ARRAY_BUFFER, vao.geom_vb.unwrap());
161 for attr in &shgl.geometries {
162 if let Some(loc) = attr.loc{
163 (gl.glVertexAttribPointer)(loc, attr.size, gl_sys::FLOAT, 0, attr.stride, attr.offset as *const () as *const _);
164 (gl.glEnableVertexAttribArray)(loc);
165 }
166 }
167 (gl.glBindBuffer)(gl_sys::ARRAY_BUFFER, vao.inst_vb.unwrap());
168 for attr in &shgl.instances {
169 if let Some(loc) = attr.loc{
170 (gl.glVertexAttribPointer)(loc, attr.size, gl_sys::FLOAT, 0, attr.stride, attr.offset as *const () as *const _);
171 (gl.glEnableVertexAttribArray)(loc);
172 (gl.glVertexAttribDivisor)(loc, 1 as gl_sys::GLuint);
173 }
174 }
175
176 (gl.glBindBuffer)(gl_sys::ELEMENT_ARRAY_BUFFER, vao.geom_ib.unwrap());
178 (gl.glBindVertexArray)(0);
179 (gl.glBindBuffer)(gl_sys::ARRAY_BUFFER, 0);
180 (gl.glBindBuffer)(gl_sys::ELEMENT_ARRAY_BUFFER, 0);
181 }
182 }
183 unsafe {
184 (gl.glUseProgram)(shgl.program);
185 (gl.glBindVertexArray)(draw_item.os.vao.as_ref().unwrap().vao.unwrap());
186 let instances = (draw_item.instances.as_ref().unwrap().len() / sh.mapping.instances.total_slots) as u64;
187 #[cfg(use_gles_3)]{
189 shgl.uniforms.pass_uniforms_binding.bind_buffer(gl, &self.passes[pass_id].os.pass_uniforms);
190 shgl.uniforms.draw_list_uniforms_binding.bind_buffer(gl, &draw_list.os.draw_list_uniforms);
191 shgl.uniforms.draw_call_uniforms_binding.bind_buffer(gl, &draw_item.os.draw_call_uniforms);
192 if draw_call.user_uniforms.len() != 0 {
193 shgl.uniforms.user_uniforms_binding.bind_buffer(gl, &draw_item.os.user_uniforms);
194 }
195 shgl.uniforms.live_uniforms_binding.bind_buffer(gl, &shgl.uniforms.live_uniforms);
196 }
197 #[cfg(not(use_gles_3))]{
198 let pass_uniforms = self.passes[pass_id].pass_uniforms.as_slice();
199 let draw_list_uniforms = draw_list.draw_list_uniforms.as_slice();
200 let draw_call_uniforms = draw_call.draw_call_uniforms.as_slice();
201 GlShader::set_uniform_array(gl, &shgl.uniforms.pass_uniforms, pass_uniforms);
202 GlShader::set_uniform_array(gl, &shgl.uniforms.draw_list_uniforms, draw_list_uniforms);
203 GlShader::set_uniform_array(gl, &shgl.uniforms.draw_call_uniforms, draw_call_uniforms);
204 GlShader::set_uniform_array(gl, &shgl.uniforms.user_uniforms, &draw_call.user_uniforms);
205 }
206
207 #[cfg(target_os="android")]
209 if self.os.in_xr_mode{self.os.openxr.depth_texture_hook(gl, shgl, &sh.mapping)};
210
211 for i in 0..sh.mapping.textures.len() {
212 let texture_id = if let Some(texture) = &draw_call.texture_slots[i] {
213 texture.texture_id()
214 }else {
215 continue;
216 };
217 let cxtexture = &mut self.textures[texture_id];
218
219 if cxtexture.format.is_vec(){
220 cxtexture.update_vec_texture(gl, &self.os_type);
221 } else if cxtexture.format.is_video() {
222 let is_initial_setup = cxtexture.setup_video_texture(gl);
223 if is_initial_setup {
224 let e = Event::TextureHandleReady(
225 TextureHandleReadyEvent {
226 texture_id,
227 handle: cxtexture.os.gl_texture.unwrap()
228 }
229 );
230 to_dispatch.push(e);
231 }
232 }
233 }
234 for i in 0..sh.mapping.textures.len() {
235 let texture_id = if let Some(texture) = &draw_call.texture_slots[i] {
236 texture.texture_id()
237 }else {
238 continue;
239 };
240 let cxtexture = &mut self.textures[texture_id];
241 let gl = self.os.gl();
242 (gl.glActiveTexture)(gl_sys::TEXTURE0 + i as u32);
244 if let Some(texture) = cxtexture.os.gl_texture {
245 match cxtexture.format {
247 TextureFormat::VideoRGB => (gl.glBindTexture)(gl_sys::TEXTURE_EXTERNAL_OES, texture),
248 _ => (gl.glBindTexture)(gl_sys::TEXTURE_2D, texture)
249 }
250 }
251 else {
252 match cxtexture.format {
253 TextureFormat::VideoRGB => (gl.glBindTexture)(gl_sys::TEXTURE_EXTERNAL_OES, 0),
254 _ => (gl.glBindTexture)(gl_sys::TEXTURE_2D, 0)
255 }
256 }
257 if let Some(loc) = shgl.textures[i].loc{
258 (gl.glUniform1i)(loc, i as i32);
259 }
260 }
261
262 (gl.glDrawElementsInstanced)(
263 gl_sys::TRIANGLES,
264 indices as i32,
265 gl_sys::UNSIGNED_INT,
266 ptr::null(),
267 instances as i32
268 );
269 (gl.glBindVertexArray)(0);
270 (gl.glUseProgram)(0);
271 }
272
273 }
274 }
275 for event in to_dispatch.iter() {
276 self.call_event_handler(&event);
277 }
278 }
279
280 pub fn set_default_depth_and_blend_mode(gl: &LibGl) {
281 unsafe {
282 (gl.glEnable)(gl_sys::DEPTH_TEST);
283 (gl.glDepthFunc)(gl_sys::LEQUAL);
284 (gl.glBlendEquationSeparate)(gl_sys::FUNC_ADD, gl_sys::FUNC_ADD);
285 (gl.glBlendFuncSeparate)(gl_sys::ONE, gl_sys::ONE_MINUS_SRC_ALPHA, gl_sys::ONE, gl_sys::ONE_MINUS_SRC_ALPHA);
286 (gl.glEnable)(gl_sys::BLEND);
287 }
288 }
289
290 pub fn setup_render_pass(&mut self, pass_id: PassId,) -> Option<(DVec2,f64)> {
291
292 let dpi_factor = self.passes[pass_id].dpi_factor.unwrap();
293 let pass_rect = self.get_pass_rect(pass_id, dpi_factor).unwrap();
294 let pass = &mut self.passes[pass_id];
295 pass.paint_dirty = false;
296
297 if pass_rect.size.x <0.5 || pass_rect.size.y < 0.5 {
298 return None
299 }
300
301 pass.set_ortho_matrix(pass_rect.pos, pass_rect.size);
302 pass.set_dpi_factor(dpi_factor);
303
304 #[cfg(use_gles_3)]
305 pass.os.pass_uniforms.update_uniform_buffer(self.os.gl(), pass.pass_uniforms.as_slice());
306
307 Some((pass_rect.size, dpi_factor))
308 }
309
310 pub fn draw_pass_to_texture(
311 &mut self,
312 pass_id: PassId,
313 override_pass_texture: Option<&Texture>,
314 ) {
315 let draw_list_id = self.passes[pass_id].main_draw_list_id.unwrap();
316
317 let (pass_size, dpi_factor) = if let Some(pz) = self.setup_render_pass(pass_id) {
318 pz
319 }
320 else {
321 return
322 };
323
324 let mut clear_color = Vec4::default();
325 let mut clear_depth = 1.0;
326 let mut clear_flags = 0;
327 let gl = self.os.gl();
328 if self.passes[pass_id].os.gl_framebuffer.is_none() {
330 unsafe {
331 let mut gl_framebuffer = std::mem::MaybeUninit::uninit();
332 (gl.glGenFramebuffers)(1, gl_framebuffer.as_mut_ptr());
333 self.passes[pass_id].os.gl_framebuffer = Some(gl_framebuffer.assume_init());
334 }
335 }
336
337 unsafe {
339 (gl.glBindFramebuffer)(gl_sys::FRAMEBUFFER, self.passes[pass_id].os.gl_framebuffer.unwrap());
340 }
341
342 let color_textures_from_fb_texture = override_pass_texture.map(|texture| {
343 [crate::pass::CxPassColorTexture {
344 clear_color: PassClearColor::ClearWith(self.passes[pass_id].clear_color),
345 texture: texture.clone(),
346 }]
347 });
348 let color_textures = color_textures_from_fb_texture
349 .as_ref().map_or(&self.passes[pass_id].color_textures[..], |xs| &xs[..]);
350
351 for (index, color_texture) in color_textures.iter().enumerate() {
352 match color_texture.clear_color {
353 PassClearColor::InitWith(_clear_color) => {
354 let cxtexture = &mut self.textures[color_texture.texture.texture_id()];
355 let size = dpi_factor * pass_size;
356 cxtexture.update_render_target(gl, size.x as usize, size.y as usize);
357 if cxtexture.take_initial(){
358 clear_color = _clear_color;
359 clear_flags |= gl_sys::COLOR_BUFFER_BIT;
360 }
361 },
362 PassClearColor::ClearWith(_clear_color) => {
363 let cxtexture = &mut self.textures[color_texture.texture.texture_id()];
364 let size = dpi_factor * pass_size;
365 cxtexture.update_render_target(gl, size.x as usize, size.y as usize);
366 clear_color = _clear_color;
367 clear_flags |= gl_sys::COLOR_BUFFER_BIT;
368 }
369 }
370 if let Some(gl_texture) = self.textures[color_texture.texture.texture_id()].os.gl_texture {
371 unsafe {
372 (gl.glFramebufferTexture2D)(gl_sys::FRAMEBUFFER, gl_sys::COLOR_ATTACHMENT0 + index as u32, gl_sys::TEXTURE_2D, gl_texture, 0);
373 }
374 }
375 }
376
377 if let Some(depth_texture) = &self.passes[pass_id].depth_texture {
379 match self.passes[pass_id].clear_depth {
380 PassClearDepth::InitWith(_clear_depth) => {
381 let cxtexture = &mut self.textures[depth_texture.texture_id()];
382 let size = dpi_factor * pass_size;
383 cxtexture.update_depth_stencil(gl, size.x as usize, size.y as usize);
384 if cxtexture.take_initial(){
385 clear_depth = _clear_depth;
386 clear_flags |= gl_sys::DEPTH_BUFFER_BIT;
387 }
388 },
389 PassClearDepth::ClearWith(_clear_depth) => {
390 let cxtexture = &mut self.textures[depth_texture.texture_id()];
391 let size = dpi_factor * pass_size;
392 cxtexture.update_depth_stencil(gl, size.x as usize, size.y as usize);
393 clear_depth = _clear_depth;
394 clear_flags |= gl_sys::DEPTH_BUFFER_BIT;
395 }
396 }
397 }
398 else {
399 }
420
421 unsafe {
425 let (x, mut y) = (0, 0);
426 let width = (pass_size.x * dpi_factor) as u32;
427 let height = (pass_size.y * dpi_factor) as u32;
428
429 if let [color_texture] = color_textures {
432 let cxtexture = &mut self.textures[color_texture.texture.texture_id()];
433 if cxtexture.os.gl_texture.is_some() {
434 let alloc_height = cxtexture.alloc.as_ref().unwrap().height as u32;
435 if alloc_height > height {
436 y = alloc_height - height;
437 }
438 }
439 }
440
441 (gl.glViewport)(x as i32, y as i32, width as i32, height as i32);
442
443 }
445
446 if clear_flags != 0 {
447 unsafe {
448 if clear_flags & gl_sys::DEPTH_BUFFER_BIT != 0 {
449 (gl.glClearDepthf)(clear_depth);
450 }
451 (gl.glClearColor)(clear_color.x, clear_color.y, clear_color.z, clear_color.w);
452 (gl.glClear)(clear_flags);
453 }
454 }
455 Self::set_default_depth_and_blend_mode(self.os.gl());
456
457 let mut zbias = 0.0;
458 let zbias_step = self.passes[pass_id].zbias_step;
459
460 self.render_view(
461 pass_id,
462 draw_list_id,
463 &mut zbias,
464 zbias_step,
465 );
466
467 unsafe {
468 (self.os.gl().glBindFramebuffer)(gl_sys::FRAMEBUFFER, 0);
469 }
471 }
472
473 pub fn opengl_compile_shaders(&mut self) {
474 for draw_shader_ptr in &self.draw_shaders.compile_set {
476 if let Some(item) = self.draw_shaders.ptr_to_item.get(&draw_shader_ptr) {
477 let cx_shader = &mut self.draw_shaders.shaders[item.draw_shader_id];
478 let draw_shader_def = self.shader_registry.draw_shader_defs.get(&draw_shader_ptr);
479
480 #[cfg(use_gles_3)]
481 let glsl_options = generate_glsl::GlslOptions{
482 use_ovr_multiview: self.os_type.has_xr_mode(),
483 use_uniform_buffers: true,
484 use_inout: true,
485 };
486 #[cfg(not(use_gles_3))]
487 let glsl_options = generate_glsl::GlslOptions{
488 use_ovr_multiview: false,
489 use_uniform_buffers: false,
490 use_inout: false,
491 };
492
493 let vertex = generate_glsl::generate_vertex_shader(
494 draw_shader_def.as_ref().unwrap(),
495 &cx_shader.mapping.const_table,
496 &self.shader_registry,
497 glsl_options
498 );
499
500 let pixel = generate_glsl::generate_pixel_shader(
501 draw_shader_def.as_ref().unwrap(),
502 &cx_shader.mapping.const_table,
503 &self.shader_registry,
504 glsl_options
505 );
506
507 if cx_shader.mapping.flags.debug {
508 crate::log!("{}\n{}", vertex, pixel);
509 }
510
511 for (index, ds) in self.draw_shaders.os_shaders.iter().enumerate() {
513 if ds.vertex[0] == vertex && ds.pixel[0] == pixel {
514 cx_shader.os_shader_id = Some(index);
515 break;
516 }
517 }
518
519 if cx_shader.os_shader_id.is_none() {
520 let shp = CxOsDrawShader::new(self.os.gl(), &vertex, &pixel, &self.os_type);
521 cx_shader.os_shader_id = Some(self.draw_shaders.os_shaders.len());
522 self.draw_shaders.os_shaders.push(shp);
523 }
524 }
525 }
526 self.draw_shaders.compile_set.clear();
527 }
528}
534
535const NUM_SHADER_VARIANTS:usize = 2;
536
537pub struct CxOsDrawShader {
538 pub gl_shader: [Option<GlShader>;NUM_SHADER_VARIANTS],
539 pub in_vertex: String,
540 pub in_pixel: String,
541 pub vertex: [String;NUM_SHADER_VARIANTS],
542 pub pixel: [String;NUM_SHADER_VARIANTS],
543 pub live_uniforms: OpenglBuffer
545}
546
547#[cfg(not(use_gles_3))]
548pub struct GlShaderUniforms{
549 pub pass_uniforms: OpenglUniform,
550 pub draw_list_uniforms: OpenglUniform,
551 pub draw_call_uniforms: OpenglUniform,
552 pub user_uniforms: OpenglUniform,
553 pub live_uniforms: OpenglUniform,
554 pub const_table_uniform: OpenglUniform,
555}
556#[cfg(not(use_gles_3))]
557impl GlShaderUniforms{
558 fn new(gl:&LibGl, program:u32, _mapping:&CxDrawShaderMapping)->Self{
559 Self{
560 pass_uniforms: GlShader::opengl_get_uniform(gl, program, "pass_table"),
561 draw_list_uniforms: GlShader::opengl_get_uniform(gl, program, "draw_list_table"),
562 draw_call_uniforms: GlShader::opengl_get_uniform(gl, program, "draw_call_table"),
563 user_uniforms: GlShader::opengl_get_uniform(gl, program, "user_table"),
564 live_uniforms: GlShader::opengl_get_uniform(gl, program, "live_table"),
565 const_table_uniform: GlShader::opengl_get_uniform(gl, program, "const_table"),
566 }
567 }
568}
569
570#[cfg(use_gles_3)]
571pub struct GlShaderUniforms{
572 pub pass_uniforms_binding: OpenglUniformBlockBinding,
573 pub draw_list_uniforms_binding: OpenglUniformBlockBinding,
574 pub draw_call_uniforms_binding: OpenglUniformBlockBinding,
575 pub user_uniforms_binding: OpenglUniformBlockBinding,
576 pub live_uniforms_binding: OpenglUniformBlockBinding,
577 pub const_table_uniform: OpenglUniform,
578 pub live_uniforms: OpenglBuffer,
579}
580#[cfg(use_gles_3)]
581impl GlShaderUniforms{
582 fn new(gl:&LibGl, program:u32, mapping:&CxDrawShaderMapping)->Self{
583 let mut live_uniforms = OpenglBuffer::default();
584 live_uniforms.update_uniform_buffer(gl, mapping.live_uniforms_buf.as_ref());
585
586 Self{
587 pass_uniforms_binding: GlShader::opengl_get_uniform_block_binding(gl, program, "passUniforms"),
588 draw_list_uniforms_binding: GlShader::opengl_get_uniform_block_binding(gl, program, "draw_listUniforms"),
589 draw_call_uniforms_binding: GlShader::opengl_get_uniform_block_binding(gl, program, "draw_callUniforms"),
590 user_uniforms_binding: GlShader::opengl_get_uniform_block_binding(gl, program, "userUniforms"),
591 live_uniforms_binding: GlShader::opengl_get_uniform_block_binding(gl, program, "liveUniforms"),
592 const_table_uniform: GlShader::opengl_get_uniform(gl, program, "const_table"),
593 live_uniforms,
594 }
595 }
596}
597
598pub struct GlShader {
599 pub program: u32,
600 pub geometries: Vec<OpenglAttribute>,
601 pub instances: Vec<OpenglAttribute>,
602 pub textures: Vec<OpenglUniform>,
603 pub xr_depth_texture: OpenglUniform,
604 pub uniforms: GlShaderUniforms
606
607}
608
609impl GlShader{
610 pub fn new(gl: &LibGl, vertex: &str, pixel: &str, mapping: &CxDrawShaderMapping, os_type: &OsType)->Self{
611 #[cfg(ohos_sim)]
613 unsafe fn read_cache(_gl: &LibOpenGl, _vertex: &str, _pixel: &str, _os_type: &OsType) -> Option<gl_sys::GLuint> {
614 None
615 }
616
617 #[cfg(not(ohos_sim))]
618 unsafe fn read_cache(gl: &LibGl, vertex: &str, pixel: &str, os_type: &OsType) -> Option<gl_sys::GLuint> {
619 if let Some(cache_dir) = os_type.get_cache_dir() {
620 let shader_hash = live_id!(shader).str_append(&vertex).str_append(&pixel);
621 let mut base_filename = format!("{}/shader_{:08x}", cache_dir, shader_hash.0);
622
623 match os_type {
624 OsType::Android(params) => {
625 base_filename = format!("{}_av{}_bn{}_kv{}", base_filename, params.android_version, params.build_number, params.kernel_version);
626 },
627 _ => (),
628 };
629
630 let filename = format!("{}.bin", base_filename);
631
632 if let Ok(mut cache_file) = File::open(&filename) {
633 let mut binary = Vec::new();
634 let mut format_bytes = [0u8; 4];
635 match cache_file.read(&mut format_bytes) {
636 Ok(_bytes_read) => {
637 let binary_format = u32::from_be_bytes(format_bytes);
638 match cache_file.read_to_end(&mut binary) {
639 Ok(_full_bytes) => {
640 let mut version_consistency_conflict = false;
641 match os_type {
643 OsType::Android(params) => {
644 let current_filename = format!("{}/shader_{:08x}_av{}_bn{}_kv{}.bin", cache_dir, shader_hash.0, params.android_version, params.build_number, params.kernel_version);
645 version_consistency_conflict = filename != current_filename;
646 },
647 _ => (),
648 };
649
650 if !version_consistency_conflict {
651 let program = (gl.glCreateProgram)();
652 (gl.glProgramBinary)(program, binary_format, binary.as_ptr() as *const _, binary.len() as i32);
653 if let Some(error) = GlShader::opengl_has_shader_error(gl, false, program as usize, "") {
654 crate::error!("ERROR::SHADER::CACHE::PROGRAM_BINARY_FAILED\n{}", error);
655 return None;
656 }
657 return Some(program);
658 } else {
659 let _ = remove_file(&filename);
661 }
662 }
663 Err(e) => {
664 crate::warning!("Failed to read the full shader cache file {filename}, error: {e}");
665 }
666 }
667 }
668 Err(e) => {
669 crate::warning!("Failed to read format bytes from shader cache file {filename}, error: {e}");
670 }
671 }
672 } else {
673 }
675 } else {
676 }
678 None
679 }
680
681 unsafe {
682 let program = if let Some(program) = read_cache(gl, &vertex,&pixel,os_type){
683 program
684 }
685 else{
686 let vs = (gl.glCreateShader)(gl_sys::VERTEX_SHADER);
687 (gl.glShaderSource)(vs, 1, [vertex.as_ptr() as *const _].as_ptr(), ptr::null());
688 (gl.glCompileShader)(vs);
689 if let Some(error) = Self::opengl_has_shader_error(gl, true, vs as usize, &vertex) {
691 panic!("ERROR::SHADER::VERTEX::COMPILATION_FAILED\n{}", error);
692 }
693 let fs = (gl.glCreateShader)(gl_sys::FRAGMENT_SHADER);
694 (gl.glShaderSource)(fs, 1, [pixel.as_ptr() as *const _].as_ptr(), ptr::null());
695 (gl.glCompileShader)(fs);
696 if let Some(error) = Self::opengl_has_shader_error(gl, true, fs as usize, &pixel) {
698 panic!("ERROR::SHADER::FRAGMENT::COMPILATION_FAILED\n{}", error);
699 }
700
701 let program = (gl.glCreateProgram)();
702 (gl.glAttachShader)(program, vs);
703 (gl.glAttachShader)(program, fs);
704 (gl.glLinkProgram)(program);
705 if let Some(error) = Self::opengl_has_shader_error(gl, false, program as usize, "") {
706 panic!("ERROR::SHADER::LINK::COMPILATION_FAILED\n{}", error);
707 }
708 (gl.glDeleteShader)(vs);
709 (gl.glDeleteShader)(fs);
710
711 #[cfg(not(ohos_sim))] if let Some(cache_dir) = os_type.get_cache_dir() {
713 let mut binary = Vec::new();
714 let mut binary_len = 0;
715 (gl.glGetProgramiv)(program, gl_sys::PROGRAM_BINARY_LENGTH, &mut binary_len);
716 if binary_len != 0 {
717 binary.resize(binary_len as usize, 0u8);
718 let mut return_size = 0i32;
719 let mut binary_format = 0u32;
720 (gl.glGetProgramBinary)(program, binary.len() as i32, &mut return_size as *mut _, &mut binary_format as *mut _, binary.as_mut_ptr() as *mut _);
721 if return_size != 0 {
722 let shader_hash = live_id!(shader).str_append(&vertex).str_append(&pixel);
724 let mut filename = format!("{}/shader_{:08x}", cache_dir, shader_hash.0);
725
726 match os_type {
727 OsType::Android(params) => {
728 filename = format!("{}_av{}_bn{}_kv{}", filename, params.android_version, params.build_number, params.kernel_version);
729 },
730 _ => (),
731 };
732
733 filename = format!("{}.bin", filename);
734
735 binary.resize(return_size as usize, 0u8);
736 match File::create(&filename) {
737 Ok(mut cache) => {
738 let _res1 = cache.write_all(&binary_format.to_be_bytes());
739 let _res2 = cache.write_all(&binary);
740 if _res1.is_err() || _res2.is_err() {
741 crate::error!("Failed to write shader binary to shader cache {filename}");
742 }
743 }
744 Err(e) => {
745 crate::error!("Failed to write shader cache to {filename}, error: {e}");
746 }
747 }
748 }
749 }
750 }
751 program
752 };
753
754 (gl.glUseProgram)(program);
755
756 let uniforms = GlShaderUniforms::new(gl, program, mapping);
757
758 #[cfg(use_gles_3)]
759 uniforms.live_uniforms_binding.bind_buffer(gl, &uniforms.live_uniforms);
760
761 #[cfg(not(use_gles_3))]
762 GlShader::set_uniform_array(gl, &uniforms.live_uniforms, &mapping.live_uniforms_buf);
763
764 let ct = &mapping.const_table.table;
765 if ct.len()>0 {
766 GlShader::set_uniform_array(gl, &uniforms.const_table_uniform, ct);
767 }
768
769 (gl.glUseProgram)(0);
770
771 let t = Self{
772 program,
773 geometries:Self::opengl_get_attributes(gl, program, "packed_geometry_", mapping.geometries.total_slots),
774 instances: Self::opengl_get_attributes(gl, program, "packed_instance_", mapping.instances.total_slots),
775 textures: Self::opengl_get_texture_slots(gl, program, &mapping.textures),
776 xr_depth_texture: Self::opengl_get_uniform(gl, program, "xr_depth_texture"),
777 uniforms
778 };
779 t
780 }
781 }
782
783
784 pub fn set_uniform_array(gl: &LibGl, loc: &OpenglUniform, array: &[f32]) {
785 if let Some(loc) = loc.loc{
786 unsafe {
787 (gl.glUniform1fv)(loc, array.len() as i32, array.as_ptr());
788 }
789 }
790 }
791
792 pub fn opengl_get_uniform(gl: &LibGl, program: u32, name: &str) -> OpenglUniform {
793 unsafe {
794 let loc = (gl.glGetUniformLocation)(program, std::ffi::CString::new(name).unwrap().as_ptr());
795 OpenglUniform {
796 loc: if loc < 0{None} else {Some(loc)},
797 }
798 }
799 }
800
801 pub fn opengl_get_uniform_block_binding(gl: &LibGl, program: u32, name: &str) -> OpenglUniformBlockBinding{
802 unsafe {
803 let index = (gl.glGetUniformBlockIndex)(program, std::ffi::CString::new(name).unwrap().as_ptr()) as i32;
804 if index < 0{
805 return OpenglUniformBlockBinding {
806 index: None,
807 }
808 }
809 (gl.glUniformBlockBinding)(program, index as u32, index as u32);
811
812 OpenglUniformBlockBinding {
813 index: Some(index as u32),
814 }
815 }
816 }
817
818 pub fn opengl_get_info_log(gl: &LibGl, compile: bool, shader: usize, source: &str) -> String {
819 unsafe {
820 let mut length = 0;
821 if compile {
822 (gl.glGetShaderiv)(shader as u32, gl_sys::INFO_LOG_LENGTH, &mut length);
823 } else {
824 (gl.glGetProgramiv)(shader as u32, gl_sys::INFO_LOG_LENGTH, &mut length);
825 }
826 let mut log = Vec::with_capacity(length as usize);
827 if compile {
828 (gl.glGetShaderInfoLog)(shader as u32, length, ptr::null_mut(), log.as_mut_ptr());
829 } else {
830 (gl.glGetProgramInfoLog)(shader as u32, length, ptr::null_mut(), log.as_mut_ptr());
831 }
832 log.set_len(length as usize);
833 let mut r = "".to_string();
834 r.push_str(CStr::from_ptr(log.as_ptr()).to_str().unwrap());
835 r.push_str("\n");
836 let split = source.split("\n");
837 for (line, chunk) in split.enumerate() {
838 r.push_str(&(line + 1).to_string());
839 r.push_str(":");
840 r.push_str(chunk);
841 r.push_str("\n");
842 }
843 r
844 }
845 }
846
847 pub fn opengl_has_shader_error(gl: &LibGl, compile: bool, shader: usize, source: &str) -> Option<String> {
848 unsafe {
850
851 let mut success = gl_sys::TRUE as i32;
852
853 if compile {
854 (gl.glGetShaderiv)(shader as u32, gl_sys::COMPILE_STATUS, &mut success);
855 }
856 else {
857 (gl.glGetProgramiv)(shader as u32, gl_sys::LINK_STATUS, &mut success);
858 };
859
860 if success != gl_sys::TRUE as i32 {
861 Some(Self::opengl_get_info_log(gl, compile, shader, source))
862 }
863 else {
864 None
865 }
866 }
867 }
868
869 pub fn opengl_get_attributes(gl: &LibGl, program: u32, prefix: &str, slots: usize) -> Vec<OpenglAttribute> {
870 let mut attribs = Vec::new();
871
872 fn ceil_div4(base: usize) -> usize {
873 let r = base >> 2;
874 if base & 3 != 0 {
875 return r + 1
876 }
877 r
878 }
879
880 let stride = (slots * mem::size_of::<f32>()) as i32;
881 let num_attr = ceil_div4(slots);
882 for i in 0..num_attr {
883 let mut name0 = prefix.to_string();
884 name0.push_str(&i.to_string());
885 name0.push_str("\0");
886
887 let mut size = ((slots - i * 4)) as i32;
888 if size > 4 {
889 size = 4;
890 }
891 unsafe {
892 attribs.push(
893 OpenglAttribute {
894 name: name0.to_string(),
895 loc: {
896 let loc = (gl.glGetAttribLocation)(program, name0.as_ptr() as *const _);
897 if loc < 0{None}else{Some(loc as u32)}
898
899 },
900 offset: (i * 4 * mem::size_of::<f32>()) as usize,
901 size: size,
902 stride: stride
903 }
904 )
905 }
906 }
907 attribs
908 }
909
910
911 pub fn opengl_get_texture_slots(gl: &LibGl, program: u32, texture_slots: &Vec<DrawShaderTextureInput>) -> Vec<OpenglUniform> {
912 let mut gl_texture_slots = Vec::new();
913
914 for slot in texture_slots {
915 let mut name0 = "ds_".to_string();
916 name0.push_str(&slot.id.to_string());
917 name0.push_str("\0");
918 unsafe {
919 let loc = (gl.glGetUniformLocation)(program, name0.as_ptr().cast());
920 gl_texture_slots.push(OpenglUniform { loc: if loc<0{None}else{Some(loc)} });
922 }
923 }
924 gl_texture_slots
925 }
926
927 pub fn free_resources(self, gl: &LibGl){
928 unsafe{
929 (gl.glDeleteShader)(self.program);
930 }
931 }
932}
933
934impl CxOsDrawShader {
935 pub fn new(gl:&LibGl, in_vertex: &str, in_pixel: &str, os_type: &OsType) -> Self {
936 let available_extensions = get_gl_string(gl, gl_sys::EXTENSIONS);
938 let is_external_texture_supported = available_extensions.split_whitespace().any(|ext| ext == "GL_OES_EGL_image_external");
939
940 let is_emulator = match os_type {
943 OsType::Android(params) => params.is_emulator,
944 OsType::OpenHarmony(_) => true, _ => false,
946 };
947
948 let is_vendor_adreno = get_gl_string(gl, gl_sys::RENDERER).contains("Adreno");
952
953 let (tex_ext_import, tex_ext_sampler) = if is_external_texture_supported && !is_vendor_adreno && !is_emulator {(
954 "#extension GL_OES_EGL_image_external : require\n",
955 "vec4 sample2dOES(samplerExternalOES sampler, vec2 pos){ return texture2D(sampler, vec2(pos.x, pos.y));}"
956 )}
957 else{
958 ("","")
959 };
960
961 let depth_clip = "
974 uniform sampler2DArray xr_depth_texture;
975 vec4 depth_clip(vec4 world, vec4 color, float clip){
976 vec4 cube_depth_camera_position = pass.depth_projection[VIEW_ID] * pass.depth_view[VIEW_ID] * world;
977
978 vec3 cube_depth_camera_position_hc = cube_depth_camera_position.xyz / cube_depth_camera_position.w;
979 cube_depth_camera_position_hc = cube_depth_camera_position_hc*0.5f + 0.5f;
980
981 vec3 depth_view_coord = vec3(cube_depth_camera_position_hc.xy, VIEW_ID);
982
983 gl_FragDepth = cube_depth_camera_position_hc.z;
984
985 float depth_view_eye_z = texture(xr_depth_texture, depth_view_coord).r;
986 if(clip < 0.5 || depth_view_eye_z >= cube_depth_camera_position_hc.z){
987 return color;
988 }
989 return vec4(0.0,0.0,0.0,0.0);
990 }
991 ";
992 #[cfg(use_gles_3)]
993 let nop_depth_clip="
994 vec4 depth_clip(vec4 w, vec4 c, float clip){return c;}
995 ";
996 #[cfg(not(use_gles_3))]
997 let nop_depth_clip="";
998
999 #[cfg(use_gles_3)]
1000 let (version, vertex_exts, pixel_exts, vertex_defs, pixel_defs, sampler) = if os_type.has_xr_mode(){(
1001 "#version 300 es",
1002 "
1004 #define VIEW_ID 0
1005 #extension GL_OVR_multiview2 : require
1006 layout(num_views=2) in;
1007 ",
1008 "
1010 #define VIEW_ID 0
1011 #extension GL_OVR_multiview2 : require
1012 ",
1013 "",
1014 "out vec4 fragColor;",
1015 "
1016 vec4 depth_clip(vec4 w, vec4 c, float clip);
1017 vec4 sample2d(sampler2D sampler, vec2 pos){{return texture(sampler, vec2(pos.x, pos.y));}}
1018 vec4 sample2d_rt(sampler2D sampler, vec2 pos){{return texture(sampler, vec2(pos.x, 1.0 - pos.y));}}
1019 "
1020 )}
1021 else{(
1022 "#version 300 es",
1023 "",
1024 "",
1025 "",
1026 "out vec4 fragColor;",
1027 "
1028 vec4 depth_clip(vec4 w, vec4 c, float clip);
1029 vec4 sample2d(sampler2D sampler, vec2 pos){{return texture(sampler, vec2(pos.x, pos.y));}}
1030 vec4 sample2d_rt(sampler2D sampler, vec2 pos){{return texture(sampler, vec2(pos.x, 1.0 - pos.y));}}
1031 "
1032 )};
1033
1034 #[cfg(not(use_gles_3))]
1035 let (version, vertex_exts, pixel_exts, vertex_defs, pixel_defs, sampler) = (
1036 "#version 100",
1037 "",
1038 "",
1039 "",
1040 "",
1041 "
1042 vec4 depth_clip(vec4 w, vec4 c, float clip){return c;}
1043 vec4 sample2d(sampler2D sampler, vec2 pos){{return texture2D(sampler, vec2(pos.x, pos.y));}}
1044 vec4 sample2d_rt(sampler2D sampler, vec2 pos){{return texture2D(sampler, vec2(pos.x, 1.0 - pos.y));}}
1045 "
1046 );
1047
1048 let vertex = format!("{version}
1056 {vertex_exts}
1057 {tex_ext_import}
1058 precision highp float;
1059 precision highp int;
1060 {sampler}
1061 {tex_ext_sampler}
1062 {vertex_defs}
1063 {in_vertex}\0",
1064 );
1065 let pixel = format!("{version}
1067 {pixel_exts}
1068 {tex_ext_import}
1069 #extension GL_OES_standard_derivatives : enable
1070 precision highp float;
1071 precision highp int;
1072 {sampler}
1073 {tex_ext_sampler}
1074 {pixel_defs}
1075 {in_pixel}
1076 {nop_depth_clip}
1077 \0",
1078 );
1079 CxOsDrawShader {
1081 in_vertex: in_vertex.to_string(),
1082 in_pixel: in_pixel.to_string(),
1083 vertex: [
1084 vertex.clone(),
1085 vertex.replace("#define VIEW_ID 0","#define VIEW_ID gl_ViewID_OVR")
1086 ],
1087 pixel: [
1088 pixel.clone(),
1089 pixel
1090 .replace("#define VIEW_ID 0","#define VIEW_ID gl_ViewID_OVR")
1091 .replace(nop_depth_clip, depth_clip),
1092 ],
1093 gl_shader: [None,None],
1094 live_uniforms: Default::default(),
1096 }
1097 }
1098
1099 pub fn free_resources(&mut self, gl: &LibGl){
1100 for gl_shader in &mut self.gl_shader{
1101 if let Some(gl_shader) = gl_shader.take(){
1102 gl_shader.free_resources(gl);
1103 }
1104 }
1105 }
1106}
1107
1108
1109fn get_gl_string(gl: &LibGl, key: gl_sys::GLenum) -> String {
1110 unsafe {
1111 let string_ptr = (gl.glGetString)(key) as *const c_char;
1112 if string_ptr == ptr::null(){
1113 return String::new()
1114 }
1115 CStr::from_ptr(string_ptr).to_string_lossy().into_owned()
1116 }
1117}
1118
1119#[derive(Default, Clone, Debug)]
1120pub struct OpenglAttribute {
1121 pub name:String,
1122 pub loc: Option<u32>,
1123 pub size: i32,
1124 pub offset: usize,
1125 pub stride: i32
1126}
1127
1128#[derive(Debug, Default, Clone)]
1129pub struct OpenglUniform {
1130 pub loc: Option<i32>,
1131 }
1133
1134
1135#[derive(Debug, Default, Clone)]
1136pub struct OpenglUniformBlockBinding {
1137 pub index: Option<u32>,
1138}
1139
1140impl OpenglUniformBlockBinding{
1141 #[allow(unused)]
1142 fn bind_buffer(&self, gl: &LibGl, buf: &OpenglBuffer,){
1143 if let Some(gl_buf) = buf.gl_buffer{
1144 if let Some(index) = self.index{
1145 unsafe{(gl.glBindBufferBase)(gl_sys::UNIFORM_BUFFER, index, gl_buf)};
1146 }
1147 }
1148 }
1149}
1150
1151#[derive(Clone, Default)]
1152pub struct CxOsGeometry {
1153 pub vb: OpenglBuffer,
1154 pub ib: OpenglBuffer,
1155}
1156
1157impl CxOsGeometry{
1158 pub fn free_resources(&mut self, gl:&LibGl){
1159 self.vb.free_resources(gl);
1160 self.ib.free_resources(gl);
1161 }
1162}
1163
1164
1165#[derive(Clone, Default)]
1173pub struct CxOsDrawList {
1174 #[allow(unused)]
1175 draw_list_uniforms: OpenglBuffer,
1176}
1177
1178#[derive(Default, Clone)]
1179pub struct CxOsDrawCallVao {
1180 pub vao: Option<u32>,
1181 pub shader_id: Option<usize>,
1182 pub inst_vb: Option<u32>,
1183 pub geom_vb: Option<u32>,
1184 pub geom_ib: Option<u32>,
1185}
1186
1187impl CxOsDrawCallVao {
1188 pub fn free(self, gl: &LibGl){
1189 if let Some(vao) = self.vao{
1190 unsafe{(gl.glDeleteVertexArrays)(1, &vao)};
1191 }
1192 }
1193}
1194
1195#[derive(Default, Clone)]
1196pub struct CxOsDrawCall {
1197 pub draw_call_uniforms: OpenglBuffer,
1198 pub user_uniforms: OpenglBuffer,
1199 pub inst_vb: OpenglBuffer,
1200 pub vao: Option<CxOsDrawCallVao>,
1201}
1202
1203impl CxOsDrawCall {
1204 pub fn free_resources(&mut self, gl:&LibGl){
1205 self.inst_vb.free_resources(gl);
1206 if let Some(vao) = self.vao.take(){
1207 vao.free(gl);
1208 }
1209 }
1210}
1211
1212#[derive(Clone, Default)]
1213pub struct CxOsTexture {
1214 pub gl_texture: Option<u32>,
1215 pub gl_renderbuffer: Option<u32>,
1216}
1217
1218impl CxTexture {
1219
1220 pub fn update_vec_texture(&mut self, gl: &LibGl, _os_type: &OsType) {
1236 let mut needs_realloc = false;
1237 if self.alloc_vec() {
1238 if let Some(previous) = self.previous_platform_resource.take() {
1239 self.os = previous;
1240 }
1241 if self.os.gl_texture.is_none() {
1242 unsafe {
1243 let mut gl_texture = std::mem::MaybeUninit::uninit();
1244 (gl.glGenTextures)(1, gl_texture.as_mut_ptr());
1245 self.os.gl_texture = Some(gl_texture.assume_init());
1246 }
1247 }
1248 needs_realloc = true;
1249 }
1250
1251 let updated = self.take_updated();
1252 if updated.is_empty() {
1253 return;
1254 }
1255
1256 unsafe {
1257 (gl.glBindTexture)(gl_sys::TEXTURE_2D, self.os.gl_texture.unwrap());
1258 (gl.glTexParameteri)(gl_sys::TEXTURE_2D, gl_sys::TEXTURE_WRAP_S, gl_sys::CLAMP_TO_EDGE as i32);
1259 (gl.glTexParameteri)(gl_sys::TEXTURE_2D, gl_sys::TEXTURE_WRAP_T, gl_sys::CLAMP_TO_EDGE as i32);
1260
1261 let (width, height, internal_format, format, data_type, data, bytes_per_pixel, use_mipmaps) = match &mut self.format {
1263 TextureFormat::VecBGRAu8_32{width, height, data, ..} => {
1264 let (internal_format, format) = {
1265 #[cfg(ohos_sim)] {
1266 for p in data.as_mut().unwrap() {
1269 let orig = *p;
1270 *p = *p & 0xFF00FF00 | (orig & 0x000000FF) << 16 | (orig & 0x00FF0000) >> 16;
1271 }
1272 (gl_sys::RGBA, gl_sys::RGBA)
1273 }
1274 #[cfg(not(ohos_sim))] {
1275 (gl_sys::BGRA, gl_sys::BGRA)
1277 }
1278 };
1279
1280 (*width, *height, internal_format, format, gl_sys::UNSIGNED_BYTE, data.as_ref().unwrap().as_ptr() as *const std::ffi::c_void, 4, false)
1281 }
1282 TextureFormat::VecMipBGRAu8_32{width, height, data, max_level: _, ..} =>
1283 (*width, *height, gl_sys::BGRA, gl_sys::BGRA, gl_sys::UNSIGNED_BYTE, data.as_ref().unwrap().as_ptr() as *const std::ffi::c_void, 4, true),
1284 TextureFormat::VecRGBAf32{width, height, data, ..} =>
1285 (*width, *height, gl_sys::RGBA, gl_sys::RGBA, gl_sys::FLOAT, data.as_ref().unwrap().as_ptr() as *const std::ffi::c_void, 16, false),
1286 TextureFormat::VecRu8{width, height, data, unpack_row_length, ..} => {
1287 if let Some(row_length) = unpack_row_length {
1289 (gl.glPixelStorei)(gl_sys::UNPACK_ROW_LENGTH, *row_length as i32);
1290 }
1291 (*width, *height, gl_sys::R8, gl_sys::RED, gl_sys::UNSIGNED_BYTE, data.as_ref().unwrap().as_ptr() as *const std::ffi::c_void, 1, false)
1292 },
1293 TextureFormat::VecRGu8{width, height, data, unpack_row_length, ..} => {
1294 if let Some(row_length) = unpack_row_length {
1296 (gl.glPixelStorei)(gl_sys::UNPACK_ROW_LENGTH, *row_length as i32);
1297 }
1298 (*width, *height, gl_sys::RG, gl_sys::RG, gl_sys::UNSIGNED_BYTE, data.as_ref().unwrap().as_ptr() as *const std::ffi::c_void, 2, false)
1299 },
1300 TextureFormat::VecRf32{width, height, data, ..} =>
1301 (*width, *height, gl_sys::RED, gl_sys::RED, gl_sys::FLOAT, data.as_ref().unwrap().as_ptr() as *const std::ffi::c_void, 4, false),
1302 _ => panic!("Unsupported texture format"),
1303 };
1304
1305 const DO_PARTIAL_TEXTURE_UPDATES: bool = false;match updated {
1311 TextureUpdated::Partial(rect) if DO_PARTIAL_TEXTURE_UPDATES => {
1312 if needs_realloc {
1313 (gl.glTexImage2D)(
1314 gl_sys::TEXTURE_2D,
1315 0,
1316 internal_format as i32,
1317 width as i32, height as i32,
1318 0,
1319 format,
1320 data_type,
1321 0 as *const _
1322 );
1323 }
1324
1325 (gl.glPixelStorei)(gl_sys::UNPACK_ALIGNMENT, bytes_per_pixel);
1326 (gl.glPixelStorei)(gl_sys::UNPACK_ROW_LENGTH, width as _);
1327 (gl.glPixelStorei)(gl_sys::UNPACK_SKIP_PIXELS, rect.origin.x as i32);
1328 (gl.glPixelStorei)(gl_sys::UNPACK_SKIP_ROWS,rect.origin.y as i32);
1329 (gl.glTexSubImage2D)(
1330 gl_sys::TEXTURE_2D,
1331 0,
1332 rect.origin.x as i32,
1333 rect.origin.y as i32 ,
1334 rect.size.width as i32,
1335 rect.size.height as i32,
1336 format,
1337 data_type,
1338 data
1339 );
1340 },
1341 TextureUpdated::Partial(_) | TextureUpdated::Full => {
1343 (gl.glPixelStorei)(gl_sys::UNPACK_ALIGNMENT, bytes_per_pixel);
1344 (gl.glPixelStorei)(gl_sys::UNPACK_ROW_LENGTH, width as _);
1345 (gl.glPixelStorei)(gl_sys::UNPACK_SKIP_PIXELS, 0);
1346 (gl.glPixelStorei)(gl_sys::UNPACK_SKIP_ROWS, 0);
1347 (gl.glTexImage2D)(
1348 gl_sys::TEXTURE_2D,
1349 0,
1350 internal_format as i32,
1351 width as i32, height as i32,
1352 0,
1353 format,
1354 data_type,
1355 data
1356 );
1357 },
1358 TextureUpdated::Empty => panic!("already asserted that updated is not empty"),
1359 };
1360
1361 (gl.glTexParameteri)(gl_sys::TEXTURE_2D, gl_sys::TEXTURE_MIN_FILTER, if use_mipmaps { gl_sys::LINEAR_MIPMAP_LINEAR } else { gl_sys::LINEAR } as i32);
1362 (gl.glTexParameteri)(gl_sys::TEXTURE_2D, gl_sys::TEXTURE_MAG_FILTER, gl_sys::LINEAR as i32);
1363
1364 if use_mipmaps {
1365 if let TextureFormat::VecMipBGRAu8_32{max_level, ..} = &self.format {
1366 (gl.glTexParameteri)(gl_sys::TEXTURE_2D, gl_sys::TEXTURE_BASE_LEVEL, 0);
1367 (gl.glTexParameteri)(gl_sys::TEXTURE_2D, gl_sys::TEXTURE_MAX_LEVEL, max_level.unwrap_or(1000) as i32);
1368 (gl.glGenerateMipmap)(gl_sys::TEXTURE_2D);
1369 }
1370 }
1371
1372 (gl.glBindTexture)(gl_sys::TEXTURE_2D, 0);
1373 }
1374 }
1375
1376 pub fn setup_video_texture(&mut self, gl: &LibGl) -> bool {
1377 while unsafe { (gl.glGetError)() } != 0 {}
1378
1379 if self.alloc_video() {
1380 self.free_previous_resources(gl);
1381 if self.os.gl_texture.is_none() {
1382 unsafe {
1383 let mut gl_texture = std::mem::MaybeUninit::uninit();
1384 (gl.glGenTextures)(1, gl_texture.as_mut_ptr());
1385 self.os.gl_texture = Some(gl_texture.assume_init());
1386 }
1387 }
1388 }
1389 if self.take_initial() {
1390 unsafe{
1391
1392 let gpu_renderer = get_gl_string(gl, gl_sys::RENDERER);
1393 if gpu_renderer.contains("Adreno") {
1394 crate::warning!("WARNING: This device is using {gpu_renderer} renderer.
1395 OpenGL external textures (GL_OES_EGL_image_external extension) are currently not working on makepad for most Adreno GPUs.
1396 This is likely due to a driver bug. External texture support is being disabled, which means you won't be able to use the Video widget on this device.");
1397 }
1398
1399 (gl.glBindTexture)(gl_sys::TEXTURE_EXTERNAL_OES, self.os.gl_texture.unwrap());
1400
1401 (gl.glTexParameteri)(gl_sys::TEXTURE_EXTERNAL_OES, gl_sys::TEXTURE_WRAP_S, gl_sys::CLAMP_TO_EDGE as i32);
1402 (gl.glTexParameteri)(gl_sys::TEXTURE_EXTERNAL_OES, gl_sys::TEXTURE_WRAP_T, gl_sys::CLAMP_TO_EDGE as i32);
1403
1404 (gl.glTexParameteri)(gl_sys::TEXTURE_EXTERNAL_OES, gl_sys::TEXTURE_MIN_FILTER, gl_sys::LINEAR as i32);
1405 (gl.glTexParameteri)(gl_sys::TEXTURE_EXTERNAL_OES, gl_sys::TEXTURE_MAG_FILTER, gl_sys::LINEAR as i32);
1406
1407 (gl.glBindTexture)(gl_sys::TEXTURE_EXTERNAL_OES, 0);
1408
1409 assert_eq!((gl.glGetError)(), 0, "UPDATE VIDEO TEXTURE ERROR {}", self.os.gl_texture.unwrap());
1410 }
1411 return true;
1412 }
1413 false
1414 }
1415
1416 pub fn update_render_target(&mut self, gl: &LibGl, width: usize, height: usize) {
1417 if self.alloc_render(width, height){
1418 let alloc = self.alloc.as_ref().unwrap();
1419 if self.os.gl_texture.is_none() {
1420 let mut gl_texture = std::mem::MaybeUninit::uninit();
1421 unsafe{
1422 (gl.glGenTextures)(1, gl_texture.as_mut_ptr());
1423 self.os.gl_texture = Some(gl_texture.assume_init());
1424 }
1425 }
1426 unsafe{(gl.glBindTexture)(gl_sys::TEXTURE_2D, self.os.gl_texture.unwrap())};
1427 match &alloc.pixel {
1428 TexturePixel::BGRAu8 => unsafe{
1429 (gl.glTexParameteri)(gl_sys::TEXTURE_2D, gl_sys::TEXTURE_MIN_FILTER, gl_sys::NEAREST as i32);
1430 (gl.glTexParameteri)(gl_sys::TEXTURE_2D, gl_sys::TEXTURE_MAG_FILTER, gl_sys::NEAREST as i32);
1431 (gl.glTexImage2D)(
1432 gl_sys::TEXTURE_2D,
1433 0,
1434 gl_sys::RGBA as i32,
1435 width as i32,
1436 height as i32,
1437 0,
1438 gl_sys::RGBA,
1439 gl_sys::UNSIGNED_BYTE,
1440 ptr::null()
1441 );
1442 },
1443 TexturePixel::RGBAf16 => unsafe{
1444 (gl.glTexParameteri)(gl_sys::TEXTURE_2D, gl_sys::TEXTURE_MIN_FILTER, gl_sys::NEAREST as i32);
1445 (gl.glTexParameteri)(gl_sys::TEXTURE_2D, gl_sys::TEXTURE_MAG_FILTER, gl_sys::NEAREST as i32);
1446 (gl.glTexImage2D)(
1447 gl_sys::TEXTURE_2D,
1448 0,
1449 gl_sys::RGBA as i32,
1450 width as i32,
1451 height as i32,
1452 0,
1453 gl_sys::RGBA,
1454 gl_sys::HALF_FLOAT,
1455 ptr::null()
1456 );
1457 }
1458 TexturePixel::RGBAf32 => unsafe{
1459 (gl.glTexParameteri)(gl_sys::TEXTURE_2D, gl_sys::TEXTURE_MIN_FILTER, gl_sys::NEAREST as i32);
1460 (gl.glTexParameteri)(gl_sys::TEXTURE_2D, gl_sys::TEXTURE_MAG_FILTER, gl_sys::NEAREST as i32);
1461 (gl.glTexImage2D)(
1462 gl_sys::TEXTURE_2D,
1463 0,
1464 gl_sys::RGBA as i32,
1465 width as i32,
1466 height as i32,
1467 0,
1468 gl_sys::RGBA,
1469 gl_sys::FLOAT,
1470 ptr::null()
1471 );
1472 }
1473 _ => panic!()
1474 }
1475 unsafe{
1476 (gl.glBindTexture)(gl_sys::TEXTURE_2D, 0);
1477 }
1478 }
1479 }
1480
1481 fn update_depth_stencil(
1482 &mut self,
1483 gl: &LibGl,
1484 width: usize,
1485 height: usize
1486 ) {
1487 if self.alloc_depth(width, height){
1488
1489 let alloc = self.alloc.as_ref().unwrap();
1490 match &alloc.pixel {
1491 TexturePixel::D32 => unsafe{
1492 if self.os.gl_renderbuffer.is_none() {
1493 let mut gl_renderbuf = std::mem::MaybeUninit::uninit();
1494 (gl.glGenRenderbuffers)(1, gl_renderbuf.as_mut_ptr());
1495 let gl_renderbuffer = gl_renderbuf.assume_init();
1496 self.os.gl_renderbuffer = Some(gl_renderbuffer);
1497 }
1498
1499 (gl.glBindRenderbuffer)(gl_sys::RENDERBUFFER, self.os.gl_renderbuffer.unwrap());
1500 (gl.glRenderbufferStorage)(
1501 gl_sys::RENDERBUFFER,
1502 gl_sys::DEPTH_COMPONENT32F,
1503 width as i32,
1504 height as i32
1505 );
1506 (gl.glBindRenderbuffer)(gl_sys::RENDERBUFFER, 0);
1507 },
1508 _ => {
1509 println!("update_platform_render_targete unsupported texture format");
1510 }
1511 }
1512 }
1513 }
1514
1515 pub fn free_previous_resources(&mut self, gl: &LibGl){
1516 if let Some(mut old_os) = self.previous_platform_resource.take(){
1517 if let Some(gl_texture) = old_os.gl_texture.take(){
1518 unsafe{(gl.glDeleteTextures)(1, &gl_texture)};
1519 crate::log!("Deleted texture: {}", gl_texture);
1520 }
1521 if let Some(gl_renderbuffer) = old_os.gl_renderbuffer.take(){
1522 unsafe{(gl.glDeleteRenderbuffers)(1, &gl_renderbuffer)};
1523 }
1524 }
1525 }
1526}
1527
1528#[derive(Default, Clone)]
1529pub struct CxOsPass {
1530 pub shader_variant: usize,
1531 pub pass_uniforms: OpenglBuffer,
1532 pub gl_framebuffer: Option<u32>,
1533}
1534
1535impl CxOsPass{
1536
1537 pub fn free_resources(&mut self, gl: &LibGl){
1538 if let Some(gl_framebuffer) = self.gl_framebuffer.take(){
1539 unsafe{(gl.glDeleteFramebuffers)(1, &gl_framebuffer)};
1540 }
1541 }
1542}
1543
1544#[derive(Default, Clone)]
1545pub struct OpenglBuffer {
1546 pub gl_buffer: Option<u32>
1547}
1548
1549impl OpenglBuffer {
1550
1551 pub fn alloc_gl_buffer(&mut self, gl: &LibGl) {
1552 unsafe {
1553 let mut gl_buffer = 0;
1554 (gl.glGenBuffers)(1, &mut gl_buffer);
1555 self.gl_buffer = Some(gl_buffer);
1556 }
1557 }
1558
1559 pub fn update_array_buffer(&mut self, gl: &LibGl, data: &[f32]) {
1560 if self.gl_buffer.is_none() {
1561 self.alloc_gl_buffer(gl);
1562 }
1563 unsafe {
1564 (gl.glBindBuffer)(gl_sys::ARRAY_BUFFER, self.gl_buffer.unwrap());
1565 (gl.glBufferData)(
1566 gl_sys::ARRAY_BUFFER,
1567 (data.len() * mem::size_of::<f32>()) as gl_sys::GLsizeiptr,
1568 data.as_ptr() as *const _,
1569 gl_sys::STATIC_DRAW
1570 );
1571 (gl.glBindBuffer)(gl_sys::ARRAY_BUFFER, 0);
1572 }
1573 }
1574
1575 pub fn update_uniform_buffer(&mut self, gl: &LibGl, data: &[f32]) {
1576 if self.gl_buffer.is_none() {
1577 self.alloc_gl_buffer(gl);
1578 }
1579 unsafe {
1580 (gl.glBindBuffer)(gl_sys::UNIFORM_BUFFER, self.gl_buffer.unwrap());
1581 (gl.glBufferData)(
1582 gl_sys::UNIFORM_BUFFER,
1583 (data.len() * mem::size_of::<f32>()) as gl_sys::GLsizeiptr,
1584 data.as_ptr() as *const _,
1585 gl_sys::STATIC_DRAW
1586 );
1587 (gl.glBindBuffer)(gl_sys::UNIFORM_BUFFER, 0);
1588 crate::gl_log_error!(gl);
1589 }
1590 }
1591
1592 pub fn update_index_buffer(&mut self, gl: &LibGl, data: &[u32]) {
1593 if self.gl_buffer.is_none() {
1594 self.alloc_gl_buffer(gl);
1595 }
1596 unsafe {
1597 (gl.glBindBuffer)(gl_sys::ELEMENT_ARRAY_BUFFER, self.gl_buffer.unwrap());
1598 (gl.glBufferData)(
1599 gl_sys::ELEMENT_ARRAY_BUFFER,
1600 (data.len() * mem::size_of::<u32>()) as gl_sys::GLsizeiptr,
1601 data.as_ptr() as *const _,
1602 gl_sys::STATIC_DRAW
1603 );
1604 (gl.glBindBuffer)(gl_sys::ELEMENT_ARRAY_BUFFER, 0);
1605 }
1606 }
1607
1608 pub fn free_resources(&mut self, gl: &LibGl){
1609 if let Some(gl_buffer) = self.gl_buffer.take(){
1610 unsafe{(gl.glDeleteBuffers)(1, &gl_buffer)};
1611 }
1612 }
1613
1614}