Attempt to bludgeon the winit/glium/gfx versions into submission

This commit is contained in:
Thom Chiovoloni 2020-12-31 19:04:58 -08:00
parent 7fce85fe60
commit 64a8d3260d
16 changed files with 269 additions and 120 deletions

View File

@ -51,6 +51,7 @@ jobs:
- run: cargo clippy --manifest-path imgui-winit-support/Cargo.toml --no-default-features --features winit-20 --all-targets
- run: cargo clippy --manifest-path imgui-winit-support/Cargo.toml --no-default-features --features winit-22 --all-targets
- run: cargo clippy --manifest-path imgui-winit-support/Cargo.toml --no-default-features --features winit-23 --all-targets
- run: cargo clippy --manifest-path imgui-winit-support/Cargo.toml --no-default-features --features winit-24 --all-targets
rustfmt:
name: Check rustfmt
runs-on: ubuntu-latest
@ -135,3 +136,4 @@ jobs:
- run: cargo test --manifest-path imgui-winit-support/Cargo.toml --no-default-features --features winit-20
- run: cargo test --manifest-path imgui-winit-support/Cargo.toml --no-default-features --features winit-22
- run: cargo test --manifest-path imgui-winit-support/Cargo.toml --no-default-features --features winit-23
- run: cargo test --manifest-path imgui-winit-support/Cargo.toml --no-default-features --features winit-24

View File

@ -5,11 +5,26 @@
### Changed
- is_key_down, is_key_pressed, is_key_released and key_pressed_amount now make a call to key_index internally and thus take a Key instead of u32
- `imgui-winit-support`'s `winit-23` feature no longer is compatible with `winit` 0.24.x, which apparently didn't work anyway. Instead the
- The default `imgui-winit-support` feature has been changed to `winit-24`, as it's now the latest.
### Removed
- key_index is now only used internally
- The `gfx` and `glium` features are removed to reduce version compatibility issues going forward.
- In the somewhat unlikely case that you used these features directly (and not as part of `imgui-{gfx,glium}-renderer`) you should use replace calls to `draw_list.vtx_buffer::<imgui::DrawVert>()` with `draw_list.transmute_vtx_buffer::<MyDrawVert>()`, where `MyDrawVert` is a struct with the same layout as `imgui::DrawVert` (For examples, please see the `imgui-gfx-renderer` and `imgui-glium-renderer` crates — in particular, the definition and implementation of `GliumDrawVert`/`GfxDrawVert`).
This is less convenient, but avoids depending on any specific version of `gfx` or `glium`, which will ease maintenance.
## [0.6.1](https://github.com/imgui-rs/imgui-rs/releases/tag/v0.6.1) - 2020-12-16
This release mainly updated the glium/winit/glium versions, adding support for winit `0.24` and related.
Unfortunately, this caused unintentional breaking changes (it was the holidays and not enough attention was paid to the changes in an urgent-sounding request for supporting the new version), and thus violated the stated semver change.
This release will be yanked once 0.7.0 is released, but not before, so that users who need 0.24 support are still able to use imgui.
## [0.6.0] - 2020-11-15
### Added

View File

@ -16,7 +16,7 @@ default = ["opengl"]
[dependencies]
gfx = "0.18"
imgui = { version = "0.6.1", path = "../imgui", features = ["gfx"] }
imgui = { version = "0.6.1", path = "../imgui" }
[target.'cfg(windows)'.build-dependencies]
winapi = { version = "0.3", features = ["d3dcompiler"] }

View File

