SDL2 window resizing

I am writing an emulator in Rust, and it performs output using SDL2. One thing that the window needs to be able to do is resize itself programmatically. Pixels are drawn by the graphics device to a large buffer allocated using std::alloc::alloc.

Currently, the main loop looks like this (simplified, cut down):

    let sdl_ctx = sdl2::init().unwrap();
    let video = sdl_ctx.video().unwrap();

    let mut current_width = 640;
    let mut current_height = 480;
    let window = video
        .window("Halfix x86 Emulator", current_width, current_height)
        .position_centered()
        .build()
        .expect("Could not create window");

    let mut canvas = window
        .into_canvas()
        .build()
        .expect("Could not create canvas");
    let mut texture_creator = canvas.texture_creator();
    let mut texture = texture_creator
        .create_texture_streaming(PixelFormatEnum::RGBA8888, current_width, current_height)
        .unwrap();

    let mut events = sdl_ctx.event_pump().unwrap();

    loop {
        vm.run(); // Runs the CPU, handles the timer, etc. 
        let (pixels, w, h) = vm.render(); // Draws the graphical output and blits it to the pixels array, which is &'static mut [u8]
        if w != current_width || h != current_height {
            current_height = h;
            current_width = w;
            let window = canvas.window_mut();
            window.set_size(w, h).unwrap();

            canvas
                .set_logical_size(current_width, current_height)
                .unwrap();

            // resize texture as well
            texture = texture_creator
                .create_texture_streaming(PixelFormatEnum::ARGB8888, current_width, current_height)
                .unwrap();

            println!("Resize canvas to w={} h={}", w, h);
        }

        for event in events.poll_iter() {
            match event {
                Event::Quit { .. } => return,
                _ => {}
            }
        }

        texture
            .with_lock(None, |pixels2, pitch| unsafe {
                if pixels2.len() != pixels.len() { // This condition fails
                    println!("w={} h={}", w, h);
                    panic!("invalid sizes!! p2={} p1={}", pixels2.len(), pixels.len());
                }
                std::ptr::copy_nonoverlapping(
                    pixels.as_ptr(),
                    pixels2.as_mut_ptr(),
                    pitch * (h as usize),
                );
            })
            .unwrap();

        canvas.copy(&texture, None, None).unwrap();
        canvas.present();
    }

Basically, the loop does the following:

  1. Run the emulator for a bit.
  2. Call the device that handles visual output and get it to spit out an array of pixels
  3. Check if the device has changed its resolution and, if so, change the size of the window
  4. Handle all events
  5. Blit the pixels to the screen

I'm sure there's a better way to do things, but I'm just not sure how. pixels2.len() != pixels.len() always fails after I switch resolutions, and Valgrind reports a ton of errors. I don't have much experience with SDL2 or its Rust bindings, and so any help/feedback would be much appreciated.

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.