1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
/* SPDX-License-Identifier: LGPL-2.1-or-later

Copyright (c) 2022 Purism, SPC
*/

/*! OpenGL procedures.

The Shader binds the surfaces on every call.
It might be that there is performance to be gained by only doing it once
for every shader/input/output surface triple.
Or even by doing binding/import once per texture individually.
*/


pub mod egl;
pub mod egl_ext;
mod glerr;
pub mod shaders;
mod raw;
mod uniforms;

pub use cgmath;
use egl::Dimensions;
use egl::Texture;
pub use egl::{ContextRef, CurrentContext};
pub use gbm::Format;
use gl;
pub use glium;
use glium::GlObject;
use glium::texture::UnsignedTexture2d;
pub use raw::Facade;
pub use shaders::bayer;
pub use shaders::yuv;

/// Initializes the GL texture.
// For unknown reasons, passing a texture obtained this way to uniforms with the relevant filters doesn't do anything to initialize it.
// Instead, this does the necessary setup.
fn import_bind_texture<F: glium::backend::Facade>(
    facade: &F,
    tex: Texture,
) -> Result<UnsignedTexture2d, glerr::Error> {
    let Dimensions { width, height } = tex.dimensions();
    let imported = unsafe {
        use glium::texture::*;
        UnsignedTexture2d::from_id(
            facade,
            UncompressedUintFormat::U8U8U8U8,
            tex.id().as_gl_id(),
            // This unbinds the texture when dropped.
            // The ownership pertains to the ID, not the backing image
            true,
            MipmapsOption::NoMipmap,
            Dimensions::Texture2d { width, height },
        )
    };
    // Can't get Backend directly out of Facade, so we access it behind glium's back.
    gl::load_with(|s| unsafe {raw::Backend::get_proc_address(s)});
    // Excuse me while I cargo-cult
    // whatever is happening in Texture2d::with_mipmaps.
    unsafe {
        let bind_point = gl::TEXTURE_2D;
        let id = imported.get_id();
        
        glerr::check(
            gl::BindTexture(bind_point, id)
        )?;
        glerr::check(
            gl::TexParameteri(bind_point, gl::TEXTURE_WRAP_S, gl::CLAMP_TO_BORDER as i32)
        )?;
        glerr::check(
            gl::TexParameteri(bind_point, gl::TEXTURE_MAG_FILTER, gl::LINEAR as i32)
        )?;
        glerr::check(
            gl::TexParameteri(bind_point, gl::TEXTURE_WRAP_T, gl::CLAMP_TO_BORDER as i32)
        )?;
        glerr::check(
            gl::TexParameteri(bind_point, gl::TEXTURE_MIN_FILTER, gl::LINEAR as i32)
        )?;
        glerr::check(
            gl::TexParameteri(bind_point, gl::TEXTURE_BASE_LEVEL, 0)
        )?;
        glerr::check(
            gl::TexParameteri(bind_point, gl::TEXTURE_MAX_LEVEL, 0)
        )?;
        // Here glium uses format RGBA8.
        // Somehow the texture is immutable. This call fails. Leaving it as commented to provide clues in case something goes wrong in the future.
        // Update: with this uncommented, the texture is blank
        //glerr::check(
            //gl::TexStorage2D(bind_point, 1, gl::R8, width as i32, height as i32)
        //)?;
    }
    Ok(imported)
}