@ -1,3 +1,4 @@
#[macro_use]
pub extern crate gfx;
pub extern crate imgui;
@ -10,8 +11,7 @@ use gfx::traits::FactoryExt;
use gfx::{CommandBuffer, Encoder, Factory, IntoIndexBuffer, Rect, Resources, Slice};
use imgui::internal::RawWrapper;
use imgui::{
BackendFlags, DrawCmd, DrawCmdParams, DrawData, DrawIdx, DrawVert, ImString, TextureId,
Textures,
BackendFlags, DrawCmd, DrawCmdParams, DrawData, DrawIdx, ImString, TextureId, Textures,
};
use std::error::Error;
use std::fmt;
@ -136,7 +136,7 @@ pub type Texture<R> = (
);
pub struct Renderer<Cf: BlendFormat, R: Resources> {
vertex_buffer: Buffer<R, DrawVert>,
vertex_buffer: Buffer<R, GfxDrawVert>,
index_buffer: Buffer<R, DrawIdx>,
slice: Slice<R>,
pso: PipelineState<R, pipeline::Meta<Cf>>,
@ -158,7 +158,7 @@ where
) -> Result<Renderer<Cf, R>, RendererError> {
let (vs_code, ps_code) = shaders.get_program_code();
let pso = factory.create_pipeline_simple(vs_code, ps_code, pipeline::new::<Cf>())?;
let vertex_buffer = factory.create_buffer::<DrawVert>(
let vertex_buffer = factory.create_buffer::<GfxDrawVert>(
256,
gfx::buffer::Role::Vertex,
gfx::memory::Usage::Dynamic,
@ -237,7 +237,9 @@ where
let clip_off = draw_data.display_pos;
let clip_scale = draw_data.framebuffer_scale;
for draw_list in draw_data.draw_lists() {
self.upload_vertex_buffer(factory, encoder, draw_list.vtx_buffer())?;
self.upload_vertex_buffer(factory, encoder, unsafe {
draw_list.transmute_vtx_buffer::<GfxDrawVert>()
})?;
self.upload_index_buffer(factory, encoder, draw_list.idx_buffer())?;
self.slice.start = 0;
for cmd in draw_list.commands() {
@ -307,10 +309,10 @@ where
&mut self,
factory: &mut F,
encoder: &mut Encoder<R, C>,
vtx_buffer: &[DrawVert],
vtx_buffer: &[GfxDrawVert],
) -> Result<(), RendererError> {
if self.vertex_buffer.len() < vtx_buffer.len() {
self.vertex_buffer = factory.create_buffer::<DrawVert>(
self.vertex_buffer = factory.create_buffer::<GfxDrawVert>(
vtx_buffer.len(),
gfx::buffer::Role::Vertex,
gfx::memory::Usage::Dynamic,
@ -388,6 +390,7 @@ mod constants {
// * Everything is parameterized with BlendFormat
// * Pipeline init is specialized for our structs
mod pipeline {
use super::*;
use gfx::format::BlendFormat;
use gfx::handle::Manager;
use gfx::preset::blend;
@ -397,11 +400,10 @@ mod pipeline {
};
use gfx::state::ColorMask;
use gfx::{ProgramInfo, Resources};
use imgui::DrawVert;
#[derive(Clone, Debug, PartialEq)]
pub struct Data<'a, R: Resources, Cf: BlendFormat + 'a> {
pub vertex_buffer: &'a <gfx::VertexBuffer<DrawVert> as DataBind<R>>::Data,
pub vertex_buffer: &'a <gfx::VertexBuffer<GfxDrawVert> as DataBind<R>>::Data,
#[cfg(not(feature = "directx"))]
pub matrix: &'a <gfx::Global<[[f32; 4]; 4]> as DataBind<R>>::Data,
#[cfg(feature = "directx")]
@ -413,7 +415,7 @@ mod pipeline {
#[derive(Clone, Debug, Hash, PartialEq)]
pub struct Meta<Cf: BlendFormat> {
vertex_buffer: gfx::VertexBuffer<DrawVert>,
vertex_buffer: gfx::VertexBuffer<GfxDrawVert>,
#[cfg(not(feature = "directx"))]
matrix: gfx::Global<[[f32; 4]; 4]>,
#[cfg(feature = "directx")]
@ -425,7 +427,7 @@ mod pipeline {
#[derive(Clone, Debug, PartialEq)]
pub struct Init<'a, Cf: BlendFormat> {
vertex_buffer: <gfx::VertexBuffer<DrawVert> as DataLink<'a>>::Init,
vertex_buffer: <gfx::VertexBuffer<GfxDrawVert> as DataLink<'a>>::Init,
#[cfg(not(feature = "directx"))]
matrix: <gfx::Global<[[f32; 4]; 4]> as DataLink<'a>>::Init,
#[cfg(feature = "directx")]
@ -582,3 +584,11 @@ mod pipeline {
}
}
}
gfx_vertex_struct! {
GfxDrawVert {
pos: [f32; 2] = "pos",
uv: [f32; 2] = "uv",
col: [gfx::format::U8Norm; 4] = "col",
}
}

View File

@ -11,4 +11,4 @@ categories = ["gui", "rendering"]
[dependencies]
glium = { version = ">=0.28, < 0.30", default-features = false }
imgui = { version = "0.6.1", path = "../imgui", features = ["glium"] }
imgui = { version = "0.6.1", path = "../imgui" }

View File

@ -100,6 +100,42 @@ pub struct Renderer {
textures: Textures<Texture>,
}
#[repr(C)]
#[derive(Copy, Clone, Debug, PartialEq)]
pub struct GliumDrawVert {
pub pos: [f32; 2],
pub uv: [f32; 2],
pub col: [u8; 4],
}
// manual impl to avoid an allocation, and to reduce macro wonkiness.
impl glium::vertex::Vertex for GliumDrawVert {
#[inline]
fn build_bindings() -> glium::vertex::VertexFormat {
use std::borrow::Cow::*;
Borrowed(&[
(
Borrowed("pos"),
0,
glium::vertex::AttributeType::F32F32,
false,
),
(
Borrowed("uv"),
8,
glium::vertex::AttributeType::F32F32,
false,
),
(
Borrowed("col"),
16,
glium::vertex::AttributeType::U8U8U8U8,
false,
),
])
}
}
impl Renderer {
pub fn init<F: Facade>(
ctx: &mut imgui::Context,
@ -166,7 +202,9 @@ impl Renderer {
let clip_off = draw_data.display_pos;
let clip_scale = draw_data.framebuffer_scale;
for draw_list in draw_data.draw_lists() {
let vtx_buffer = VertexBuffer::immutable(&self.ctx, draw_list.vtx_buffer())?;
let vtx_buffer = VertexBuffer::immutable(&self.ctx, unsafe {
draw_list.transmute_vtx_buffer::<GliumDrawVert>()
})?;
let idx_buffer = IndexBuffer::immutable(
&self.ctx,
PrimitiveType::TrianglesList,

View File

@ -14,10 +14,11 @@ imgui = { version = "0.6.1", path = "../imgui" }
winit-19 = { version = ">= 0.16, < 0.20", package = "winit", optional = true }
winit-20 = { version = ">= 0.20, < 0.22", package = "winit", optional = true }
winit-22 = { version = "0.22", package = "winit", optional = true }
winit-23 = { version = ">= 0.23, < 0.25", package = "winit", optional = true }
winit-23 = { version = "0.23", package = "winit", optional = true }
winit-24 = { version = "0.24", package = "winit", optional = true }
[features]
default = ["winit-23"]
default = ["winit-24"]
# This is phrased as a negative (unlike most features) so that it needs to be
# explicitly disabled (and `default-features = false` won't do it). To avoid

View File

@ -79,9 +79,10 @@
//!
//! The following versions are supported, controlled by the listed feature.
//!
//! - The `winit-23` feature supports winit versions `0.23` and `0.24`. This is
//! - The `winit-24` feature supports winit versions `0.24`. This is
//! on by default, so to use any other version you need to disable this crates
//! default features.
//! - The `winit-23` feature uses winit versions compatible with `0.23`.
//! - The `winit-22` feature uses winit versions compatible with `0.22`.
//! - The `winit-20` feature should support winit either `0.20` or winit `0.21`.
//! - The `winit-19` feature should support winits older than `0.19` (possibly
@ -93,7 +94,7 @@
//! feature, fixing the configuration, or disabling `debug_assertions`.
//!
//! Conversely, if no `winit-*` features are enabled, we will fail to compile.
//! This is not an issue generally, as by default we turn on `winit-23`.
//! This is not an issue generally, as by default we turn on `winit-24`.
//!
//! All of this is in attempt to preserve the additive nature of features (while
//! still helping users notice project configuration issues), however it's done
@ -131,20 +132,31 @@
//! - Changing the default feature to the new latest `winit` version is *not* a
//! breaking change.
#[cfg(feature = "winit-23")]
#[cfg(feature = "winit-24")]
use winit_24 as winit;
#[cfg(all(not(feature = "winit-24"), feature = "winit-23"))]
use winit_23 as winit;
#[cfg(all(not(feature = "winit-23"), feature = "winit-22"))]
#[cfg(all(
not(any(feature = "winit-24", feature = "winit-23", feature = "winit-22")),
feature = "winit-20",
))]
use winit_22 as winit;
#[cfg(all(
not(any(feature = "winit-23", feature = "winit-22")),
not(any(feature = "winit-24", feature = "winit-23", feature = "winit-22")),
feature = "winit-20",
))]
use winit_20 as winit;
#[cfg(all(
not(any(feature = "winit-23", feature = "winit-22", feature = "winit-20")),
not(any(
feature = "winit-24",
feature = "winit-23",
feature = "winit-22",
feature = "winit-20"
)),
feature = "winit-19",
))]
use winit_19 as winit;
@ -155,7 +167,12 @@ use std::cmp::Ordering;
use winit::dpi::{LogicalPosition, LogicalSize};
#[cfg(all(
not(any(feature = "winit-23", feature = "winit-22", feature = "winit-20")),
not(any(
feature = "winit-24",
feature = "winit-23",
feature = "winit-22",
feature = "winit-20"
)),
feature = "winit-19",
))]
use winit::{
@ -163,7 +180,12 @@ use winit::{
TouchPhase, VirtualKeyCode, Window, WindowEvent,
};
#[cfg(any(feature = "winit-20", feature = "winit-22", feature = "winit-23"))]
#[cfg(any(
feature = "winit-20",
feature = "winit-22",
feature = "winit-23",
feature = "winit-24"
))]
use winit::{
error::ExternalError,
event::{
@ -179,9 +201,11 @@ use winit::{
feature = "winit-20",
feature = "winit-22",
feature = "winit-23",
feature = "winit-24",
)))]
compile_error!("Please enable at least one version of `winit` (see documentation for details).");
// FIXME(thom): make updading winit and adding a new feature less of a hassle here.
fn check_multiple_winits() {
use std::io::Write as _;
use std::sync::atomic::{AtomicBool, Ordering};
@ -189,7 +213,8 @@ fn check_multiple_winits() {
if cfg!(any(not(debug_assertions), feature = "no-warn-on-multiple")) {
return;
}
let winits_enabled = cfg!(feature = "winit-23") as usize
let winits_enabled = cfg!(feature = "winit-24") as usize
+ cfg!(feature = "winit-23") as usize
+ cfg!(feature = "winit-22") as usize
+ cfg!(feature = "winit-20") as usize
+ cfg!(feature = "winit-19") as usize;
@ -216,7 +241,8 @@ fn check_multiple_winits() {
(this likely indicates misconfiguration, see documentation for details)."
);
let feats = [
("winit-23", cfg!(feature = "winit-23"), " (default)"),
("winit-24", cfg!(feature = "winit-24"), " (default)"),
("winit-23", cfg!(feature = "winit-23"), ""),
("winit-22", cfg!(feature = "winit-22"), ""),
("winit-20", cfg!(feature = "winit-20"), ""),
("winit-19", cfg!(feature = "winit-19"), ""),
@ -226,7 +252,7 @@ fn check_multiple_winits() {
let _ = writeln!(err, " `feature = {:?}` is enabled{}", name, extra);
}
}
if cfg!(feature = "winit-23") && winits_enabled == 2 {
if cfg!(feature = "winit-24") && winits_enabled == 2 {
let _ = writeln!(
err,
" Perhaps you are missing a `default-features = false`?",
@ -303,7 +329,12 @@ fn to_winit_cursor(cursor: imgui::MouseCursor) -> MouseCursor {
impl CursorSettings {
#[cfg(all(
not(any(feature = "winit-23", feature = "winit-22", feature = "winit-20")),
not(any(
feature = "winit-24",
feature = "winit-23",
feature = "winit-22",
feature = "winit-20"
)),
feature = "winit-19",
))]
fn apply(&self, window: &Window) {
@ -315,7 +346,12 @@ impl CursorSettings {
_ => window.hide_cursor(true),
}
}
#[cfg(any(feature = "winit-20", feature = "winit-22", feature = "winit-23"))]
#[cfg(any(
feature = "winit-20",
feature = "winit-22",
feature = "winit-23",
feature = "winit-24"
))]
fn apply(&self, window: &Window) {
match self.cursor {
Some(mouse_cursor) if !self.draw_cursor => {
@ -421,7 +457,12 @@ impl WinitPlatform {
/// * framebuffer scale (= DPI factor) is set
/// * display size is set
#[cfg(all(
not(any(feature = "winit-23", feature = "winit-22", feature = "winit-20")),
not(any(
feature = "winit-24",
feature = "winit-23",
feature = "winit-22",
feature = "winit-20"
)),
feature = "winit-19",
))]
pub fn attach_window(&mut self, io: &mut Io, window: &Window, hidpi_mode: HiDpiMode) {
@ -440,7 +481,12 @@ impl WinitPlatform {
///
/// * framebuffer scale (= DPI factor) is set
/// * display size is set
#[cfg(any(feature = "winit-20", feature = "winit-22", feature = "winit-23"))]
#[cfg(any(
feature = "winit-20",
feature = "winit-22",
feature = "winit-23",
feature = "winit-24"
))]
pub fn attach_window(&mut self, io: &mut Io, window: &Window, hidpi_mode: HiDpiMode) {
let (hidpi_mode, hidpi_factor) = hidpi_mode.apply(window.scale_factor());
self.hidpi_mode = hidpi_mode;
@ -461,7 +507,12 @@ impl WinitPlatform {
/// This utility function is useful if you are using a DPI mode other than default, and want
/// your application to use the same logical coordinates as imgui-rs.
#[cfg(all(
not(any(feature = "winit-23", feature = "winit-22", feature = "winit-20")),
not(any(
feature = "winit-24",
feature = "winit-23",
feature = "winit-22",
feature = "winit-20"
)),
feature = "winit-19",
))]
pub fn scale_size_from_winit(&self, window: &Window, logical_size: LogicalSize) -> LogicalSize {
@ -476,7 +527,12 @@ impl WinitPlatform {
///
/// This utility function is useful if you are using a DPI mode other than default, and want
/// your application to use the same logical coordinates as imgui-rs.
#[cfg(any(feature = "winit-20", feature = "winit-22", feature = "winit-23"))]
#[cfg(any(
feature = "winit-20",
feature = "winit-22",
feature = "winit-23",
feature = "winit-24"
))]
pub fn scale_size_from_winit(
&self,
window: &Window,
@ -494,7 +550,12 @@ impl WinitPlatform {
/// This utility function is useful if you are using a DPI mode other than default, and want
/// your application to use the same logical coordinates as imgui-rs.
#[cfg(all(
not(any(feature = "winit-23", feature = "winit-22", feature = "winit-20")),
not(any(
feature = "winit-24",
feature = "winit-23",
feature = "winit-22",
feature = "winit-20"
)),
feature = "winit-19",
))]
pub fn scale_pos_from_winit(
@ -513,7 +574,12 @@ impl WinitPlatform {
///
/// This utility function is useful if you are using a DPI mode other than default, and want
/// your application to use the same logical coordinates as imgui-rs.
#[cfg(any(feature = "winit-20", feature = "winit-22", feature = "winit-23"))]
#[cfg(any(
feature = "winit-20",
feature = "winit-22",
feature = "winit-23",
feature = "winit-24"
))]
pub fn scale_pos_from_winit(
&self,
window: &Window,
@ -531,7 +597,12 @@ impl WinitPlatform {
/// This utility function is useful if you are using a DPI mode other than default, and want
/// your application to use the same logical coordinates as imgui-rs.
#[cfg(all(
not(any(feature = "winit-23", feature = "winit-22", feature = "winit-20")),
not(any(
feature = "winit-24",
feature = "winit-23",
feature = "winit-22",
feature = "winit-20"
)),
feature = "winit-19",
))]
pub fn scale_pos_for_winit(
@ -550,7 +621,12 @@ impl WinitPlatform {
///
/// This utility function is useful if you are using a DPI mode other than default, and want
/// your application to use the same logical coordinates as imgui-rs.
#[cfg(any(feature = "winit-20", feature = "winit-22", feature = "winit-23"))]
#[cfg(any(
feature = "winit-20",
feature = "winit-22",
feature = "winit-23",
feature = "winit-24"
))]
pub fn scale_pos_for_winit(
&self,
window: &Window,
@ -571,7 +647,12 @@ impl WinitPlatform {
/// * keyboard state is updated
/// * mouse state is updated
#[cfg(all(
not(any(feature = "winit-23", feature = "winit-22", feature = "winit-20")),
not(any(
feature = "winit-24",
feature = "winit-23",
feature = "winit-22",
feature = "winit-20"
)),
feature = "winit-19",
))]
pub fn handle_event(&mut self, io: &mut Io, window: &Window, event: &Event) {
@ -613,7 +694,7 @@ impl WinitPlatform {
/// * keyboard state is updated
/// * mouse state is updated
#[cfg(all(
not(any(feature = "winit-23", feature = "winit-22")),
not(any(feature = "winit-24", feature = "winit-23", feature = "winit-22")),
feature = "winit-20",
))]
pub fn handle_event<T>(&mut self, io: &mut Io, window: &Window, event: &Event<T>) {
@ -660,7 +741,7 @@ impl WinitPlatform {
/// * window size / dpi factor changes are applied
/// * keyboard state is updated
/// * mouse state is updated
#[cfg(any(feature = "winit-22", feature = "winit-23"))]
#[cfg(any(feature = "winit-22", feature = "winit-23", feature = "winit-24"))]
pub fn handle_event<T>(&mut self, io: &mut Io, window: &Window, event: &Event<T>) {
match *event {
Event::WindowEvent {
@ -696,7 +777,12 @@ impl WinitPlatform {
}
}
#[cfg(all(
not(any(feature = "winit-23", feature = "winit-22", feature = "winit-20")),
not(any(
feature = "winit-24",
feature = "winit-23",
feature = "winit-22",
feature = "winit-20"
)),
feature = "winit-19",
))]
fn handle_window_event(&mut self, io: &mut Io, window: &Window, event: &WindowEvent) {
@ -787,7 +873,7 @@ impl WinitPlatform {
}
}
#[cfg(all(
not(feature = "winit-23"),
not(any(feature = "winit-23", feature = "winit-24")),
any(feature = "winit-20", feature = "winit-22")
))]
fn handle_window_event(&mut self, io: &mut Io, window: &Window, event: &WindowEvent) {
@ -892,7 +978,7 @@ impl WinitPlatform {
}
}
#[cfg(feature = "winit-23")]
#[cfg(any(feature = "winit-23", feature = "winit-24"))]
fn handle_window_event(&mut self, io: &mut Io, window: &Window, event: &WindowEvent) {
match *event {
WindowEvent::Resized(physical_size) => {
@ -1002,7 +1088,12 @@ impl WinitPlatform {
///
/// * mouse cursor is repositioned (if requested by imgui-rs)
#[cfg(all(
not(any(feature = "winit-23", feature = "winit-22", feature = "winit-20")),
not(any(
feature = "winit-24",
feature = "winit-23",
feature = "winit-22",
feature = "winit-20"
)),
feature = "winit-19",
))]
pub fn prepare_frame(&self, io: &mut Io, window: &Window) -> Result<(), String> {
@ -1023,7 +1114,12 @@ impl WinitPlatform {
/// This function performs the following actions:
///
/// * mouse cursor is repositioned (if requested by imgui-rs)
#[cfg(any(feature = "winit-20", feature = "winit-22", feature = "winit-23"))]
#[cfg(any(
feature = "winit-20",
feature = "winit-22",
feature = "winit-23",
feature = "winit-24"
))]
pub fn prepare_frame(&self, io: &mut Io, window: &Window) -> Result<(), ExternalError> {
self.copy_mouse_to_io(&mut io.mouse_down);
if io.want_set_mouse_pos {

View File

@ -13,9 +13,7 @@ readme = "../README.markdown"
exclude = ["/resources"]
[dependencies]
bitflags = "1.0"
glium = { version = ">= 0.28, < 0.30", default-features = false, optional = true }
gfx = { version = "0.18", optional = true }
bitflags = "1"
imgui-sys = { version = "0.6.0", path = "../imgui-sys" }
parking_lot = "0.11"

View File

@ -228,6 +228,7 @@ impl FontAtlas {
}
#[test]
#[cfg(test)]
fn test_font_atlas_memory_layout() {
use std::mem;
assert_eq!(
@ -238,13 +239,15 @@ fn test_font_atlas_memory_layout() {
mem::align_of::<FontAtlas>(),
mem::align_of::<sys::ImFontAtlas>()
);
use memoffset::offset_of;
use sys::ImFontAtlas;
macro_rules! assert_field_offset {
($l:ident, $r:ident) => {
assert_eq!(offset_of!(FontAtlas, $l), offset_of!(ImFontAtlas, $r));
assert_eq!(
memoffset::offset_of!(FontAtlas, $l),
memoffset::offset_of!(ImFontAtlas, $r)
);
};
};
}
assert_field_offset!(locked, Locked);
assert_field_offset!(flags, Flags);
assert_field_offset!(tex_id, TexID);

View File

@ -41,13 +41,15 @@ fn test_font_memory_layout() {
use std::mem;
assert_eq!(mem::size_of::<Font>(), mem::size_of::<sys::ImFont>());
assert_eq!(mem::align_of::<Font>(), mem::align_of::<sys::ImFont>());
use memoffset::offset_of;
use sys::ImFont;
macro_rules! assert_field_offset {
($l:ident, $r:ident) => {
assert_eq!(offset_of!(Font, $l), offset_of!(ImFont, $r));
assert_eq!(
memoffset::offset_of!(Font, $l),
memoffset::offset_of!(ImFont, $r)
);
};
};
}
assert_field_offset!(index_advance_x, IndexAdvanceX);
assert_field_offset!(fallback_advance_x, FallbackAdvanceX);
assert_field_offset!(font_size, FontSize);

View File

@ -45,13 +45,15 @@ fn test_font_glyph_memory_layout() {
mem::align_of::<FontGlyph>(),
mem::align_of::<sys::ImFontGlyph>()
);
use memoffset::offset_of;
use sys::ImFontGlyph;
macro_rules! assert_field_offset {
($l:ident, $r:ident) => {
assert_eq!(offset_of!(FontGlyph, $l), offset_of!(ImFontGlyph, $r));
assert_eq!(
memoffset::offset_of!(FontGlyph, $l),
memoffset::offset_of!(ImFontGlyph, $r)
);
};
};
}
assert_field_offset!(bitfields, _bitfield_1);
assert_field_offset!(advance_x, AdvanceX);
assert_field_offset!(x0, X0);

View File

@ -18,6 +18,7 @@ impl<T> ImVector<T> {
}
#[test]
#[cfg(test)]
fn test_imvector_memory_layout() {
use std::mem;
assert_eq!(
@ -28,14 +29,16 @@ fn test_imvector_memory_layout() {
mem::align_of::<ImVector<u8>>(),
mem::align_of::<sys::ImVector_char>()
);
use memoffset::offset_of;
use sys::ImVector_char;
type VectorChar = ImVector<u8>;
macro_rules! assert_field_offset {
($l:ident, $r:ident) => {
assert_eq!(offset_of!(VectorChar, $l), offset_of!(ImVector_char, $r));
assert_eq!(
memoffset::offset_of!(VectorChar, $l),
memoffset::offset_of!(ImVector_char, $r)
);
};
};
}
assert_field_offset!(size, Size);
assert_field_offset!(capacity, Capacity);
assert_field_offset!(data, Data);

View File

@ -384,17 +384,20 @@ impl IndexMut<MouseButton> for Io {
}
#[test]
#[cfg(test)]
fn test_io_memory_layout() {
use std::mem;
assert_eq!(mem::size_of::<Io>(), mem::size_of::<sys::ImGuiIO>());
assert_eq!(mem::align_of::<Io>(), mem::align_of::<sys::ImGuiIO>());
use memoffset::offset_of;
use sys::ImGuiIO;
macro_rules! assert_field_offset {
($l:ident, $r:ident) => {
assert_eq!(offset_of!(Io, $l), offset_of!(ImGuiIO, $r));
assert_eq!(
memoffset::offset_of!(Io, $l),
memoffset::offset_of!(ImGuiIO, $r)
);
};
};
}
assert_field_offset!(config_flags, ConfigFlags);
assert_field_offset!(backend_flags, BackendFlags);
assert_field_offset!(display_size, DisplaySize);

View File

@ -88,6 +88,7 @@ impl<'a> Iterator for DrawListIterator<'a> {
}
#[test]
#[cfg(test)]
fn test_drawdata_memory_layout() {
use std::mem;
assert_eq!(
@ -98,13 +99,15 @@ fn test_drawdata_memory_layout() {
mem::align_of::<DrawData>(),
mem::align_of::<sys::ImDrawData>()
);
use memoffset::offset_of;
use sys::ImDrawData;
macro_rules! assert_field_offset {
($l:ident, $r:ident) => {
assert_eq!(offset_of!(DrawData, $l), offset_of!(ImDrawData, $r));
assert_eq!(
memoffset::offset_of!(DrawData, $l),
memoffset::offset_of!(ImDrawData, $r)
);
};
};
}
assert_field_offset!(valid, Valid);
assert_field_offset!(cmd_lists, CmdLists);
assert_field_offset!(cmd_lists_count, CmdListsCount);
@ -152,6 +155,21 @@ impl DrawList {
)
}
}
/// # Safety
/// This is equivalent to `transmute(self.vtx_buffer())` with a little more
/// checking, and thus inherits the safety considerations of `transmute`ing
/// slices.
pub unsafe fn transmute_vtx_buffer<VTy: Copy>(&self) -> &[VTy] {
// these checks are constant and thus are removed from release builds
assert_eq!(
core::mem::size_of::<VTy>(),
core::mem::size_of::<DrawVert>(),
);
assert!(core::mem::align_of::<VTy>() <= core::mem::align_of::<DrawVert>());
slice::from_raw_parts(self.0.VtxBuffer.Data.cast(), self.0.VtxBuffer.Size as usize)
}
pub fn commands(&self) -> DrawCmdIterator {
unsafe {
DrawCmdIterator {
@ -228,55 +246,8 @@ pub struct DrawVert {
pub col: [u8; 4],
}
#[cfg(feature = "glium")]
mod glium_support {
#![allow(clippy::unneeded_field_pattern)]
use super::DrawVert;
use glium::implement_vertex;
implement_vertex!(DrawVert, pos, uv, col);
}
#[cfg(feature = "gfx")]
mod gfx_support {
use super::DrawVert;
use gfx::*;
// gfx doesn't provide a macro to implement vertex structure for an existing struct, so we
// create a dummy vertex with the same memory layout using gfx macros, and delegate query(name)
// calls later to the automatically derived implementation
gfx_vertex_struct! {
Dummy {
pos: [f32; 2] = "pos",
uv: [f32; 2] = "uv",
col: [format::U8Norm; 4] = "col",
}
}
unsafe impl gfx::traits::Pod for DrawVert {}
impl gfx::pso::buffer::Structure<gfx::format::Format> for DrawVert {
fn query(name: &str) -> Option<gfx::pso::buffer::Element<gfx::format::Format>> {
// Dummy has the same memory layout, so this should be ok
Dummy::query(name)
}
}
#[test]
fn test_dummy_memory_layout() {
use std::mem;
assert_eq!(mem::size_of::<DrawVert>(), mem::size_of::<Dummy>());
assert_eq!(mem::align_of::<DrawVert>(), mem::align_of::<Dummy>());
use memoffset::offset_of;
macro_rules! assert_field_offset {
($l:ident, $r:ident) => {
assert_eq!(offset_of!(DrawVert, $l), offset_of!(Dummy, $r));
};
};
assert_field_offset!(pos, pos);
assert_field_offset!(uv, uv);
assert_field_offset!(col, col);
}
}
#[test]
#[cfg(test)]
fn test_drawvert_memory_layout() {
use std::mem;
assert_eq!(
@ -287,13 +258,15 @@ fn test_drawvert_memory_layout() {
mem::align_of::<DrawVert>(),
mem::align_of::<sys::ImDrawVert>()
);
use memoffset::offset_of;
use sys::ImDrawVert;
macro_rules! assert_field_offset {
($l:ident, $r:ident) => {
assert_eq!(offset_of!(DrawVert, $l), offset_of!(ImDrawVert, $r));
assert_eq!(
memoffset::offset_of!(DrawVert, $l),
memoffset::offset_of!(ImDrawVert, $r)
);
};
};
}
assert_field_offset!(pos, pos);
assert_field_offset!(uv, uv);
assert_field_offset!(col, col);

View File

@ -423,17 +423,20 @@ fn test_style_color_indexing() {
}
#[test]
#[cfg(test)]
fn test_style_memory_layout() {
use std::mem;
assert_eq!(mem::size_of::<Style>(), mem::size_of::<sys::ImGuiStyle>());
assert_eq!(mem::align_of::<Style>(), mem::align_of::<sys::ImGuiStyle>());
use memoffset::offset_of;
use sys::ImGuiStyle;
macro_rules! assert_field_offset {
($l:ident, $r:ident) => {
assert_eq!(offset_of!(Style, $l), offset_of!(ImGuiStyle, $r));
assert_eq!(
memoffset::offset_of!(Style, $l),
memoffset::offset_of!(ImGuiStyle, $r)
);
};
};
}
assert_field_offset!(alpha, Alpha);
assert_field_offset!(window_padding, WindowPadding);
assert_field_offset!(window_rounding, WindowRounding);