cpu start
This commit is contained in:
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,81 @@
|
||||
// dear imgui: CPU framebuffer renderer backend
|
||||
// (supports caller-owned framebuffers/textures in generic packed pixel formats)
|
||||
//
|
||||
// Implemented features:
|
||||
// [X] Renderer: User texture binding. Use 'ImGui_ImplCPU_Texture*' as texture identifier.
|
||||
// [X] Renderer: Large meshes support (64k+ vertices) even with 16-bit indices.
|
||||
// [X] Renderer: Texture updates support for dynamic font atlas.
|
||||
|
||||
#pragma once
|
||||
#ifndef IMGUI_DISABLE
|
||||
#include "imgui.h"
|
||||
|
||||
struct ImGui_ImplCPU_PixelFormat;
|
||||
typedef ImU32 (*ImGui_ImplCPU_MapColorFn)(const ImGui_ImplCPU_PixelFormat* format, unsigned char r, unsigned char g, unsigned char b, unsigned char a);
|
||||
|
||||
struct ImGui_ImplCPU_PixelFormat
|
||||
{
|
||||
int BitsPerPixel;
|
||||
int BytesPerPixel;
|
||||
ImU32 Rmask;
|
||||
ImU32 Gmask;
|
||||
ImU32 Bmask;
|
||||
ImU32 Amask;
|
||||
ImU8 Rshift;
|
||||
ImU8 Gshift;
|
||||
ImU8 Bshift;
|
||||
ImU8 Ashift;
|
||||
ImU8 Rloss;
|
||||
ImU8 Gloss;
|
||||
ImU8 Bloss;
|
||||
ImU8 Aloss;
|
||||
const ImU32* Palette; // Optional palette entries stored as IM_COL32(r, g, b, a).
|
||||
int PaletteSize; // Number of palette entries, or 0 when Palette is unused.
|
||||
ImGui_ImplCPU_MapColorFn MapColorFn; // Optional indexed/paletted mapping override. Return a raw packed pixel value.
|
||||
};
|
||||
|
||||
enum ImGui_ImplCPU_BuiltinFormat
|
||||
{
|
||||
ImGui_ImplCPU_BuiltinFormat_RGBA8888 = 0,
|
||||
ImGui_ImplCPU_BuiltinFormat_BGRA8888,
|
||||
ImGui_ImplCPU_BuiltinFormat_ARGB8888,
|
||||
ImGui_ImplCPU_BuiltinFormat_ABGR8888,
|
||||
ImGui_ImplCPU_BuiltinFormat_RGB565,
|
||||
ImGui_ImplCPU_BuiltinFormat_ARGB1555,
|
||||
ImGui_ImplCPU_BuiltinFormat_RGBA4444,
|
||||
ImGui_ImplCPU_BuiltinFormat_RGB888,
|
||||
ImGui_ImplCPU_BuiltinFormat_BGR888,
|
||||
ImGui_ImplCPU_BuiltinFormat_Alpha8,
|
||||
ImGui_ImplCPU_BuiltinFormat_COUNT
|
||||
};
|
||||
|
||||
struct ImGui_ImplCPU_Framebuffer
|
||||
{
|
||||
unsigned char* Pixels;
|
||||
int Width;
|
||||
int Height;
|
||||
int Pitch;
|
||||
const ImGui_ImplCPU_PixelFormat* Format; // Optional. Defaults to ImGui_ImplCPU_BuiltinFormat_RGBA8888.
|
||||
};
|
||||
|
||||
struct ImGui_ImplCPU_Texture
|
||||
{
|
||||
const unsigned char* Pixels;
|
||||
int Width;
|
||||
int Height;
|
||||
int Pitch;
|
||||
const ImGui_ImplCPU_PixelFormat* Format; // Optional. Defaults to ImGui_ImplCPU_BuiltinFormat_RGBA8888.
|
||||
};
|
||||
|
||||
// Follow "Getting Started" link and check examples/ folder to learn about using backends!
|
||||
IMGUI_IMPL_API const ImGui_ImplCPU_PixelFormat* ImGui_ImplCPU_GetBuiltinPixelFormat(ImGui_ImplCPU_BuiltinFormat format);
|
||||
IMGUI_IMPL_API bool ImGui_ImplCPU_Init();
|
||||
IMGUI_IMPL_API void ImGui_ImplCPU_Shutdown();
|
||||
IMGUI_IMPL_API void ImGui_ImplCPU_NewFrame();
|
||||
IMGUI_IMPL_API void ImGui_ImplCPU_RenderDrawData(ImDrawData* draw_data, ImGui_ImplCPU_Framebuffer* framebuffer);
|
||||
|
||||
// (Advanced) Use e.g. if you need to precisely control the timing of texture updates
|
||||
// by setting ImDrawData::Textures = nullptr to handle this manually.
|
||||
IMGUI_IMPL_API void ImGui_ImplCPU_UpdateTexture(ImTextureData* tex);
|
||||
|
||||
#endif // #ifndef IMGUI_DISABLE
|
||||
+2
-1
@@ -84,6 +84,7 @@ List of Platforms Backends:
|
||||
|
||||
List of Renderer Backends:
|
||||
|
||||
imgui_impl_cpu.cpp ; Generic packed-pixel CPU framebuffer renderer (RGBA/BGRA/RGB565/indexed, etc. see example_sdl2_cpu, example_apple_cpu)
|
||||
imgui_impl_dx9.cpp ; DirectX9
|
||||
imgui_impl_dx10.cpp ; DirectX10
|
||||
imgui_impl_dx11.cpp ; DirectX11
|
||||
@@ -105,7 +106,7 @@ List of high-level Frameworks Backends (combining Platform + Renderer):
|
||||
imgui_impl_null.cpp
|
||||
|
||||
Emscripten is also supported!
|
||||
The SDL2+GL, SDL3+GL, SDL2+Surface, SDL3+Surface, GLFW+GL and GLFW+WebGPU examples are all ready to build and run with Emscripten.
|
||||
The SDL2+CPU, SDL2+GL, SDL3+GL, SDL2+Surface, SDL3+Surface, GLFW+GL and GLFW+WebGPU examples are all ready to build and run with Emscripten.
|
||||
|
||||
### Recommended Backends
|
||||
|
||||
|
||||
@@ -71,6 +71,11 @@ OSX + OpenGL2 example. <BR>
|
||||
(NB: imgui_impl_osx.mm is currently not as feature complete as other platforms backends.
|
||||
You may prefer to use the GLFW Or SDL backends, which will also support Windows and Linux.)
|
||||
|
||||
[example_apple_cpu/](https://github.com/ocornut/imgui/blob/master/examples/example_apple_cpu/) <BR>
|
||||
OSX + CPU framebuffer example. <BR>
|
||||
= main.mm + imgui_impl_osx.mm + imgui_impl_cpu.cpp <BR>
|
||||
This is a native Cocoa example, renders to a native BGRA framebuffer, and does not use SDL.<BR>
|
||||
|
||||
[example_glfw_wgpu/](https://github.com/ocornut/imgui/blob/master/examples/example_glfw_wgpu/) <BR>
|
||||
GLFW + WebGPU example. Supports Emscripten (web), Dawn (native), WGPU (native). <BR>
|
||||
= main.cpp + imgui_impl_glfw.cpp + imgui_impl_wgpu.cpp
|
||||
@@ -150,6 +155,12 @@ SDL2 (Win32, Mac, Linux, etc.) + SDL_Surface CPU renderer example.<BR>
|
||||
= main.cpp + imgui_impl_sdl2.cpp + imgui_impl_sdlsurface2.cpp <BR>
|
||||
This supports building with Emscripten.<BR>
|
||||
|
||||
[example_sdl2_cpu/](https://github.com/ocornut/imgui/blob/master/examples/example_sdl2_cpu/) <BR>
|
||||
SDL2 (Win32, Mac, Linux, etc.) + caller-owned packed-pixel CPU framebuffer renderer example.<BR>
|
||||
= main.cpp + imgui_impl_sdl2.cpp + imgui_impl_cpu.cpp <BR>
|
||||
This derives the CPU framebuffer format from the current SDL window surface.<BR>
|
||||
This supports building with Emscripten.<BR>
|
||||
|
||||
[example_sdl2_vulkan/](https://github.com/ocornut/imgui/blob/master/examples/example_sdl2_vulkan/) <BR>
|
||||
SDL2 (Win32, Mac, Linux, etc.) + Vulkan example. <BR>
|
||||
= main.cpp + imgui_impl_sdl2.cpp + imgui_impl_vulkan.cpp <BR>
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
# Makefile for example_apple_cpu, for macOS only
|
||||
CXX = clang++
|
||||
EXE = example_apple_cpu
|
||||
IMGUI_DIR = ../..
|
||||
SOURCES = main.mm
|
||||
SOURCES += $(IMGUI_DIR)/imgui.cpp $(IMGUI_DIR)/imgui_demo.cpp $(IMGUI_DIR)/imgui_draw.cpp $(IMGUI_DIR)/imgui_tables.cpp $(IMGUI_DIR)/imgui_widgets.cpp
|
||||
SOURCES += $(IMGUI_DIR)/backends/imgui_impl_osx.mm $(IMGUI_DIR)/backends/imgui_impl_cpu.cpp
|
||||
|
||||
OPTFLAGS ?= -O2
|
||||
CXXFLAGS = -std=c++11 -ObjC++ -fobjc-arc -g $(OPTFLAGS) -Wall -Wextra -I$(IMGUI_DIR) -I$(IMGUI_DIR)/backends
|
||||
FRAMEWORKS = -framework Cocoa -framework GameController
|
||||
|
||||
all: $(EXE)
|
||||
@echo Build complete for Mac OS X
|
||||
|
||||
$(EXE): $(SOURCES)
|
||||
$(CXX) $(CXXFLAGS) $(SOURCES) -o $(EXE) $(FRAMEWORKS)
|
||||
|
||||
run: all
|
||||
./$(EXE)
|
||||
|
||||
clean:
|
||||
rm -f $(EXE) *.o
|
||||
@@ -0,0 +1,14 @@
|
||||
# How to Build
|
||||
|
||||
## macOS
|
||||
|
||||
Use the provided `Makefile` or directly:
|
||||
```sh
|
||||
clang++ -std=c++11 -ObjC++ -fobjc-arc -I ../.. -I ../../backends \
|
||||
main.mm ../../backends/imgui_impl_osx.mm ../../backends/imgui_impl_cpu.cpp ../../imgui*.cpp \
|
||||
-framework Cocoa -framework GameController \
|
||||
-o example_apple_cpu
|
||||
```
|
||||
|
||||
This example uses Cocoa + `imgui_impl_osx` for windowing/input and `imgui_impl_cpu` for rendering.
|
||||
It renders to a native BGRA CPU framebuffer and does not use SDL.
|
||||
Executable
BIN
Binary file not shown.
@@ -0,0 +1,424 @@
|
||||
// Dear ImGui: standalone macOS example using Cocoa + CPU framebuffer rendering.
|
||||
|
||||
// Learn about Dear ImGui:
|
||||
// - FAQ https://dearimgui.com/faq
|
||||
// - Getting Started https://dearimgui.com/getting-started
|
||||
// - Documentation https://dearimgui.com/docs (same as your local docs/ folder).
|
||||
// - Introduction, links and more at the top of imgui.cpp
|
||||
|
||||
#import <Cocoa/Cocoa.h>
|
||||
|
||||
#include "imgui.h"
|
||||
#include "imgui_impl_cpu.h"
|
||||
#include "imgui_impl_osx.h"
|
||||
#include <chrono>
|
||||
#include <cmath>
|
||||
#include <string.h>
|
||||
|
||||
struct ExampleTimingHistory
|
||||
{
|
||||
double Samples[120];
|
||||
int Count;
|
||||
int Offset;
|
||||
|
||||
ExampleTimingHistory() : Count(0), Offset(0) { memset(Samples, 0, sizeof(Samples)); }
|
||||
|
||||
void AddSample(double value_ms)
|
||||
{
|
||||
Samples[Offset] = value_ms;
|
||||
Offset = (Offset + 1) % IM_ARRAYSIZE(Samples);
|
||||
if (Count < IM_ARRAYSIZE(Samples))
|
||||
Count++;
|
||||
}
|
||||
|
||||
double GetAverageMs() const
|
||||
{
|
||||
if (Count == 0)
|
||||
return 0.0;
|
||||
double total = 0.0;
|
||||
for (int i = 0; i < Count; i++)
|
||||
total += Samples[i];
|
||||
return total / (double)Count;
|
||||
}
|
||||
};
|
||||
|
||||
struct ExampleFramebuffer
|
||||
{
|
||||
ImVector<unsigned char> Storage;
|
||||
ImGui_ImplCPU_Framebuffer CPU;
|
||||
CGColorSpaceRef ColorSpace;
|
||||
CGDataProviderRef DataProvider;
|
||||
CGImageRef Image;
|
||||
|
||||
ExampleFramebuffer() : ColorSpace(nullptr), DataProvider(nullptr), Image(nullptr)
|
||||
{
|
||||
CPU.Pixels = nullptr;
|
||||
CPU.Width = 0;
|
||||
CPU.Height = 0;
|
||||
CPU.Pitch = 0;
|
||||
CPU.Format = nullptr;
|
||||
}
|
||||
};
|
||||
|
||||
static double ExampleGetTimeMs()
|
||||
{
|
||||
typedef std::chrono::steady_clock Clock;
|
||||
return std::chrono::duration<double, std::milli>(Clock::now().time_since_epoch()).count();
|
||||
}
|
||||
|
||||
static void DestroyFramebuffer(ExampleFramebuffer* framebuffer)
|
||||
{
|
||||
if (framebuffer->Image != nullptr)
|
||||
{
|
||||
CGImageRelease(framebuffer->Image);
|
||||
framebuffer->Image = nullptr;
|
||||
}
|
||||
if (framebuffer->DataProvider != nullptr)
|
||||
{
|
||||
CGDataProviderRelease(framebuffer->DataProvider);
|
||||
framebuffer->DataProvider = nullptr;
|
||||
}
|
||||
if (framebuffer->ColorSpace != nullptr)
|
||||
{
|
||||
CGColorSpaceRelease(framebuffer->ColorSpace);
|
||||
framebuffer->ColorSpace = nullptr;
|
||||
}
|
||||
|
||||
framebuffer->CPU.Pixels = nullptr;
|
||||
framebuffer->CPU.Width = 0;
|
||||
framebuffer->CPU.Height = 0;
|
||||
framebuffer->CPU.Pitch = 0;
|
||||
framebuffer->Storage.clear();
|
||||
}
|
||||
|
||||
static ImU32 PackBGRA(unsigned char r, unsigned char g, unsigned char b, unsigned char a)
|
||||
{
|
||||
#if defined(__BYTE_ORDER__) && (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)
|
||||
return ((ImU32)b << 24) | ((ImU32)g << 16) | ((ImU32)r << 8) | (ImU32)a;
|
||||
#else
|
||||
return (ImU32)b | ((ImU32)g << 8) | ((ImU32)r << 16) | ((ImU32)a << 24);
|
||||
#endif
|
||||
}
|
||||
|
||||
static bool RecreateFramebuffer(ExampleFramebuffer* framebuffer, int width, int height)
|
||||
{
|
||||
DestroyFramebuffer(framebuffer);
|
||||
|
||||
framebuffer->Storage.resize(width * height * 4);
|
||||
framebuffer->CPU.Pixels = framebuffer->Storage.Data;
|
||||
framebuffer->CPU.Width = width;
|
||||
framebuffer->CPU.Height = height;
|
||||
framebuffer->CPU.Pitch = width * 4;
|
||||
framebuffer->CPU.Format = ImGui_ImplCPU_GetBuiltinPixelFormat(ImGui_ImplCPU_BuiltinFormat_BGRA8888);
|
||||
if (framebuffer->CPU.Pixels == nullptr)
|
||||
return false;
|
||||
|
||||
framebuffer->ColorSpace = CGColorSpaceCreateDeviceRGB();
|
||||
if (framebuffer->ColorSpace == nullptr)
|
||||
{
|
||||
DestroyFramebuffer(framebuffer);
|
||||
return false;
|
||||
}
|
||||
|
||||
framebuffer->DataProvider = CGDataProviderCreateWithData(nullptr, framebuffer->CPU.Pixels, (size_t)framebuffer->CPU.Pitch * (size_t)framebuffer->CPU.Height, nullptr);
|
||||
if (framebuffer->DataProvider == nullptr)
|
||||
{
|
||||
DestroyFramebuffer(framebuffer);
|
||||
return false;
|
||||
}
|
||||
|
||||
framebuffer->Image = CGImageCreate((size_t)framebuffer->CPU.Width, (size_t)framebuffer->CPU.Height, 8, 32, (size_t)framebuffer->CPU.Pitch, framebuffer->ColorSpace, kCGBitmapByteOrder32Little | kCGImageAlphaNoneSkipFirst, framebuffer->DataProvider, nullptr, false, kCGRenderingIntentDefault);
|
||||
if (framebuffer->Image == nullptr)
|
||||
{
|
||||
DestroyFramebuffer(framebuffer);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void ClearFramebuffer(ImGui_ImplCPU_Framebuffer* framebuffer, unsigned char r, unsigned char g, unsigned char b, unsigned char a)
|
||||
{
|
||||
const ImU32 pixel = PackBGRA(r, g, b, a);
|
||||
for (int y = 0; y < framebuffer->Height; y++)
|
||||
{
|
||||
ImU32* dst = (ImU32*)(void*)(framebuffer->Pixels + (size_t)y * (size_t)framebuffer->Pitch);
|
||||
for (int x = 0; x < framebuffer->Width; x++)
|
||||
dst[x] = pixel;
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------------
|
||||
// AppView
|
||||
//-----------------------------------------------------------------------------------
|
||||
|
||||
@interface AppView : NSView
|
||||
- (void)shutdownImGui;
|
||||
@end
|
||||
|
||||
@implementation AppView
|
||||
{
|
||||
ExampleFramebuffer _framebuffer;
|
||||
ExampleTimingHistory _rasterTimes;
|
||||
ExampleTimingHistory _presentTimes;
|
||||
BOOL _imguiInitialized;
|
||||
BOOL _frameScheduled;
|
||||
}
|
||||
|
||||
- (instancetype)initWithFrame:(NSRect)frame
|
||||
{
|
||||
self = [super initWithFrame:frame];
|
||||
return self;
|
||||
}
|
||||
|
||||
- (BOOL)isFlipped
|
||||
{
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (void)viewDidMoveToWindow
|
||||
{
|
||||
[super viewDidMoveToWindow];
|
||||
if (self.window != nil && !_imguiInitialized)
|
||||
[self initializeImGui];
|
||||
}
|
||||
|
||||
- (void)dealloc
|
||||
{
|
||||
[self shutdownImGui];
|
||||
}
|
||||
|
||||
- (void)initializeImGui
|
||||
{
|
||||
IMGUI_CHECKVERSION();
|
||||
ImGui::CreateContext();
|
||||
ImGuiIO& io = ImGui::GetIO(); (void)io;
|
||||
io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls
|
||||
io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad; // Enable Gamepad Controls
|
||||
|
||||
ImGui::StyleColorsDark();
|
||||
|
||||
ImGui_ImplOSX_Init(self);
|
||||
ImGui_ImplCPU_Init();
|
||||
|
||||
_imguiInitialized = YES;
|
||||
[self scheduleNextFrameAfter:0.0];
|
||||
}
|
||||
|
||||
- (void)shutdownImGui
|
||||
{
|
||||
if (!_imguiInitialized)
|
||||
return;
|
||||
|
||||
DestroyFramebuffer(&_framebuffer);
|
||||
ImGui_ImplCPU_Shutdown();
|
||||
ImGui_ImplOSX_Shutdown();
|
||||
ImGui::DestroyContext();
|
||||
_imguiInitialized = NO;
|
||||
}
|
||||
|
||||
// Queue the next draw on the main loop instead of pacing to display refresh.
|
||||
- (void)scheduleNextFrameAfter:(double)delay_seconds
|
||||
{
|
||||
if (_frameScheduled)
|
||||
return;
|
||||
_frameScheduled = YES;
|
||||
dispatch_time_t when = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delay_seconds * (double)NSEC_PER_SEC));
|
||||
dispatch_after(when, dispatch_get_main_queue(), ^{
|
||||
self->_frameScheduled = NO;
|
||||
[self setNeedsDisplay:YES];
|
||||
});
|
||||
}
|
||||
|
||||
- (void)renderFrame
|
||||
{
|
||||
if (!_imguiInitialized)
|
||||
return;
|
||||
|
||||
if (self.window == nil || [self.window isMiniaturized])
|
||||
{
|
||||
[self scheduleNextFrameAfter:0.01];
|
||||
return;
|
||||
}
|
||||
|
||||
const CGFloat scale = self.window.backingScaleFactor > 0.0 ? self.window.backingScaleFactor : 1.0;
|
||||
const int logical_w = (int)llround(self.bounds.size.width);
|
||||
const int logical_h = (int)llround(self.bounds.size.height);
|
||||
const int framebuffer_w = (int)llround(self.bounds.size.width * scale);
|
||||
const int framebuffer_h = (int)llround(self.bounds.size.height * scale);
|
||||
if (framebuffer_w <= 0 || framebuffer_h <= 0)
|
||||
{
|
||||
[self scheduleNextFrameAfter:0.01];
|
||||
return;
|
||||
}
|
||||
|
||||
if (_framebuffer.CPU.Width != framebuffer_w || _framebuffer.CPU.Height != framebuffer_h)
|
||||
if (!RecreateFramebuffer(&_framebuffer, framebuffer_w, framebuffer_h))
|
||||
return;
|
||||
|
||||
// Start the Dear ImGui frame
|
||||
ImGui_ImplCPU_NewFrame();
|
||||
ImGui_ImplOSX_NewFrame(self);
|
||||
ImGui::NewFrame();
|
||||
|
||||
// Our state
|
||||
static bool show_demo_window = true;
|
||||
static bool show_another_window = false;
|
||||
static ImVec4 clear_color = ImVec4(0.45f, 0.55f, 0.60f, 1.00f);
|
||||
|
||||
// 1. Show the big demo window
|
||||
if (show_demo_window)
|
||||
ImGui::ShowDemoWindow(&show_demo_window);
|
||||
|
||||
// 2. Show a simple window that we create ourselves.
|
||||
{
|
||||
static float f = 0.0f;
|
||||
static int counter = 0;
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
|
||||
ImGui::Begin("Hello, world!");
|
||||
|
||||
ImGui::Text("This is some useful text.");
|
||||
ImGui::Checkbox("Demo Window", &show_demo_window);
|
||||
ImGui::Checkbox("Another Window", &show_another_window);
|
||||
|
||||
ImGui::SliderFloat("float", &f, 0.0f, 1.0f);
|
||||
ImGui::ColorEdit3("clear color", (float*)&clear_color);
|
||||
|
||||
if (ImGui::Button("Button"))
|
||||
counter++;
|
||||
ImGui::SameLine();
|
||||
ImGui::Text("counter = %d", counter);
|
||||
|
||||
ImGui::Text("Raster %.3f ms | Present %.3f ms", _rasterTimes.GetAverageMs(), _presentTimes.GetAverageMs());
|
||||
ImGui::Text("Window %d x %d | Framebuffer %d x %d (scale %.2f)", logical_w, logical_h, framebuffer_w, framebuffer_h, scale);
|
||||
ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / io.Framerate, io.Framerate);
|
||||
ImGui::End();
|
||||
}
|
||||
|
||||
// 3. Show another simple window.
|
||||
if (show_another_window)
|
||||
{
|
||||
ImGui::Begin("Another Window", &show_another_window);
|
||||
ImGui::Text("Hello from another window!");
|
||||
if (ImGui::Button("Close Me"))
|
||||
show_another_window = false;
|
||||
ImGui::End();
|
||||
}
|
||||
|
||||
// Rendering
|
||||
ImGui::Render();
|
||||
const double raster_start_ms = ExampleGetTimeMs();
|
||||
ClearFramebuffer(&_framebuffer.CPU,
|
||||
(unsigned char)(clear_color.x * 255),
|
||||
(unsigned char)(clear_color.y * 255),
|
||||
(unsigned char)(clear_color.z * 255),
|
||||
(unsigned char)(clear_color.w * 255));
|
||||
ImGui_ImplCPU_RenderDrawData(ImGui::GetDrawData(), &_framebuffer.CPU);
|
||||
_rasterTimes.AddSample(ExampleGetTimeMs() - raster_start_ms);
|
||||
}
|
||||
|
||||
- (void)drawRect:(NSRect)dirtyRect
|
||||
{
|
||||
IM_UNUSED(dirtyRect);
|
||||
|
||||
[self renderFrame];
|
||||
|
||||
if (_framebuffer.Image != nullptr)
|
||||
{
|
||||
CGContextRef context = NSGraphicsContext.currentContext.CGContext;
|
||||
// CGImage draws with a bottom-up raster convention here, while the CPU framebuffer is top-down.
|
||||
const double present_start_ms = ExampleGetTimeMs();
|
||||
CGContextSaveGState(context);
|
||||
CGContextTranslateCTM(context, 0.0, self.bounds.size.height);
|
||||
CGContextScaleCTM(context, 1.0, -1.0);
|
||||
CGContextDrawImage(context, CGRectMake(0.0, 0.0, self.bounds.size.width, self.bounds.size.height), _framebuffer.Image);
|
||||
CGContextRestoreGState(context);
|
||||
_presentTimes.AddSample(ExampleGetTimeMs() - present_start_ms);
|
||||
}
|
||||
|
||||
[self scheduleNextFrameAfter:0.0];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
//-----------------------------------------------------------------------------------
|
||||
// AppDelegate
|
||||
//-----------------------------------------------------------------------------------
|
||||
|
||||
@interface AppDelegate : NSObject <NSApplicationDelegate>
|
||||
@property (nonatomic, readonly) NSWindow* window;
|
||||
@property (nonatomic, readonly) AppView* view;
|
||||
@end
|
||||
|
||||
@implementation AppDelegate
|
||||
{
|
||||
NSWindow* _window;
|
||||
AppView* _view;
|
||||
}
|
||||
|
||||
@synthesize window = _window;
|
||||
@synthesize view = _view;
|
||||
|
||||
- (BOOL)applicationShouldTerminateAfterLastWindowClosed:(NSApplication*)application
|
||||
{
|
||||
IM_UNUSED(application);
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (void)setupMenu
|
||||
{
|
||||
NSMenu* main_menu_bar = [[NSMenu alloc] init];
|
||||
NSMenu* app_menu = [[NSMenu alloc] initWithTitle:@"Dear ImGui macOS+CPU Example"];
|
||||
NSMenuItem* menu_item = [app_menu addItemWithTitle:@"Quit Dear ImGui macOS+CPU Example" action:@selector(terminate:) keyEquivalent:@"q"];
|
||||
[menu_item setKeyEquivalentModifierMask:NSEventModifierFlagCommand];
|
||||
|
||||
menu_item = [[NSMenuItem alloc] init];
|
||||
[menu_item setSubmenu:app_menu];
|
||||
[main_menu_bar addItem:menu_item];
|
||||
[NSApp setMainMenu:main_menu_bar];
|
||||
}
|
||||
|
||||
- (void)applicationDidFinishLaunching:(NSNotification*)notification
|
||||
{
|
||||
IM_UNUSED(notification);
|
||||
|
||||
[NSApp setActivationPolicy:NSApplicationActivationPolicyRegular];
|
||||
[self setupMenu];
|
||||
|
||||
NSRect view_rect = NSMakeRect(100.0, 100.0, 1280.0, 720.0);
|
||||
_window = [[NSWindow alloc] initWithContentRect:view_rect styleMask:NSWindowStyleMaskTitled | NSWindowStyleMaskMiniaturizable | NSWindowStyleMaskResizable | NSWindowStyleMaskClosable backing:NSBackingStoreBuffered defer:NO];
|
||||
[_window setTitle:@"Dear ImGui macOS+CPU Example"];
|
||||
[_window setAcceptsMouseMovedEvents:YES];
|
||||
[_window setOpaque:YES];
|
||||
|
||||
_view = [[AppView alloc] initWithFrame:_window.contentView.bounds];
|
||||
[_view setAutoresizingMask:NSViewWidthSizable | NSViewHeightSizable];
|
||||
[_window setContentView:_view];
|
||||
[_window makeKeyAndOrderFront:NSApp];
|
||||
[NSApp activateIgnoringOtherApps:YES];
|
||||
}
|
||||
|
||||
- (void)applicationWillTerminate:(NSNotification*)notification
|
||||
{
|
||||
IM_UNUSED(notification);
|
||||
[_view shutdownImGui];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
IM_UNUSED(argc);
|
||||
IM_UNUSED(argv);
|
||||
|
||||
@autoreleasepool
|
||||
{
|
||||
NSApplication* application = [NSApplication sharedApplication];
|
||||
AppDelegate* delegate = [AppDelegate new];
|
||||
[application setDelegate:delegate];
|
||||
[application run];
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
#
|
||||
# Cross Platform Makefile (example_sdl2_cpu)
|
||||
# Compatible with MSYS2/MINGW, Linux and macOS
|
||||
#
|
||||
# You will need SDL2 (http://www.libsdl.org):
|
||||
# Linux: apt-get install libsdl2-dev
|
||||
# macOS: brew install sdl2
|
||||
# MSYS2: pacman -S mingw-w64-i686-SDL2
|
||||
#
|
||||
|
||||
EXE = example_sdl2_cpu
|
||||
IMGUI_DIR = ../..
|
||||
SOURCES = main.cpp
|
||||
SOURCES += $(IMGUI_DIR)/imgui.cpp $(IMGUI_DIR)/imgui_demo.cpp $(IMGUI_DIR)/imgui_draw.cpp $(IMGUI_DIR)/imgui_tables.cpp $(IMGUI_DIR)/imgui_widgets.cpp
|
||||
SOURCES += $(IMGUI_DIR)/backends/imgui_impl_sdl2.cpp $(IMGUI_DIR)/backends/imgui_impl_cpu.cpp
|
||||
OBJS = $(addsuffix .o, $(basename $(notdir $(SOURCES))))
|
||||
UNAME_S := $(shell uname -s)
|
||||
SDL2_CONFIG ?= $(shell if command -v sdl2-config >/dev/null 2>&1; then command -v sdl2-config; elif [ -x /opt/homebrew/bin/sdl2-config ]; then echo /opt/homebrew/bin/sdl2-config; elif [ -x /usr/local/bin/sdl2-config ]; then echo /usr/local/bin/sdl2-config; else echo sdl2-config; fi)
|
||||
|
||||
CXXFLAGS = -std=c++11 -I$(IMGUI_DIR) -I$(IMGUI_DIR)/backends
|
||||
OPTFLAGS ?= -O2
|
||||
CXXFLAGS += -g $(OPTFLAGS) -Wall -Wformat
|
||||
LIBS =
|
||||
|
||||
##---------------------------------------------------------------------
|
||||
## BUILD FLAGS PER PLATFORM
|
||||
##---------------------------------------------------------------------
|
||||
|
||||
ifeq ($(UNAME_S), Linux) #LINUX
|
||||
ECHO_MESSAGE = "Linux"
|
||||
LIBS += `$(SDL2_CONFIG) --libs`
|
||||
|
||||
CXXFLAGS += `$(SDL2_CONFIG) --cflags`
|
||||
CFLAGS = $(CXXFLAGS)
|
||||
endif
|
||||
|
||||
ifeq ($(UNAME_S), Darwin) #APPLE
|
||||
ECHO_MESSAGE = "Mac OS X"
|
||||
LIBS += `$(SDL2_CONFIG) --libs`
|
||||
CXXFLAGS += `$(SDL2_CONFIG) --cflags`
|
||||
CXXFLAGS += -I/usr/local/include -I/opt/local/include
|
||||
CFLAGS = $(CXXFLAGS)
|
||||
endif
|
||||
|
||||
ifeq ($(OS), Windows_NT)
|
||||
ECHO_MESSAGE = "MinGW"
|
||||
LIBS += -lgdi32 `pkg-config --static --libs sdl2`
|
||||
|
||||
CXXFLAGS += `pkg-config --cflags sdl2`
|
||||
CFLAGS = $(CXXFLAGS)
|
||||
endif
|
||||
|
||||
##---------------------------------------------------------------------
|
||||
## BUILD RULES
|
||||
##---------------------------------------------------------------------
|
||||
|
||||
%.o:%.cpp
|
||||
$(CXX) $(CXXFLAGS) -c -o $@ $<
|
||||
|
||||
%.o:$(IMGUI_DIR)/%.cpp
|
||||
$(CXX) $(CXXFLAGS) -c -o $@ $<
|
||||
|
||||
%.o:$(IMGUI_DIR)/backends/%.cpp
|
||||
$(CXX) $(CXXFLAGS) -c -o $@ $<
|
||||
|
||||
all: $(EXE)
|
||||
@echo Build complete for $(ECHO_MESSAGE)
|
||||
|
||||
$(EXE): $(OBJS)
|
||||
$(CXX) -o $@ $^ $(CXXFLAGS) $(LIBS)
|
||||
|
||||
clean:
|
||||
rm -f $(EXE) $(OBJS)
|
||||
@@ -0,0 +1,54 @@
|
||||
CC = emcc
|
||||
CXX = em++
|
||||
WEB_DIR = web
|
||||
EXE = $(WEB_DIR)/index.html
|
||||
IMGUI_DIR = ../..
|
||||
SOURCES = main.cpp
|
||||
SOURCES += $(IMGUI_DIR)/imgui.cpp $(IMGUI_DIR)/imgui_demo.cpp $(IMGUI_DIR)/imgui_draw.cpp $(IMGUI_DIR)/imgui_tables.cpp $(IMGUI_DIR)/imgui_widgets.cpp
|
||||
SOURCES += $(IMGUI_DIR)/backends/imgui_impl_sdl2.cpp $(IMGUI_DIR)/backends/imgui_impl_cpu.cpp
|
||||
OBJS = $(addprefix em_,$(addsuffix .o, $(basename $(notdir $(SOURCES)))))
|
||||
CPPFLAGS =
|
||||
LDFLAGS =
|
||||
EMS =
|
||||
|
||||
EMS += -s USE_SDL=2
|
||||
EMS += -s DISABLE_EXCEPTION_CATCHING=1
|
||||
LDFLAGS += -s WASM=1 -s ALLOW_MEMORY_GROWTH=1 -s NO_EXIT_RUNTIME=0 -s ASSERTIONS=1
|
||||
|
||||
USE_FILE_SYSTEM ?= 0
|
||||
ifeq ($(USE_FILE_SYSTEM), 0)
|
||||
LDFLAGS += -s NO_FILESYSTEM=1
|
||||
CPPFLAGS += -DIMGUI_DISABLE_FILE_FUNCTIONS
|
||||
endif
|
||||
ifeq ($(USE_FILE_SYSTEM), 1)
|
||||
LDFLAGS += --no-heap-copy --preload-file ../../misc/fonts@/fonts
|
||||
endif
|
||||
|
||||
CPPFLAGS += -I$(IMGUI_DIR) -I$(IMGUI_DIR)/backends
|
||||
CPPFLAGS += -Wall -Wformat -O2 $(EMS)
|
||||
LDFLAGS += --shell-file ../libs/emscripten/shell_minimal.html
|
||||
LDFLAGS += $(EMS)
|
||||
|
||||
em_%.o:%.cpp
|
||||
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $<
|
||||
|
||||
em_%.o:$(IMGUI_DIR)/%.cpp
|
||||
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $<
|
||||
|
||||
em_%.o:$(IMGUI_DIR)/backends/%.cpp
|
||||
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $<
|
||||
|
||||
all: $(EXE)
|
||||
@echo Build complete for $(EXE)
|
||||
|
||||
$(WEB_DIR):
|
||||
mkdir $@
|
||||
|
||||
serve: all
|
||||
python3 -m http.server -d $(WEB_DIR)
|
||||
|
||||
$(EXE): $(OBJS) $(WEB_DIR)
|
||||
$(CXX) -o $@ $(OBJS) $(LDFLAGS)
|
||||
|
||||
clean:
|
||||
rm -rf $(OBJS) $(WEB_DIR)
|
||||
@@ -0,0 +1,47 @@
|
||||
# How to Build
|
||||
|
||||
## Windows with Visual Studio's IDE
|
||||
|
||||
Use the provided project file (`example_sdl2_cpu.vcxproj`) or open `imgui_examples.sln`.
|
||||
|
||||
## Windows with Visual Studio's CLI
|
||||
|
||||
Use `build_win32.bat` or directly:
|
||||
```
|
||||
set SDL2_DIR=path_to_your_sdl2_folder
|
||||
cl /Zi /MD /utf-8 /I.. /I..\.. /I%SDL2_DIR%\include main.cpp ..\..\backends\imgui_impl_sdl2.cpp ..\..\backends\imgui_impl_cpu.cpp ..\..\imgui*.cpp /FeDebug/example_sdl2_cpu.exe /FoDebug/ /link /libpath:%SDL2_DIR%\lib\x86 SDL2.lib SDL2main.lib /subsystem:console
|
||||
# ^^ include paths ^^ source files ^^ output exe ^^ output dir ^^ libraries
|
||||
# or for 64-bit:
|
||||
cl /Zi /MD /utf-8 /I.. /I..\.. /I%SDL2_DIR%\include main.cpp ..\..\backends\imgui_impl_sdl2.cpp ..\..\backends\imgui_impl_cpu.cpp ..\..\imgui*.cpp /FeDebug/example_sdl2_cpu.exe /FoDebug/ /link /libpath:%SDL2_DIR%\lib\x64 SDL2.lib SDL2main.lib /subsystem:console
|
||||
```
|
||||
|
||||
## Linux and similar Unixes
|
||||
|
||||
Use the provided `Makefile` or directly:
|
||||
```
|
||||
c++ `sdl2-config --cflags` -I .. -I ../.. -I ../../backends \
|
||||
main.cpp ../../backends/imgui_impl_sdl2.cpp ../../backends/imgui_impl_cpu.cpp ../../imgui*.cpp \
|
||||
`sdl2-config --libs`
|
||||
```
|
||||
|
||||
## macOS
|
||||
|
||||
Use the provided `Makefile` or directly:
|
||||
```
|
||||
brew install sdl2
|
||||
c++ `sdl2-config --cflags` -I .. -I ../.. -I ../../backends \
|
||||
main.cpp ../../backends/imgui_impl_sdl2.cpp ../../backends/imgui_impl_cpu.cpp ../../imgui*.cpp \
|
||||
`sdl2-config --libs`
|
||||
```
|
||||
|
||||
## Emscripten
|
||||
|
||||
Use `Makefile.emscripten`:
|
||||
```sh
|
||||
source /path/to/emsdk/emsdk_env.sh
|
||||
make -f Makefile.emscripten
|
||||
```
|
||||
|
||||
This makes `web/index.html`, `web/index.js`, and `web/index.wasm`.
|
||||
|
||||
This example keeps Dear ImGui on the CPU and allocates its framebuffer in the active SDL window surface format, rather than forcing a fixed RGBA32 output format.
|
||||
@@ -0,0 +1,8 @@
|
||||
@REM Build for Visual Studio compiler. Run your copy of vcvars32.bat or vcvarsall.bat to setup command-line compiler.
|
||||
@set OUT_DIR=Debug
|
||||
@set OUT_EXE=example_sdl2_cpu
|
||||
@set INCLUDES=/I..\.. /I..\..\backends /I%SDL2_DIR%\include
|
||||
@set SOURCES=main.cpp ..\..\backends\imgui_impl_sdl2.cpp ..\..\backends\imgui_impl_cpu.cpp ..\..\imgui*.cpp
|
||||
@set LIBS=/LIBPATH:%SDL2_DIR%\lib\x86 SDL2.lib SDL2main.lib
|
||||
mkdir %OUT_DIR%
|
||||
cl /nologo /Zi /O2 /MD /utf-8 %INCLUDES% %SOURCES% /Fe%OUT_DIR%/%OUT_EXE%.exe /Fo%OUT_DIR%/ /link %LIBS% /subsystem:console
|
||||
Executable
BIN
Binary file not shown.
@@ -0,0 +1,187 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Debug|Win32">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Debug|x64">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|Win32">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|x64">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<ProjectGuid>{1E9DB182-9BF1-4C7D-8930-85ACAEAC2458}</ProjectGuid>
|
||||
<RootNamespace>example_sdl2_cpu</RootNamespace>
|
||||
<WindowsTargetPlatformVersion>8.1</WindowsTargetPlatformVersion>
|
||||
<ProjectName>example_sdl2_cpu</ProjectName>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
<PlatformToolset>v140</PlatformToolset>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
<PlatformToolset>v140</PlatformToolset>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
<PlatformToolset>v140</PlatformToolset>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
<PlatformToolset>v140</PlatformToolset>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<OutDir>$(ProjectDir)$(Configuration)\</OutDir>
|
||||
<IntDir>$(ProjectDir)$(Configuration)\</IntDir>
|
||||
<IncludePath>$(IncludePath)</IncludePath>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<OutDir>$(ProjectDir)$(Configuration)\</OutDir>
|
||||
<IntDir>$(ProjectDir)$(Configuration)\</IntDir>
|
||||
<IncludePath>$(IncludePath)</IncludePath>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<OutDir>$(ProjectDir)$(Configuration)\</OutDir>
|
||||
<IntDir>$(ProjectDir)$(Configuration)\</IntDir>
|
||||
<IncludePath>$(IncludePath)</IncludePath>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<OutDir>$(ProjectDir)$(Configuration)\</OutDir>
|
||||
<IntDir>$(ProjectDir)$(Configuration)\</IntDir>
|
||||
<IncludePath>$(IncludePath)</IncludePath>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level4</WarningLevel>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<AdditionalIncludeDirectories>..\..;..\..\backends;%SDL2_DIR%\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<AdditionalOptions>/utf-8 %(AdditionalOptions)</AdditionalOptions>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<AdditionalLibraryDirectories>%SDL2_DIR%\lib\x86;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
<AdditionalDependencies>SDL2.lib;SDL2main.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<IgnoreSpecificDefaultLibraries>msvcrt.lib</IgnoreSpecificDefaultLibraries>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level4</WarningLevel>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<AdditionalIncludeDirectories>..\..;..\..\backends;%SDL2_DIR%\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<AdditionalOptions>/utf-8 %(AdditionalOptions)</AdditionalOptions>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<AdditionalLibraryDirectories>%SDL2_DIR%\lib\x64;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
<AdditionalDependencies>SDL2.lib;SDL2main.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<IgnoreSpecificDefaultLibraries>msvcrt.lib</IgnoreSpecificDefaultLibraries>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level4</WarningLevel>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<AdditionalIncludeDirectories>..\..;..\..\backends;%SDL2_DIR%\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<BufferSecurityCheck>false</BufferSecurityCheck>
|
||||
<AdditionalOptions>/utf-8 %(AdditionalOptions)</AdditionalOptions>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<AdditionalLibraryDirectories>%SDL2_DIR%\lib\x86;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
<AdditionalDependencies>SDL2.lib;SDL2main.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<IgnoreSpecificDefaultLibraries>
|
||||
</IgnoreSpecificDefaultLibraries>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level4</WarningLevel>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<AdditionalIncludeDirectories>..\..;..\..\backends;%SDL2_DIR%\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<BufferSecurityCheck>false</BufferSecurityCheck>
|
||||
<AdditionalOptions>/utf-8 %(AdditionalOptions)</AdditionalOptions>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<AdditionalLibraryDirectories>%SDL2_DIR%\lib\x64;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
<AdditionalDependencies>SDL2.lib;SDL2main.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<IgnoreSpecificDefaultLibraries>
|
||||
</IgnoreSpecificDefaultLibraries>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\..\imgui.cpp" />
|
||||
<ClCompile Include="..\..\imgui_demo.cpp" />
|
||||
<ClCompile Include="..\..\imgui_draw.cpp" />
|
||||
<ClCompile Include="..\..\imgui_tables.cpp" />
|
||||
<ClCompile Include="..\..\imgui_widgets.cpp" />
|
||||
<ClCompile Include="..\..\backends\imgui_impl_sdl2.cpp" />
|
||||
<ClCompile Include="..\..\backends\imgui_impl_cpu.cpp" />
|
||||
<ClCompile Include="main.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\..\imconfig.h" />
|
||||
<ClInclude Include="..\..\imgui.h" />
|
||||
<ClInclude Include="..\..\imgui_internal.h" />
|
||||
<ClInclude Include="..\..\backends\imgui_impl_sdl2.h" />
|
||||
<ClInclude Include="..\..\backends\imgui_impl_cpu.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="..\..\misc\debuggers\imgui.natstepfilter" />
|
||||
<None Include="..\..\misc\debuggers\imgui.natvis" />
|
||||
<None Include="..\README.txt" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
</Project>
|
||||
@@ -0,0 +1,64 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup>
|
||||
<Filter Include="imgui">
|
||||
<UniqueIdentifier>{20b90ce4-7fcb-4731-b9a0-075f875de82d}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="sources">
|
||||
<UniqueIdentifier>{f18ab499-84e1-499f-8eff-9754361e0e52}</UniqueIdentifier>
|
||||
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\..\imgui.cpp">
|
||||
<Filter>imgui</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\imgui_demo.cpp">
|
||||
<Filter>imgui</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\imgui_draw.cpp">
|
||||
<Filter>imgui</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="main.cpp">
|
||||
<Filter>sources</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\imgui_tables.cpp">
|
||||
<Filter>imgui</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\imgui_widgets.cpp">
|
||||
<Filter>imgui</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\backends\imgui_impl_sdl2.cpp">
|
||||
<Filter>sources</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\backends\imgui_impl_cpu.cpp">
|
||||
<Filter>sources</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\..\imconfig.h">
|
||||
<Filter>imgui</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\imgui.h">
|
||||
<Filter>imgui</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\imgui_internal.h">
|
||||
<Filter>imgui</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\backends\imgui_impl_cpu.h">
|
||||
<Filter>sources</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\backends\imgui_impl_sdl2.h">
|
||||
<Filter>sources</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="..\README.txt" />
|
||||
<None Include="..\..\misc\debuggers\imgui.natvis">
|
||||
<Filter>imgui</Filter>
|
||||
</None>
|
||||
<None Include="..\..\misc\debuggers\imgui.natstepfilter">
|
||||
<Filter>imgui</Filter>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
@@ -0,0 +1,321 @@
|
||||
// main.cpp
|
||||
// Example program using imgui_impl_cpu backend
|
||||
|
||||
#include "imgui.h"
|
||||
#include "imgui_impl_cpu.h"
|
||||
#include "imgui_impl_sdl2.h"
|
||||
#include <SDL.h>
|
||||
#include <chrono>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#ifdef __EMSCRIPTEN__
|
||||
#include "../libs/emscripten/emscripten_mainloop_stub.h"
|
||||
#endif
|
||||
|
||||
struct ExampleTimingHistory
|
||||
{
|
||||
double Samples[120];
|
||||
int Count;
|
||||
int Offset;
|
||||
|
||||
ExampleTimingHistory() : Count(0), Offset(0) { memset(Samples, 0, sizeof(Samples)); }
|
||||
|
||||
void AddSample(double value_ms)
|
||||
{
|
||||
Samples[Offset] = value_ms;
|
||||
Offset = (Offset + 1) % IM_ARRAYSIZE(Samples);
|
||||
if (Count < IM_ARRAYSIZE(Samples))
|
||||
Count++;
|
||||
}
|
||||
|
||||
double GetAverageMs() const
|
||||
{
|
||||
if (Count == 0)
|
||||
return 0.0;
|
||||
double total = 0.0;
|
||||
for (int i = 0; i < Count; i++)
|
||||
total += Samples[i];
|
||||
return total / (double)Count;
|
||||
}
|
||||
};
|
||||
|
||||
struct ExampleFramebuffer
|
||||
{
|
||||
ImVector<unsigned char> Storage;
|
||||
ImVector<ImU32> Palette;
|
||||
ImGui_ImplCPU_PixelFormat Format;
|
||||
ImGui_ImplCPU_Framebuffer CPU;
|
||||
SDL_Surface* Surface;
|
||||
Uint32 SDLFormat;
|
||||
|
||||
ExampleFramebuffer() { memset((void*)this, 0, sizeof(*this)); }
|
||||
};
|
||||
|
||||
static double ExampleGetTimeMs()
|
||||
{
|
||||
typedef std::chrono::steady_clock Clock;
|
||||
return std::chrono::duration<double, std::milli>(Clock::now().time_since_epoch()).count();
|
||||
}
|
||||
|
||||
static void InitCPUFormatFromSDL(ImGui_ImplCPU_PixelFormat* out, ImVector<ImU32>* out_palette, const SDL_PixelFormat* format)
|
||||
{
|
||||
memset(out, 0, sizeof(*out));
|
||||
out->BitsPerPixel = format->BitsPerPixel;
|
||||
out->BytesPerPixel = format->BytesPerPixel;
|
||||
out->Rmask = format->Rmask;
|
||||
out->Gmask = format->Gmask;
|
||||
out->Bmask = format->Bmask;
|
||||
out->Amask = format->Amask;
|
||||
out->Rshift = (ImU8)format->Rshift;
|
||||
out->Gshift = (ImU8)format->Gshift;
|
||||
out->Bshift = (ImU8)format->Bshift;
|
||||
out->Ashift = (ImU8)format->Ashift;
|
||||
out->Rloss = (ImU8)format->Rloss;
|
||||
out->Gloss = (ImU8)format->Gloss;
|
||||
out->Bloss = (ImU8)format->Bloss;
|
||||
out->Aloss = (ImU8)format->Aloss;
|
||||
out->Palette = nullptr;
|
||||
out->PaletteSize = 0;
|
||||
out->MapColorFn = nullptr;
|
||||
|
||||
out_palette->clear();
|
||||
if (format->palette != nullptr && format->palette->colors != nullptr && format->palette->ncolors > 0)
|
||||
{
|
||||
out_palette->resize(format->palette->ncolors);
|
||||
for (int i = 0; i < format->palette->ncolors; i++)
|
||||
{
|
||||
const SDL_Color& c = format->palette->colors[i];
|
||||
(*out_palette)[i] = IM_COL32(c.r, c.g, c.b, c.a);
|
||||
}
|
||||
out->Palette = out_palette->Data;
|
||||
out->PaletteSize = out_palette->Size;
|
||||
}
|
||||
}
|
||||
|
||||
static bool RecreateFramebuffer(ExampleFramebuffer* framebuffer, SDL_Surface* window_surface)
|
||||
{
|
||||
if (framebuffer->Surface != nullptr)
|
||||
{
|
||||
SDL_FreeSurface(framebuffer->Surface);
|
||||
framebuffer->Surface = nullptr;
|
||||
}
|
||||
|
||||
const int width = window_surface->w;
|
||||
const int height = window_surface->h;
|
||||
const int bytes_per_pixel = window_surface->format->BytesPerPixel;
|
||||
if (width <= 0 || height <= 0 || bytes_per_pixel <= 0)
|
||||
return false;
|
||||
|
||||
InitCPUFormatFromSDL(&framebuffer->Format, &framebuffer->Palette, window_surface->format);
|
||||
framebuffer->Storage.resize(width * height * bytes_per_pixel);
|
||||
framebuffer->CPU.Pixels = framebuffer->Storage.Data;
|
||||
framebuffer->CPU.Width = width;
|
||||
framebuffer->CPU.Height = height;
|
||||
framebuffer->CPU.Pitch = width * bytes_per_pixel;
|
||||
framebuffer->CPU.Format = &framebuffer->Format;
|
||||
framebuffer->SDLFormat = window_surface->format->format;
|
||||
framebuffer->Surface = SDL_CreateRGBSurfaceWithFormatFrom(framebuffer->CPU.Pixels, width, height, window_surface->format->BitsPerPixel, framebuffer->CPU.Pitch, window_surface->format->format);
|
||||
return framebuffer->Surface != nullptr;
|
||||
}
|
||||
|
||||
int main(int, char**)
|
||||
{
|
||||
// Setup SDL
|
||||
if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER | SDL_INIT_GAMECONTROLLER) != 0)
|
||||
{
|
||||
printf("Error: %s\n", SDL_GetError());
|
||||
return -1;
|
||||
}
|
||||
|
||||
// From 2.0.18: Enable native IME.
|
||||
#ifdef SDL_HINT_IME_SHOW_UI
|
||||
SDL_SetHint(SDL_HINT_IME_SHOW_UI, "1");
|
||||
#endif
|
||||
|
||||
// Create window
|
||||
float main_scale = ImGui_ImplSDL2_GetContentScaleForDisplay(0);
|
||||
SDL_WindowFlags window_flags = (SDL_WindowFlags)(SDL_WINDOW_RESIZABLE | SDL_WINDOW_ALLOW_HIGHDPI | SDL_WINDOW_SHOWN);
|
||||
SDL_Window* window = SDL_CreateWindow("Dear ImGui SDL2+CPU Example",
|
||||
SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED,
|
||||
(int)(1280 * main_scale), (int)(720 * main_scale), window_flags);
|
||||
if (!window)
|
||||
{
|
||||
printf("Error creating window: %s\n", SDL_GetError());
|
||||
return -1;
|
||||
}
|
||||
|
||||
SDL_Surface* window_surface = SDL_GetWindowSurface(window);
|
||||
if (!window_surface)
|
||||
{
|
||||
printf("Error getting window surface: %s\n", SDL_GetError());
|
||||
return -1;
|
||||
}
|
||||
|
||||
int win_w = window_surface->w;
|
||||
int win_h = window_surface->h;
|
||||
ExampleFramebuffer framebuffer;
|
||||
if (!RecreateFramebuffer(&framebuffer, window_surface))
|
||||
{
|
||||
printf("Error creating framebuffer: %s\n", SDL_GetError());
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Setup Dear ImGui context
|
||||
IMGUI_CHECKVERSION();
|
||||
ImGui::CreateContext();
|
||||
ImGuiIO& io = ImGui::GetIO(); (void)io;
|
||||
io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls
|
||||
io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad; // Enable Gamepad Controls
|
||||
#ifdef __EMSCRIPTEN__
|
||||
io.IniFilename = nullptr;
|
||||
#endif
|
||||
|
||||
// Setup Dear ImGui style
|
||||
ImGui::StyleColorsDark();
|
||||
|
||||
// Setup scaling
|
||||
ImGuiStyle& style = ImGui::GetStyle();
|
||||
style.ScaleAllSizes(main_scale); // Bake a fixed style scale.
|
||||
style.FontScaleDpi = main_scale;
|
||||
|
||||
// Setup Platform/Renderer backends
|
||||
ImGui_ImplSDL2_InitForOther(window);
|
||||
ImGui_ImplSDL2_SetGamepadMode(ImGui_ImplSDL2_GamepadMode_AutoFirst, nullptr, 0);
|
||||
ImGui_ImplCPU_Init();
|
||||
|
||||
// Our state
|
||||
bool show_demo_window = true;
|
||||
bool show_another_window = false;
|
||||
ImVec4 clear_color = ImVec4(0.45f, 0.55f, 0.60f, 1.00f);
|
||||
ExampleTimingHistory raster_times;
|
||||
ExampleTimingHistory present_times;
|
||||
|
||||
// Main loop
|
||||
bool done = false;
|
||||
#ifdef __EMSCRIPTEN__
|
||||
EMSCRIPTEN_MAINLOOP_BEGIN
|
||||
#else
|
||||
while (!done)
|
||||
#endif
|
||||
{
|
||||
// Poll and handle events (inputs, window resize, etc.)
|
||||
SDL_Event event;
|
||||
while (SDL_PollEvent(&event))
|
||||
{
|
||||
ImGui_ImplSDL2_ProcessEvent(&event);
|
||||
if (event.type == SDL_QUIT)
|
||||
done = true;
|
||||
|
||||
if (event.type == SDL_WINDOWEVENT)
|
||||
{
|
||||
if (event.window.event == SDL_WINDOWEVENT_CLOSE && event.window.windowID == SDL_GetWindowID(window))
|
||||
done = true;
|
||||
|
||||
if (event.window.event == SDL_WINDOWEVENT_SIZE_CHANGED || event.window.event == SDL_WINDOWEVENT_RESIZED)
|
||||
{
|
||||
// Recreate framebuffer at new size
|
||||
window_surface = SDL_GetWindowSurface(window);
|
||||
int new_w = window_surface->w;
|
||||
int new_h = window_surface->h;
|
||||
if (new_w != win_w || new_h != win_h || window_surface->format->format != framebuffer.SDLFormat)
|
||||
{
|
||||
if (!RecreateFramebuffer(&framebuffer, window_surface))
|
||||
{
|
||||
printf("Error creating framebuffer after resize: %s\n", SDL_GetError());
|
||||
return -1;
|
||||
}
|
||||
win_w = new_w;
|
||||
win_h = new_h;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Skip rendering when minimized to avoid busy-looping
|
||||
if (SDL_GetWindowFlags(window) & SDL_WINDOW_MINIMIZED)
|
||||
{
|
||||
SDL_Delay(10);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Start the Dear ImGui frame
|
||||
ImGui_ImplCPU_NewFrame();
|
||||
ImGui_ImplSDL2_NewFrame();
|
||||
ImGui::NewFrame();
|
||||
|
||||
int logical_w = 0;
|
||||
int logical_h = 0;
|
||||
SDL_GetWindowSize(window, &logical_w, &logical_h);
|
||||
|
||||
// 1. Show the big demo window
|
||||
if (show_demo_window)
|
||||
ImGui::ShowDemoWindow(&show_demo_window);
|
||||
|
||||
// 2. Show a simple window that we create ourselves. Mirror the SDL_Renderer example.
|
||||
{
|
||||
static float f = 0.0f;
|
||||
static int counter = 0;
|
||||
|
||||
ImGui::Begin("Hello, world!"); // Create a window called "Hello, world!" and append into it.
|
||||
|
||||
ImGui::Text("This is some useful text."); // Display some text
|
||||
ImGui::Checkbox("Demo Window", &show_demo_window); // Edit bools storing our window open/close state
|
||||
ImGui::Checkbox("Another Window", &show_another_window);
|
||||
|
||||
ImGui::SliderFloat("float", &f, 0.0f, 1.0f); // Edit 1 float using a slider from 0.0f to 1.0f
|
||||
ImGui::ColorEdit3("clear color", (float*)&clear_color); // Edit 3 floats representing a color
|
||||
|
||||
if (ImGui::Button("Button")) // Buttons return true when clicked
|
||||
counter++;
|
||||
ImGui::SameLine();
|
||||
ImGui::Text("counter = %d", counter);
|
||||
|
||||
ImGui::Text("Raster %.3f ms | Present %.3f ms", raster_times.GetAverageMs(), present_times.GetAverageMs());
|
||||
ImGui::Text("Window %d x %d | Framebuffer %d x %d", logical_w, logical_h, framebuffer.CPU.Width, framebuffer.CPU.Height);
|
||||
ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / io.Framerate, io.Framerate);
|
||||
ImGui::End();
|
||||
}
|
||||
|
||||
// 3. Show another simple window.
|
||||
if (show_another_window)
|
||||
{
|
||||
ImGui::Begin("Another Window", &show_another_window); // Pass a pointer to our bool variable (the window will have a closing button that will clear the bool when clicked)
|
||||
ImGui::Text("Hello from another window!");
|
||||
if (ImGui::Button("Close Me"))
|
||||
show_another_window = false;
|
||||
ImGui::End();
|
||||
}
|
||||
|
||||
// Rendering
|
||||
ImGui::Render();
|
||||
|
||||
const double raster_start_ms = ExampleGetTimeMs();
|
||||
SDL_FillRect(framebuffer.Surface, nullptr, SDL_MapRGBA(framebuffer.Surface->format,
|
||||
(Uint8)(clear_color.x * 255),
|
||||
(Uint8)(clear_color.y * 255),
|
||||
(Uint8)(clear_color.z * 255),
|
||||
(Uint8)(clear_color.w * 255)));
|
||||
|
||||
ImGui_ImplCPU_RenderDrawData(ImGui::GetDrawData(), &framebuffer.CPU);
|
||||
raster_times.AddSample(ExampleGetTimeMs() - raster_start_ms);
|
||||
|
||||
const double present_start_ms = ExampleGetTimeMs();
|
||||
SDL_BlitSurface(framebuffer.Surface, nullptr, window_surface, nullptr);
|
||||
SDL_UpdateWindowSurface(window);
|
||||
present_times.AddSample(ExampleGetTimeMs() - present_start_ms);
|
||||
}
|
||||
#ifdef __EMSCRIPTEN__
|
||||
EMSCRIPTEN_MAINLOOP_END;
|
||||
#endif
|
||||
|
||||
ImGui_ImplCPU_Shutdown();
|
||||
ImGui_ImplSDL2_Shutdown();
|
||||
ImGui::DestroyContext();
|
||||
|
||||
if (framebuffer.Surface != nullptr)
|
||||
SDL_FreeSurface(framebuffer.Surface);
|
||||
SDL_DestroyWindow(window);
|
||||
SDL_Quit();
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -5,11 +5,46 @@
|
||||
#include "imgui_impl_sdl2.h"
|
||||
#include "imgui_impl_sdlsurface2.h"
|
||||
#include <SDL.h>
|
||||
#include <chrono>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#ifdef __EMSCRIPTEN__
|
||||
#include "../libs/emscripten/emscripten_mainloop_stub.h"
|
||||
#endif
|
||||
|
||||
struct ExampleTimingHistory
|
||||
{
|
||||
double Samples[120];
|
||||
int Count;
|
||||
int Offset;
|
||||
|
||||
ExampleTimingHistory() : Count(0), Offset(0) { memset(Samples, 0, sizeof(Samples)); }
|
||||
|
||||
void AddSample(double value_ms)
|
||||
{
|
||||
Samples[Offset] = value_ms;
|
||||
Offset = (Offset + 1) % IM_ARRAYSIZE(Samples);
|
||||
if (Count < IM_ARRAYSIZE(Samples))
|
||||
Count++;
|
||||
}
|
||||
|
||||
double GetAverageMs() const
|
||||
{
|
||||
if (Count == 0)
|
||||
return 0.0;
|
||||
double total = 0.0;
|
||||
for (int i = 0; i < Count; i++)
|
||||
total += Samples[i];
|
||||
return total / (double)Count;
|
||||
}
|
||||
};
|
||||
|
||||
static double ExampleGetTimeMs()
|
||||
{
|
||||
typedef std::chrono::steady_clock Clock;
|
||||
return std::chrono::duration<double, std::milli>(Clock::now().time_since_epoch()).count();
|
||||
}
|
||||
|
||||
int main(int, char**)
|
||||
{
|
||||
// Setup SDL
|
||||
@@ -79,6 +114,8 @@ int main(int, char**)
|
||||
bool show_demo_window = true;
|
||||
bool show_another_window = false;
|
||||
ImVec4 clear_color = ImVec4(0.45f, 0.55f, 0.60f, 1.00f);
|
||||
ExampleTimingHistory raster_times;
|
||||
ExampleTimingHistory present_times;
|
||||
|
||||
// Main loop
|
||||
bool done = false;
|
||||
@@ -133,6 +170,10 @@ int main(int, char**)
|
||||
ImGui_ImplSDL2_NewFrame();
|
||||
ImGui::NewFrame();
|
||||
|
||||
int logical_w = 0;
|
||||
int logical_h = 0;
|
||||
SDL_GetWindowSize(window, &logical_w, &logical_h);
|
||||
|
||||
// 1. Show the big demo window
|
||||
if (show_demo_window)
|
||||
ImGui::ShowDemoWindow(&show_demo_window);
|
||||
@@ -156,6 +197,8 @@ int main(int, char**)
|
||||
ImGui::SameLine();
|
||||
ImGui::Text("counter = %d", counter);
|
||||
|
||||
ImGui::Text("Raster %.3f ms | Present %.3f ms", raster_times.GetAverageMs(), present_times.GetAverageMs());
|
||||
ImGui::Text("Window %d x %d | Framebuffer %d x %d", logical_w, logical_h, framebuffer->w, framebuffer->h);
|
||||
ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / io.Framerate, io.Framerate);
|
||||
ImGui::End();
|
||||
}
|
||||
@@ -173,6 +216,7 @@ int main(int, char**)
|
||||
// Rendering
|
||||
ImGui::Render();
|
||||
|
||||
const double raster_start_ms = ExampleGetTimeMs();
|
||||
SDL_FillRect(framebuffer, nullptr, SDL_MapRGBA(framebuffer->format,
|
||||
(Uint8)(clear_color.x * 255),
|
||||
(Uint8)(clear_color.y * 255),
|
||||
@@ -180,9 +224,12 @@ int main(int, char**)
|
||||
(Uint8)(clear_color.w * 255)));
|
||||
|
||||
ImGui_ImplSDLSurface2_RenderDrawData(ImGui::GetDrawData());
|
||||
raster_times.AddSample(ExampleGetTimeMs() - raster_start_ms);
|
||||
|
||||
const double present_start_ms = ExampleGetTimeMs();
|
||||
SDL_BlitSurface(framebuffer, nullptr, window_surface, nullptr);
|
||||
SDL_UpdateWindowSurface(window);
|
||||
present_times.AddSample(ExampleGetTimeMs() - present_start_ms);
|
||||
}
|
||||
#ifdef __EMSCRIPTEN__
|
||||
EMSCRIPTEN_MAINLOOP_END;
|
||||
|
||||
@@ -31,6 +31,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "example_sdl2_sdlrenderer2",
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "example_sdl2_surface", "example_sdl2_surface\example_sdl2_surface.vcxproj", "{47525E56-7D05-474E-A455-64C5BBFFC029}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "example_sdl2_cpu", "example_sdl2_cpu\example_sdl2_cpu.vcxproj", "{1E9DB182-9BF1-4C7D-8930-85ACAEAC2458}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "example_sdl3_opengl3", "example_sdl3_opengl3\example_sdl3_opengl3.vcxproj", "{84AAA301-84FE-428B-9E3E-817BC8123C0C}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "example_sdl3_sdlrenderer3", "example_sdl3_sdlrenderer3\example_sdl3_sdlrenderer3.vcxproj", "{C0290D21-3AD2-4A35-ABBC-A2F5F48326DA}"
|
||||
@@ -167,6 +169,14 @@ Global
|
||||
{47525E56-7D05-474E-A455-64C5BBFFC029}.Release|Win32.Build.0 = Release|Win32
|
||||
{47525E56-7D05-474E-A455-64C5BBFFC029}.Release|x64.ActiveCfg = Release|x64
|
||||
{47525E56-7D05-474E-A455-64C5BBFFC029}.Release|x64.Build.0 = Release|x64
|
||||
{1E9DB182-9BF1-4C7D-8930-85ACAEAC2458}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||
{1E9DB182-9BF1-4C7D-8930-85ACAEAC2458}.Debug|Win32.Build.0 = Debug|Win32
|
||||
{1E9DB182-9BF1-4C7D-8930-85ACAEAC2458}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{1E9DB182-9BF1-4C7D-8930-85ACAEAC2458}.Debug|x64.Build.0 = Debug|x64
|
||||
{1E9DB182-9BF1-4C7D-8930-85ACAEAC2458}.Release|Win32.ActiveCfg = Release|Win32
|
||||
{1E9DB182-9BF1-4C7D-8930-85ACAEAC2458}.Release|Win32.Build.0 = Release|Win32
|
||||
{1E9DB182-9BF1-4C7D-8930-85ACAEAC2458}.Release|x64.ActiveCfg = Release|x64
|
||||
{1E9DB182-9BF1-4C7D-8930-85ACAEAC2458}.Release|x64.Build.0 = Release|x64
|
||||
{84AAA301-84FE-428B-9E3E-817BC8123C0C}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||
{84AAA301-84FE-428B-9E3E-817BC8123C0C}.Debug|Win32.Build.0 = Debug|Win32
|
||||
{84AAA301-84FE-428B-9E3E-817BC8123C0C}.Debug|x64.ActiveCfg = Debug|x64
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
misc/cpp/
|
||||
InputText() wrappers for C++ standard library (STL) type: std::string.
|
||||
This is also an example of how you may wrap your own similar types.
|
||||
Includes imgui_cpu_validate.cpp, an offscreen validation utility for the imgui_impl_cpu backend.
|
||||
|
||||
misc/debuggers/
|
||||
Helper files for popular debuggers (Visual Studio, GDB, LLDB).
|
||||
|
||||
Executable
BIN
Binary file not shown.
@@ -0,0 +1,385 @@
|
||||
// dear imgui: imgui_impl_cpu format validation utility
|
||||
// Build manually with imgui core sources + backends/imgui_impl_cpu.cpp.
|
||||
|
||||
#include "imgui.h"
|
||||
#include "imgui_impl_cpu.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
struct ValidationBuffer
|
||||
{
|
||||
ImVector<unsigned char> Storage;
|
||||
ImVector<ImU32> Palette;
|
||||
ImGui_ImplCPU_PixelFormat Format;
|
||||
ImGui_ImplCPU_Framebuffer Framebuffer;
|
||||
|
||||
ValidationBuffer() { memset((void*)this, 0, sizeof(*this)); }
|
||||
};
|
||||
|
||||
static inline unsigned char Validation_ExpandBits(ImU32 value, int bits)
|
||||
{
|
||||
if (bits <= 0)
|
||||
return 0;
|
||||
if (bits >= 8)
|
||||
return (unsigned char)value;
|
||||
ImU32 max_value = (1u << bits) - 1u;
|
||||
return (unsigned char)((value * 255u + (max_value >> 1)) / max_value);
|
||||
}
|
||||
|
||||
static inline ImU32 Validation_CompressBits(unsigned char value, int bits)
|
||||
{
|
||||
if (bits <= 0)
|
||||
return 0;
|
||||
if (bits >= 8)
|
||||
return value;
|
||||
ImU32 max_value = (1u << bits) - 1u;
|
||||
return (ImU32)((value * max_value + 127u) / 255u);
|
||||
}
|
||||
|
||||
static inline void Validation_UnpackCanonicalRGBA(ImU32 pixel, unsigned char* r, unsigned char* g, unsigned char* b, unsigned char* a)
|
||||
{
|
||||
*r = (unsigned char)((pixel >> IM_COL32_R_SHIFT) & 0xFF);
|
||||
*g = (unsigned char)((pixel >> IM_COL32_G_SHIFT) & 0xFF);
|
||||
*b = (unsigned char)((pixel >> IM_COL32_B_SHIFT) & 0xFF);
|
||||
*a = (unsigned char)((pixel >> IM_COL32_A_SHIFT) & 0xFF);
|
||||
}
|
||||
|
||||
static inline ImU32 Validation_ReadRawPixel(const ValidationBuffer& buffer, int x, int y)
|
||||
{
|
||||
const unsigned char* p = buffer.Framebuffer.Pixels + (size_t)y * (size_t)buffer.Framebuffer.Pitch + (size_t)x * (size_t)buffer.Format.BytesPerPixel;
|
||||
switch (buffer.Format.BytesPerPixel)
|
||||
{
|
||||
case 1:
|
||||
return *p;
|
||||
case 2:
|
||||
{
|
||||
ImU16 pixel = 0;
|
||||
memcpy(&pixel, p, sizeof(pixel));
|
||||
return pixel;
|
||||
}
|
||||
case 3:
|
||||
#if defined(__BYTE_ORDER__) && (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)
|
||||
return (ImU32)((p[0] << 16) | (p[1] << 8) | p[2]);
|
||||
#else
|
||||
return (ImU32)(p[0] | (p[1] << 8) | (p[2] << 16));
|
||||
#endif
|
||||
case 4:
|
||||
{
|
||||
ImU32 pixel = 0;
|
||||
memcpy(&pixel, p, sizeof(pixel));
|
||||
return pixel;
|
||||
}
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static inline void Validation_WriteRawPixel(ValidationBuffer* buffer, int x, int y, ImU32 pixel)
|
||||
{
|
||||
unsigned char* p = buffer->Framebuffer.Pixels + (size_t)y * (size_t)buffer->Framebuffer.Pitch + (size_t)x * (size_t)buffer->Format.BytesPerPixel;
|
||||
switch (buffer->Format.BytesPerPixel)
|
||||
{
|
||||
case 1:
|
||||
*p = (unsigned char)pixel;
|
||||
return;
|
||||
case 2:
|
||||
{
|
||||
ImU16 v = (ImU16)pixel;
|
||||
memcpy(p, &v, sizeof(v));
|
||||
return;
|
||||
}
|
||||
case 3:
|
||||
#if defined(__BYTE_ORDER__) && (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)
|
||||
p[0] = (unsigned char)((pixel >> 16) & 0xFF);
|
||||
p[1] = (unsigned char)((pixel >> 8) & 0xFF);
|
||||
p[2] = (unsigned char)(pixel & 0xFF);
|
||||
#else
|
||||
p[0] = (unsigned char)(pixel & 0xFF);
|
||||
p[1] = (unsigned char)((pixel >> 8) & 0xFF);
|
||||
p[2] = (unsigned char)((pixel >> 16) & 0xFF);
|
||||
#endif
|
||||
return;
|
||||
case 4:
|
||||
memcpy(p, &pixel, sizeof(pixel));
|
||||
return;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
static ImU32 Validation_MapNearestPaletteColor(const ImGui_ImplCPU_PixelFormat* format, unsigned char r, unsigned char g, unsigned char b, unsigned char a)
|
||||
{
|
||||
unsigned int best_distance = 0xFFFFFFFFu;
|
||||
int best_index = 0;
|
||||
for (int i = 0; i < format->PaletteSize; i++)
|
||||
{
|
||||
unsigned char pr, pg, pb, pa;
|
||||
Validation_UnpackCanonicalRGBA(format->Palette[i], &pr, &pg, &pb, &pa);
|
||||
int dr = (int)pr - (int)r;
|
||||
int dg = (int)pg - (int)g;
|
||||
int db = (int)pb - (int)b;
|
||||
int da = (int)pa - (int)a;
|
||||
unsigned int distance = (unsigned int)(dr * dr + dg * dg + db * db + da * da);
|
||||
if (distance < best_distance)
|
||||
{
|
||||
best_distance = distance;
|
||||
best_index = i;
|
||||
if (distance == 0)
|
||||
break;
|
||||
}
|
||||
}
|
||||
return (ImU32)best_index;
|
||||
}
|
||||
|
||||
static ImU32 Validation_PackPixel(const ValidationBuffer& buffer, unsigned char r, unsigned char g, unsigned char b, unsigned char a)
|
||||
{
|
||||
if (buffer.Format.Palette != nullptr && buffer.Format.PaletteSize > 0)
|
||||
{
|
||||
if (buffer.Format.MapColorFn != nullptr)
|
||||
return buffer.Format.MapColorFn(&buffer.Format, r, g, b, a);
|
||||
return Validation_MapNearestPaletteColor(&buffer.Format, r, g, b, a);
|
||||
}
|
||||
|
||||
ImU32 pixel = 0;
|
||||
if (buffer.Format.Rmask != 0)
|
||||
pixel |= (Validation_CompressBits(r, 8 - buffer.Format.Rloss) << buffer.Format.Rshift) & buffer.Format.Rmask;
|
||||
if (buffer.Format.Gmask != 0)
|
||||
pixel |= (Validation_CompressBits(g, 8 - buffer.Format.Gloss) << buffer.Format.Gshift) & buffer.Format.Gmask;
|
||||
if (buffer.Format.Bmask != 0)
|
||||
pixel |= (Validation_CompressBits(b, 8 - buffer.Format.Bloss) << buffer.Format.Bshift) & buffer.Format.Bmask;
|
||||
if (buffer.Format.Amask != 0)
|
||||
pixel |= (Validation_CompressBits(a, 8 - buffer.Format.Aloss) << buffer.Format.Ashift) & buffer.Format.Amask;
|
||||
return pixel;
|
||||
}
|
||||
|
||||
static void Validation_DecodePixel(const ValidationBuffer& buffer, int x, int y, unsigned char* r, unsigned char* g, unsigned char* b, unsigned char* a)
|
||||
{
|
||||
ImU32 pixel = Validation_ReadRawPixel(buffer, x, y);
|
||||
if (buffer.Format.Palette != nullptr && buffer.Format.PaletteSize > 0)
|
||||
{
|
||||
if (pixel >= (ImU32)buffer.Format.PaletteSize)
|
||||
{
|
||||
*r = *g = *b = *a = 0;
|
||||
return;
|
||||
}
|
||||
Validation_UnpackCanonicalRGBA(buffer.Format.Palette[pixel], r, g, b, a);
|
||||
return;
|
||||
}
|
||||
|
||||
*r = (buffer.Format.Rmask != 0) ? Validation_ExpandBits((pixel & buffer.Format.Rmask) >> buffer.Format.Rshift, 8 - buffer.Format.Rloss) : 0;
|
||||
*g = (buffer.Format.Gmask != 0) ? Validation_ExpandBits((pixel & buffer.Format.Gmask) >> buffer.Format.Gshift, 8 - buffer.Format.Gloss) : 0;
|
||||
*b = (buffer.Format.Bmask != 0) ? Validation_ExpandBits((pixel & buffer.Format.Bmask) >> buffer.Format.Bshift, 8 - buffer.Format.Bloss) : 0;
|
||||
*a = (buffer.Format.Amask != 0) ? Validation_ExpandBits((pixel & buffer.Format.Amask) >> buffer.Format.Ashift, 8 - buffer.Format.Aloss) : 255;
|
||||
}
|
||||
|
||||
static bool Validation_InitBuffer(ValidationBuffer* buffer, int width, int height, const ImGui_ImplCPU_PixelFormat* format)
|
||||
{
|
||||
buffer->Format = *format;
|
||||
buffer->Framebuffer.Width = width;
|
||||
buffer->Framebuffer.Height = height;
|
||||
buffer->Framebuffer.Pitch = width * buffer->Format.BytesPerPixel;
|
||||
buffer->Storage.resize(height * buffer->Framebuffer.Pitch);
|
||||
buffer->Framebuffer.Pixels = buffer->Storage.Data;
|
||||
buffer->Framebuffer.Format = &buffer->Format;
|
||||
return buffer->Framebuffer.Pixels != nullptr;
|
||||
}
|
||||
|
||||
static bool Validation_InitIndexedBuffer(ValidationBuffer* buffer, int width, int height)
|
||||
{
|
||||
buffer->Palette.clear();
|
||||
buffer->Palette.push_back(IM_COL32(114, 140, 153, 255));
|
||||
buffer->Palette.push_back(IM_COL32(255, 0, 0, 255));
|
||||
buffer->Palette.push_back(IM_COL32(0, 255, 0, 255));
|
||||
buffer->Palette.push_back(IM_COL32(0, 0, 255, 255));
|
||||
buffer->Palette.push_back(IM_COL32(255, 255, 255, 255));
|
||||
buffer->Palette.push_back(IM_COL32(255, 255, 0, 255));
|
||||
|
||||
memset(&buffer->Format, 0, sizeof(buffer->Format));
|
||||
buffer->Format.BitsPerPixel = 8;
|
||||
buffer->Format.BytesPerPixel = 1;
|
||||
buffer->Format.Palette = buffer->Palette.Data;
|
||||
buffer->Format.PaletteSize = buffer->Palette.Size;
|
||||
buffer->Format.MapColorFn = Validation_MapNearestPaletteColor;
|
||||
return Validation_InitBuffer(buffer, width, height, &buffer->Format);
|
||||
}
|
||||
|
||||
static void Validation_ClearBuffer(ValidationBuffer* buffer, unsigned char r, unsigned char g, unsigned char b, unsigned char a)
|
||||
{
|
||||
ImU32 pixel = Validation_PackPixel(*buffer, r, g, b, a);
|
||||
for (int y = 0; y < buffer->Framebuffer.Height; y++)
|
||||
for (int x = 0; x < buffer->Framebuffer.Width; x++)
|
||||
Validation_WriteRawPixel(buffer, x, y, pixel);
|
||||
}
|
||||
|
||||
static bool Validation_CompareBuffers(const char* name, const ValidationBuffer& reference, const ValidationBuffer& candidate, int tolerance_rgb, int tolerance_alpha, bool ignore_alpha)
|
||||
{
|
||||
for (int y = 0; y < reference.Framebuffer.Height; y++)
|
||||
for (int x = 0; x < reference.Framebuffer.Width; x++)
|
||||
{
|
||||
unsigned char rr, rg, rb, ra;
|
||||
unsigned char cr, cg, cb, ca;
|
||||
Validation_DecodePixel(reference, x, y, &rr, &rg, &rb, &ra);
|
||||
Validation_DecodePixel(candidate, x, y, &cr, &cg, &cb, &ca);
|
||||
|
||||
if (abs((int)rr - (int)cr) > tolerance_rgb
|
||||
|| abs((int)rg - (int)cg) > tolerance_rgb
|
||||
|| abs((int)rb - (int)cb) > tolerance_rgb
|
||||
|| (!ignore_alpha && abs((int)ra - (int)ca) > tolerance_alpha))
|
||||
{
|
||||
printf("Validation failed for %s at (%d, %d): ref=(%u,%u,%u,%u) got=(%u,%u,%u,%u)\n",
|
||||
name, x, y, rr, rg, rb, ra, cr, cg, cb, ca);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static void Validation_FillBGRAImage(ImVector<unsigned char>* storage, ImGui_ImplCPU_Texture* texture)
|
||||
{
|
||||
const int width = 48;
|
||||
const int height = 32;
|
||||
storage->resize(width * height * 4);
|
||||
for (int y = 0; y < height; y++)
|
||||
for (int x = 0; x < width; x++)
|
||||
{
|
||||
unsigned char r = (unsigned char)(32 + x * 4);
|
||||
unsigned char g = (unsigned char)(32 + y * 6);
|
||||
unsigned char b = (unsigned char)(255 - x * 4);
|
||||
int offset = (y * width + x) * 4;
|
||||
(*storage)[offset + 0] = b;
|
||||
(*storage)[offset + 1] = g;
|
||||
(*storage)[offset + 2] = r;
|
||||
(*storage)[offset + 3] = 255;
|
||||
}
|
||||
|
||||
texture->Pixels = storage->Data;
|
||||
texture->Width = width;
|
||||
texture->Height = height;
|
||||
texture->Pitch = width * 4;
|
||||
texture->Format = ImGui_ImplCPU_GetBuiltinPixelFormat(ImGui_ImplCPU_BuiltinFormat_BGRA8888);
|
||||
}
|
||||
|
||||
static void Validation_BuildMainScene(const ImGui_ImplCPU_Texture* image_texture)
|
||||
{
|
||||
ImDrawList* bg = ImGui::GetBackgroundDrawList();
|
||||
bg->AddRectFilled(ImVec2(8.0f, 8.0f), ImVec2(40.0f, 40.0f), IM_COL32(255, 0, 0, 255));
|
||||
bg->AddRectFilled(ImVec2(472.0f, 280.0f), ImVec2(504.0f, 312.0f), IM_COL32(0, 255, 0, 255));
|
||||
|
||||
ImGui::SetNextWindowPos(ImVec2(32.0f, 24.0f), ImGuiCond_Always);
|
||||
ImGui::SetNextWindowSize(ImVec2(320.0f, 180.0f), ImGuiCond_Always);
|
||||
ImGui::Begin("Validation", nullptr, ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoCollapse);
|
||||
ImGui::Text("CPU format validation");
|
||||
ImGui::Text("Top-left marker is red. Bottom-right is green.");
|
||||
ImGui::ColorButton("##color", ImVec4(0.2f, 0.6f, 0.9f, 1.0f), 0, ImVec2(48.0f, 24.0f));
|
||||
ImGui::SameLine();
|
||||
ImGui::Image((ImTextureID)(intptr_t)image_texture, ImVec2((float)image_texture->Width, (float)image_texture->Height));
|
||||
ImGui::ProgressBar(0.65f, ImVec2(240.0f, 0.0f));
|
||||
ImGui::End();
|
||||
}
|
||||
|
||||
static void Validation_BuildPaletteScene()
|
||||
{
|
||||
ImDrawList* bg = ImGui::GetBackgroundDrawList();
|
||||
bg->AddRectFilled(ImVec2(8.0f, 8.0f), ImVec2(40.0f, 40.0f), IM_COL32(255, 0, 0, 255));
|
||||
bg->AddRectFilled(ImVec2(472.0f, 280.0f), ImVec2(504.0f, 312.0f), IM_COL32(0, 255, 0, 255));
|
||||
bg->AddRectFilled(ImVec2(160.0f, 32.0f), ImVec2(320.0f, 96.0f), IM_COL32(0, 0, 255, 255));
|
||||
bg->AddRectFilled(ImVec2(56.0f, 232.0f), ImVec2(168.0f, 280.0f), IM_COL32(255, 255, 0, 255));
|
||||
bg->AddRectFilled(ImVec2(360.0f, 64.0f), ImVec2(456.0f, 112.0f), IM_COL32(255, 255, 255, 255));
|
||||
}
|
||||
|
||||
static bool Validation_RenderInto(ValidationBuffer* buffer, ImDrawData* draw_data)
|
||||
{
|
||||
Validation_ClearBuffer(buffer, 114, 140, 153, 255);
|
||||
ImGui_ImplCPU_RenderDrawData(draw_data, &buffer->Framebuffer);
|
||||
return true;
|
||||
}
|
||||
|
||||
int main(int, char**)
|
||||
{
|
||||
IMGUI_CHECKVERSION();
|
||||
ImGui::CreateContext();
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
io.DisplaySize = ImVec2(512.0f, 320.0f);
|
||||
io.DeltaTime = 1.0f / 60.0f;
|
||||
io.Fonts->TexDesiredFormat = ImTextureFormat_Alpha8;
|
||||
|
||||
ImGui::StyleColorsDark();
|
||||
ImGui_ImplCPU_Init();
|
||||
|
||||
ImVector<unsigned char> image_storage;
|
||||
ImGui_ImplCPU_Texture image_texture;
|
||||
memset(&image_texture, 0, sizeof(image_texture));
|
||||
Validation_FillBGRAImage(&image_storage, &image_texture);
|
||||
|
||||
ValidationBuffer reference;
|
||||
Validation_InitBuffer(&reference, 512, 320, ImGui_ImplCPU_GetBuiltinPixelFormat(ImGui_ImplCPU_BuiltinFormat_RGBA8888));
|
||||
|
||||
const ImGui_ImplCPU_BuiltinFormat builtin_formats[] =
|
||||
{
|
||||
ImGui_ImplCPU_BuiltinFormat_RGBA8888,
|
||||
ImGui_ImplCPU_BuiltinFormat_BGRA8888,
|
||||
ImGui_ImplCPU_BuiltinFormat_ARGB8888,
|
||||
ImGui_ImplCPU_BuiltinFormat_ABGR8888,
|
||||
ImGui_ImplCPU_BuiltinFormat_RGB565,
|
||||
ImGui_ImplCPU_BuiltinFormat_ARGB1555,
|
||||
ImGui_ImplCPU_BuiltinFormat_RGBA4444,
|
||||
ImGui_ImplCPU_BuiltinFormat_RGB888,
|
||||
ImGui_ImplCPU_BuiltinFormat_BGR888
|
||||
};
|
||||
const char* builtin_names[] =
|
||||
{
|
||||
"RGBA8888",
|
||||
"BGRA8888",
|
||||
"ARGB8888",
|
||||
"ABGR8888",
|
||||
"RGB565",
|
||||
"ARGB1555",
|
||||
"RGBA4444",
|
||||
"RGB888",
|
||||
"BGR888"
|
||||
};
|
||||
const int builtin_tolerance[] =
|
||||
{
|
||||
0, 0, 0, 0, 8, 8, 17, 0, 0
|
||||
};
|
||||
const bool builtin_ignore_alpha[] =
|
||||
{
|
||||
false, false, false, false, true, false, false, true, true
|
||||
};
|
||||
|
||||
ImGui_ImplCPU_NewFrame();
|
||||
ImGui::NewFrame();
|
||||
Validation_BuildMainScene(&image_texture);
|
||||
ImGui::Render();
|
||||
if (!Validation_RenderInto(&reference, ImGui::GetDrawData()))
|
||||
return 1;
|
||||
|
||||
for (int i = 0; i < IM_ARRAYSIZE(builtin_formats); i++)
|
||||
{
|
||||
ValidationBuffer candidate;
|
||||
Validation_InitBuffer(&candidate, 512, 320, ImGui_ImplCPU_GetBuiltinPixelFormat(builtin_formats[i]));
|
||||
Validation_RenderInto(&candidate, ImGui::GetDrawData());
|
||||
if (!Validation_CompareBuffers(builtin_names[i], reference, candidate, builtin_tolerance[i], builtin_tolerance[i], builtin_ignore_alpha[i]))
|
||||
return 1;
|
||||
}
|
||||
|
||||
ValidationBuffer palette_reference;
|
||||
Validation_InitBuffer(&palette_reference, 512, 320, ImGui_ImplCPU_GetBuiltinPixelFormat(ImGui_ImplCPU_BuiltinFormat_RGBA8888));
|
||||
ValidationBuffer palette_candidate;
|
||||
Validation_InitIndexedBuffer(&palette_candidate, 512, 320);
|
||||
|
||||
ImGui_ImplCPU_NewFrame();
|
||||
ImGui::NewFrame();
|
||||
Validation_BuildPaletteScene();
|
||||
ImGui::Render();
|
||||
Validation_RenderInto(&palette_reference, ImGui::GetDrawData());
|
||||
Validation_RenderInto(&palette_candidate, ImGui::GetDrawData());
|
||||
if (!Validation_CompareBuffers("Indexed8", palette_reference, palette_candidate, 0, 0, false))
|
||||
return 1;
|
||||
|
||||
ImGui_ImplCPU_Shutdown();
|
||||
ImGui::DestroyContext();
|
||||
printf("imgui_impl_cpu validation passed.\n");
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user