You are an expert in writing code in many different languages. Your goal is to perform code completion for the following code, keeping in mind the rest of the code and the file meta data.
    Metadata details:
    filename: texture_registry.rs
    path of file: ./repos/flutter-rs/flutter-engine/src
    
    the code of the file until where you have to start completion: use crate::FlutterEngine;
use flutter_engine_sys::FlutterOpenGLTexture;
#[cfg(feature = "image")]
use image::RgbaImage;
use parking_lot::Mutex;
use std::collections::HashMap;
use std::os::raw::c_void;
use std::sync::atomic::{AtomicI64, Ordering};
use std::sync::Arc;

pub(crate) struct TextureRegistry {
    last_id: AtomicI64,
    frames: Arc<Mutex<HashMap<TextureId, TextureFrame>>>,
}

impl TextureRegistry {
    pub fn new() -> Self {
        Self {
            last_id: AtomicI64::new(1),
            frames: Arc::new(Default::default()),
        }
    }

    pub fn create_texture(&self, engine: FlutterEngine) -> Texture {
        let texture_id = self.last_id.fetch_add(1, Ordering::Relaxed);

        engine.run_on_platform_thread(move |engine| {
            log::trace!("texture {}: register", texture_id);
            unsafe {
                flutter_engine_sys::FlutterEngineRegisterExternalTexture(
                    engine.engine_ptr(),
                    texture_id,
                );
            }
        });

        Texture {
            engine,
            texture_id,
            frames: self.frames.clone(),
        }
    }

    pub fn get_texture_frame(
        &self,
        texture_id: TextureId,
        _size: (usize, usize),
    ) -> Option<TextureFrame> {
        self.frames.lock().remov
    
    pub fn post_frame_rgba(&self, img: RgbaImage) {
        let texture_id = self.texture_id;
        let frames = self.frames.clone();
        self.engine.run_on_render_thread(move |engine| {
            let (width, height) = img.dimensions();

            let glid = unsafe {
                let mut glid: u32 = 0;
                gl::GenTextures(1, &mut glid as *mut _);
                gl::BindTexture(gl::TEXTURE_2D, glid);
                gl::PixelStorei(gl::UNPACK_ALIGNMENT, 1);
                gl::TexParameteri(gl::TEXTURE_2D, gl::TEXTURE_MIN_FILTER, gl::LINEAR as _);
                gl::TexParameteri(gl::TEXTURE_2D, gl::TEXTURE_MAG_FILTER, gl::LINEAR as _);
                gl::TexImage2D(
                    gl::TEXTURE_2D,
                    0,             // mipmap level
                    gl::RGBA as _, // internal format of the texture
                    width as _,
                    height as _,
                    0,                           // border, must be 0
                    gl::RGBA,                    // format of the pixel data
                    gl::UNSIGNED_BYTE,           // data type of the pixel data
                    (&img).as_ptr() as *const _, // pixel data
                );
                gl::BindTexture(gl::TEXTURE_2D, 0);

                glid
            };

            let engine_weak = engine.downgrade();
            let frame = TextureFrame::new(gl::TEXTURE_2D, glid, gl::RGBA8, move || {
                if let Some(engine) = engine_weak.upgrade() {
                    engine.run_on_render_thread(move |_| unsafe {
                        gl::DeleteTextures(1, &glid as *const _);
                    });
                }
            });

            post_frame_internal(&engine, texture_id, &frames, frame);
        });
    }