Add SDL3 surface backend for ImGui example

- Created imgui_impl_sdlsurface3.h and corresponding implementation file.
- Added Makefile for building the SDL3 surface example on Linux and macOS.
- Included README.md with build instructions for Windows, Linux, and macOS.
- Added build script for Windows (build_win32.bat) and Visual Studio project files.
- Implemented main application logic in main.cpp to demonstrate ImGui with SDL3 and surface rendering.
This commit is contained in:
moonpower
2026-03-13 13:23:18 +01:00
parent 00843f9ece
commit 2f2b8a1226
12 changed files with 1898 additions and 242 deletions
+620 -229
View File
@@ -1,324 +1,715 @@
// imgui_impl_sdlsurface2.cpp
// CPU-only SDL_Surface backend for Dear ImGui
#include "imgui_impl_sdlsurface2.h"
#include "imgui.h"
#ifndef IMGUI_DISABLE
#include <SDL.h>
#include <cstring>
#include <stdint.h>
#include <algorithm>
#include <cmath>
#include <cstring>
// No clamp in C++11
template<typename T>
static inline T ImClamp(T v, T lo, T hi)
struct ImGui_ImplSDLSurface2_FastFormat32
{
if (v < lo) return lo;
if (v > hi) return hi;
return v;
Uint32 Rmask;
Uint32 Gmask;
Uint32 Bmask;
Uint32 Amask;
Uint8 Rshift;
Uint8 Gshift;
Uint8 Bshift;
Uint8 Ashift;
bool HasAlpha;
bool Valid;
ImGui_ImplSDLSurface2_FastFormat32() { memset((void*)this, 0, sizeof(*this)); }
};
struct ImGui_ImplSDLSurface2_SurfaceInfo
{
SDL_Surface* Surface;
Uint8* Pixels;
int Pitch;
int Width;
int Height;
SDL_PixelFormat* Format;
SDL_Palette* Palette;
ImGui_ImplSDLSurface2_FastFormat32 FastFormat;
bool IsFast;
ImGui_ImplSDLSurface2_SurfaceInfo() { memset((void*)this, 0, sizeof(*this)); }
};
struct ImGui_ImplSDLSurface2_Data
{
SDL_Surface* TargetSurface;
SDL_Surface* FontSurface;
ImGui_ImplSDLSurface2_SurfaceInfo TargetInfo;
ImGui_ImplSDLSurface2_Data() { memset((void*)this, 0, sizeof(*this)); }
};
struct ImGui_ImplSDLSurface2_RasterVertex
{
float X;
float Y;
float U;
float V;
float R;
float G;
float B;
float A;
};
static ImGui_ImplSDLSurface2_Data* ImGui_ImplSDLSurface2_GetBackendData()
{
return ImGui::GetCurrentContext() ? (ImGui_ImplSDLSurface2_Data*)ImGui::GetIO().BackendRendererUserData : nullptr;
}
static SDL_Surface* g_TargetSurface = nullptr;
static SDL_Surface* g_FontSurface = nullptr;
static inline Uint32 GetPixel(SDL_Surface* s, int x, int y)
static inline float ImGui_ImplSDLSurface2_Edge(float ax, float ay, float bx, float by, float px, float py)
{
Uint8* p = (Uint8*)s->pixels + y * s->pitch + x * s->format->BytesPerPixel;
switch (s->format->BytesPerPixel)
{
case 1: return *p;
case 2: return *(Uint16*)p;
case 3:
if (SDL_BYTEORDER == SDL_BIG_ENDIAN)
return (p[0] << 16) | (p[1] << 8) | p[2];
else
return p[0] | (p[1] << 8) | (p[2] << 16);
case 4: return *(Uint32*)p;
}
return (bx - ax) * (py - ay) - (by - ay) * (px - ax);
}
static inline int ImGui_ImplSDLSurface2_ClampInt(int v, int lo, int hi)
{
return (v < lo) ? lo : (v > hi ? hi : v);
}
static inline Uint8 ImGui_ImplSDLSurface2_ClampByte(float v)
{
if (v <= 0.0f)
return 0;
if (v >= 255.0f)
return 255;
return (Uint8)(v + 0.5f);
}
static inline void BlendPixel(SDL_Surface* s, int x, int y,
Uint8 sr, Uint8 sg, Uint8 sb, Uint8 sa)
static inline Uint8 ImGui_ImplSDLSurface2_Mul255(Uint32 a, Uint32 b)
{
if (!s || sa == 0) return;
if (x < 0 || y < 0 || x >= s->w || y >= s->h) return;
Uint32 t = a * b + 128;
return (Uint8)((t + (t >> 8)) >> 8);
}
if (sa == 255)
static ImGui_ImplSDLSurface2_FastFormat32 ImGui_ImplSDLSurface2_BuildFastFormat(SDL_PixelFormat* format)
{
ImGui_ImplSDLSurface2_FastFormat32 out;
if (format == nullptr)
return out;
if (format->BitsPerPixel != 32 || format->BytesPerPixel != 4)
return out;
if (format->Rloss != 0 || format->Gloss != 0 || format->Bloss != 0)
return out;
if (format->Amask != 0 && format->Aloss != 0)
return out;
out.Rmask = format->Rmask;
out.Gmask = format->Gmask;
out.Bmask = format->Bmask;
out.Amask = format->Amask;
out.Rshift = format->Rshift;
out.Gshift = format->Gshift;
out.Bshift = format->Bshift;
out.Ashift = format->Ashift;
out.HasAlpha = format->Amask != 0;
out.Valid = true;
return out;
}
static bool ImGui_ImplSDLSurface2_CanUseFastPath(SDL_Surface* surface, const ImGui_ImplSDLSurface2_FastFormat32& format)
{
#ifdef IMGUI_IMPL_SDLSURFACE_DISABLE_FAST_PATH
IM_UNUSED(surface);
IM_UNUSED(format);
return false;
#else
if (surface == nullptr || !format.Valid)
return false;
if ((surface->pitch & 3) != 0)
return false;
if ((((uintptr_t)surface->pixels) & 3) != 0)
return false;
return true;
#endif
}
static void ImGui_ImplSDLSurface2_InitSurfaceInfo(ImGui_ImplSDLSurface2_SurfaceInfo* out, SDL_Surface* surface)
{
out->Surface = surface;
out->Pixels = surface ? (Uint8*)surface->pixels : nullptr;
out->Pitch = surface ? surface->pitch : 0;
out->Width = surface ? surface->w : 0;
out->Height = surface ? surface->h : 0;
out->Format = surface ? surface->format : nullptr;
out->Palette = (surface && surface->format) ? surface->format->palette : nullptr;
out->FastFormat = ImGui_ImplSDLSurface2_BuildFastFormat(out->Format);
out->IsFast = ImGui_ImplSDLSurface2_CanUseFastPath(surface, out->FastFormat);
}
static inline Uint32 ImGui_ImplSDLSurface2_ReadPixelRaw(const ImGui_ImplSDLSurface2_SurfaceInfo& surface, int x, int y)
{
const Uint8* p = surface.Pixels + y * surface.Pitch + x * surface.Format->BytesPerPixel;
switch (surface.Format->BytesPerPixel)
{
Uint32 out_pix = SDL_MapRGBA(s->format, sr, sg, sb, sa);
Uint8* p = (Uint8*)s->pixels + y * s->pitch + x * s->format->BytesPerPixel;
switch (s->format->BytesPerPixel)
case 1:
return *p;
case 2:
return *(const Uint16*)p;
case 3:
if (SDL_BYTEORDER == SDL_BIG_ENDIAN)
return (Uint32)((p[0] << 16) | (p[1] << 8) | p[2]);
return (Uint32)(p[0] | (p[1] << 8) | (p[2] << 16));
case 4:
return *(const Uint32*)p;
default:
return 0;
}
}
static inline void ImGui_ImplSDLSurface2_WritePixelRaw(const ImGui_ImplSDLSurface2_SurfaceInfo& surface, int x, int y, Uint32 pixel)
{
Uint8* p = surface.Pixels + y * surface.Pitch + x * surface.Format->BytesPerPixel;
switch (surface.Format->BytesPerPixel)
{
case 1: *p = (Uint8)out_pix; break;
case 2: *(Uint16*)p = (Uint16)out_pix; break;
case 1:
*p = (Uint8)pixel;
return;
case 2:
*(Uint16*)p = (Uint16)pixel;
return;
case 3:
if (SDL_BYTEORDER == SDL_BIG_ENDIAN)
{
p[0] = (out_pix >> 16) & 0xFF;
p[1] = (out_pix >> 8) & 0xFF;
p[2] = out_pix & 0xFF;
p[0] = (Uint8)((pixel >> 16) & 0xFF);
p[1] = (Uint8)((pixel >> 8) & 0xFF);
p[2] = (Uint8)(pixel & 0xFF);
}
else
{
p[0] = out_pix & 0xFF;
p[1] = (out_pix >> 8) & 0xFF;
p[2] = (out_pix >> 16) & 0xFF;
p[0] = (Uint8)(pixel & 0xFF);
p[1] = (Uint8)((pixel >> 8) & 0xFF);
p[2] = (Uint8)((pixel >> 16) & 0xFF);
}
break;
case 4: *(Uint32*)p = out_pix; break;
return;
case 4:
*(Uint32*)p = pixel;
return;
default:
return;
}
}
static inline void ImGui_ImplSDLSurface2_UnpackFastRGBA(const ImGui_ImplSDLSurface2_FastFormat32& format, Uint32 pixel, Uint8* r, Uint8* g, Uint8* b, Uint8* a)
{
*r = (Uint8)((pixel & format.Rmask) >> format.Rshift);
*g = (Uint8)((pixel & format.Gmask) >> format.Gshift);
*b = (Uint8)((pixel & format.Bmask) >> format.Bshift);
*a = format.HasAlpha ? (Uint8)((pixel & format.Amask) >> format.Ashift) : 255;
}
static inline Uint32 ImGui_ImplSDLSurface2_PackFastRGBA(const ImGui_ImplSDLSurface2_FastFormat32& format, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
{
Uint32 pixel = (((Uint32)r << format.Rshift) & format.Rmask)
| (((Uint32)g << format.Gshift) & format.Gmask)
| (((Uint32)b << format.Bshift) & format.Bmask);
if (format.HasAlpha)
pixel |= (((Uint32)a << format.Ashift) & format.Amask);
return pixel;
}
static inline void ImGui_ImplSDLSurface2_ReadPixelRGBA(const ImGui_ImplSDLSurface2_SurfaceInfo& surface, int x, int y, Uint8* r, Uint8* g, Uint8* b, Uint8* a)
{
if (surface.IsFast)
{
const Uint32* src = (const Uint32*)(surface.Pixels + y * surface.Pitch) + x;
ImGui_ImplSDLSurface2_UnpackFastRGBA(surface.FastFormat, *src, r, g, b, a);
return;
}
Uint32 pixel = ImGui_ImplSDLSurface2_ReadPixelRaw(surface, x, y);
SDL_GetRGBA(pixel, surface.Format, r, g, b, a);
}
static inline void ImGui_ImplSDLSurface2_BlendPixelFast(const ImGui_ImplSDLSurface2_SurfaceInfo& target, Uint32* dst, Uint8 sr, Uint8 sg, Uint8 sb, Uint8 sa)
{
if (sa == 0)
return;
if (sa == 255)
{
*dst = ImGui_ImplSDLSurface2_PackFastRGBA(target.FastFormat, sr, sg, sb, 255);
return;
}
Uint32 dst_pix = GetPixel(s, x, y);
Uint8 dr, dg, db, da;
SDL_GetRGBA(dst_pix, s->format, &dr, &dg, &db, &da);
ImGui_ImplSDLSurface2_UnpackFastRGBA(target.FastFormat, *dst, &dr, &dg, &db, &da);
Uint8 inv_a = (Uint8)(255 - sa);
Uint8 out_r = (Uint8)(ImGui_ImplSDLSurface2_Mul255(sr, sa) + ImGui_ImplSDLSurface2_Mul255(dr, inv_a));
Uint8 out_g = (Uint8)(ImGui_ImplSDLSurface2_Mul255(sg, sa) + ImGui_ImplSDLSurface2_Mul255(dg, inv_a));
Uint8 out_b = (Uint8)(ImGui_ImplSDLSurface2_Mul255(sb, sa) + ImGui_ImplSDLSurface2_Mul255(db, inv_a));
Uint8 out_a = target.FastFormat.HasAlpha ? (Uint8)(sa + ImGui_ImplSDLSurface2_Mul255(da, inv_a)) : 255;
*dst = ImGui_ImplSDLSurface2_PackFastRGBA(target.FastFormat, out_r, out_g, out_b, out_a);
}
Uint8 out_r = (Uint8)((sr * sa + dr * (255 - sa)) / 255);
Uint8 out_g = (Uint8)((sg * sa + dg * (255 - sa)) / 255);
Uint8 out_b = (Uint8)((sb * sa + db * (255 - sa)) / 255);
Uint8 out_a = (Uint8)((sa + (da * (255 - sa)) / 255));
static inline void ImGui_ImplSDLSurface2_BlendPixelGeneric(const ImGui_ImplSDLSurface2_SurfaceInfo& target, int x, int y, Uint8 sr, Uint8 sg, Uint8 sb, Uint8 sa)
{
if (sa == 0)
return;
if (sa == 255)
{
Uint32 pixel = SDL_MapRGBA(target.Format, sr, sg, sb, 255);
ImGui_ImplSDLSurface2_WritePixelRaw(target, x, y, pixel);
return;
}
Uint32 out_pix = SDL_MapRGBA(s->format, out_r, out_g, out_b, out_a);
Uint8* p = (Uint8*)s->pixels + y * s->pitch + x * s->format->BytesPerPixel;
switch (s->format->BytesPerPixel)
Uint8 dr, dg, db, da;
Uint32 dst_pixel = ImGui_ImplSDLSurface2_ReadPixelRaw(target, x, y);
SDL_GetRGBA(dst_pixel, target.Format, &dr, &dg, &db, &da);
Uint8 inv_a = (Uint8)(255 - sa);
Uint8 out_r = (Uint8)(ImGui_ImplSDLSurface2_Mul255(sr, sa) + ImGui_ImplSDLSurface2_Mul255(dr, inv_a));
Uint8 out_g = (Uint8)(ImGui_ImplSDLSurface2_Mul255(sg, sa) + ImGui_ImplSDLSurface2_Mul255(dg, inv_a));
Uint8 out_b = (Uint8)(ImGui_ImplSDLSurface2_Mul255(sb, sa) + ImGui_ImplSDLSurface2_Mul255(db, inv_a));
Uint8 out_a = target.Format->Amask ? (Uint8)(sa + ImGui_ImplSDLSurface2_Mul255(da, inv_a)) : 255;
Uint32 pixel = SDL_MapRGBA(target.Format, out_r, out_g, out_b, out_a);
ImGui_ImplSDLSurface2_WritePixelRaw(target, x, y, pixel);
}
static inline void ImGui_ImplSDLSurface2_SetupRasterVertex(ImGui_ImplSDLSurface2_RasterVertex* out, const ImDrawVert& v, const ImVec2& display_pos, const ImVec2& framebuffer_scale)
{
out->X = (v.pos.x - display_pos.x) * framebuffer_scale.x;
out->Y = (v.pos.y - display_pos.y) * framebuffer_scale.y;
out->U = v.uv.x;
out->V = v.uv.y;
out->R = (float)((v.col >> IM_COL32_R_SHIFT) & 0xFF);
out->G = (float)((v.col >> IM_COL32_G_SHIFT) & 0xFF);
out->B = (float)((v.col >> IM_COL32_B_SHIFT) & 0xFF);
out->A = (float)((v.col >> IM_COL32_A_SHIFT) & 0xFF);
}
static void ImGui_ImplSDLSurface2_RenderTriangleFast(const ImGui_ImplSDLSurface2_SurfaceInfo& target, const ImGui_ImplSDLSurface2_SurfaceInfo* texture, const ImGui_ImplSDLSurface2_RasterVertex& v0, const ImGui_ImplSDLSurface2_RasterVertex& v1, const ImGui_ImplSDLSurface2_RasterVertex& v2, int clip_min_x, int clip_min_y, int clip_max_x, int clip_max_y)
{
int min_x = std::max((int)std::floor(std::min(v0.X, std::min(v1.X, v2.X))), clip_min_x);
int min_y = std::max((int)std::floor(std::min(v0.Y, std::min(v1.Y, v2.Y))), clip_min_y);
int max_x = std::min((int)std::ceil(std::max(v0.X, std::max(v1.X, v2.X))) - 1, clip_max_x - 1);
int max_y = std::min((int)std::ceil(std::max(v0.Y, std::max(v1.Y, v2.Y))) - 1, clip_max_y - 1);
if (min_x > max_x || min_y > max_y)
return;
float area = ImGui_ImplSDLSurface2_Edge(v0.X, v0.Y, v1.X, v1.Y, v2.X, v2.Y);
if (area == 0.0f)
return;
float sign = (area < 0.0f) ? -1.0f : 1.0f;
area *= sign;
float e0_dx = (v1.Y - v2.Y) * sign;
float e0_dy = (v2.X - v1.X) * sign;
float e1_dx = (v2.Y - v0.Y) * sign;
float e1_dy = (v0.X - v2.X) * sign;
float e2_dx = (v0.Y - v1.Y) * sign;
float e2_dy = (v1.X - v0.X) * sign;
float inv_area = 1.0f / area;
float dw0_dx = e0_dx * inv_area;
float dw0_dy = e0_dy * inv_area;
float dw1_dx = e1_dx * inv_area;
float dw1_dy = e1_dy * inv_area;
float dw2_dx = e2_dx * inv_area;
float dw2_dy = e2_dy * inv_area;
float dr_dx = dw0_dx * v0.R + dw1_dx * v1.R + dw2_dx * v2.R;
float dg_dx = dw0_dx * v0.G + dw1_dx * v1.G + dw2_dx * v2.G;
float db_dx = dw0_dx * v0.B + dw1_dx * v1.B + dw2_dx * v2.B;
float da_dx = dw0_dx * v0.A + dw1_dx * v1.A + dw2_dx * v2.A;
float du_dx = dw0_dx * v0.U + dw1_dx * v1.U + dw2_dx * v2.U;
float dv_dx = dw0_dx * v0.V + dw1_dx * v1.V + dw2_dx * v2.V;
float dr_dy = dw0_dy * v0.R + dw1_dy * v1.R + dw2_dy * v2.R;
float dg_dy = dw0_dy * v0.G + dw1_dy * v1.G + dw2_dy * v2.G;
float db_dy = dw0_dy * v0.B + dw1_dy * v1.B + dw2_dy * v2.B;
float da_dy = dw0_dy * v0.A + dw1_dy * v1.A + dw2_dy * v2.A;
float du_dy = dw0_dy * v0.U + dw1_dy * v1.U + dw2_dy * v2.U;
float dv_dy = dw0_dy * v0.V + dw1_dy * v1.V + dw2_dy * v2.V;
float start_x = (float)min_x + 0.5f;
float start_y = (float)min_y + 0.5f;
float e0_row = ImGui_ImplSDLSurface2_Edge(v1.X, v1.Y, v2.X, v2.Y, start_x, start_y) * sign;
float e1_row = ImGui_ImplSDLSurface2_Edge(v2.X, v2.Y, v0.X, v0.Y, start_x, start_y) * sign;
float e2_row = ImGui_ImplSDLSurface2_Edge(v0.X, v0.Y, v1.X, v1.Y, start_x, start_y) * sign;
float w0_row = e0_row * inv_area;
float w1_row = e1_row * inv_area;
float w2_row = e2_row * inv_area;
float r_row = w0_row * v0.R + w1_row * v1.R + w2_row * v2.R;
float g_row = w0_row * v0.G + w1_row * v1.G + w2_row * v2.G;
float b_row = w0_row * v0.B + w1_row * v1.B + w2_row * v2.B;
float a_row = w0_row * v0.A + w1_row * v1.A + w2_row * v2.A;
float u_row = w0_row * v0.U + w1_row * v1.U + w2_row * v2.U;
float v_row = w0_row * v0.V + w1_row * v1.V + w2_row * v2.V;
int texture_max_x = texture ? (texture->Width - 1) : 0;
int texture_max_y = texture ? (texture->Height - 1) : 0;
for (int y = min_y; y <= max_y; y++)
{
case 1: *p = (Uint8)out_pix; break;
case 2: *(Uint16*)p = (Uint16)out_pix; break;
case 3:
if (SDL_BYTEORDER == SDL_BIG_ENDIAN)
float e0 = e0_row;
float e1 = e1_row;
float e2 = e2_row;
float r = r_row;
float g = g_row;
float b = b_row;
float a = a_row;
float u = u_row;
float v = v_row;
Uint32* dst = (Uint32*)(target.Pixels + y * target.Pitch) + min_x;
for (int x = min_x; x <= max_x; x++)
{
p[0] = (out_pix >> 16) & 0xFF;
p[1] = (out_pix >> 8) & 0xFF;
p[2] = out_pix & 0xFF;
if (e0 >= 0.0f && e1 >= 0.0f && e2 >= 0.0f)
{
Uint8 out_r = ImGui_ImplSDLSurface2_ClampByte(r);
Uint8 out_g = ImGui_ImplSDLSurface2_ClampByte(g);
Uint8 out_b = ImGui_ImplSDLSurface2_ClampByte(b);
Uint8 out_a = ImGui_ImplSDLSurface2_ClampByte(a);
if (texture != nullptr)
{
int tx = ImGui_ImplSDLSurface2_ClampInt((int)(u * (float)texture_max_x + 0.5f), 0, texture_max_x);
int ty = ImGui_ImplSDLSurface2_ClampInt((int)(v * (float)texture_max_y + 0.5f), 0, texture_max_y);
Uint8 tr, tg, tb, ta;
ImGui_ImplSDLSurface2_ReadPixelRGBA(*texture, tx, ty, &tr, &tg, &tb, &ta);
out_r = ImGui_ImplSDLSurface2_Mul255(out_r, tr);
out_g = ImGui_ImplSDLSurface2_Mul255(out_g, tg);
out_b = ImGui_ImplSDLSurface2_Mul255(out_b, tb);
out_a = ImGui_ImplSDLSurface2_Mul255(out_a, ta);
}
else
{
p[0] = out_pix & 0xFF;
p[1] = (out_pix >> 8) & 0xFF;
p[2] = (out_pix >> 16) & 0xFF;
ImGui_ImplSDLSurface2_BlendPixelFast(target, dst, out_r, out_g, out_b, out_a);
}
break;
case 4: *(Uint32*)p = out_pix; break;
dst++;
e0 += e0_dx;
e1 += e1_dx;
e2 += e2_dx;
r += dr_dx;
g += dg_dx;
b += db_dx;
a += da_dx;
u += du_dx;
v += dv_dx;
}
e0_row += e0_dy;
e1_row += e1_dy;
e2_row += e2_dy;
r_row += dr_dy;
g_row += dg_dy;
b_row += db_dy;
a_row += da_dy;
u_row += du_dy;
v_row += dv_dy;
}
}
static inline float Edge(const ImVec2& a, const ImVec2& b, float x, float y)
static void ImGui_ImplSDLSurface2_RenderTriangleGeneric(const ImGui_ImplSDLSurface2_SurfaceInfo& target, const ImGui_ImplSDLSurface2_SurfaceInfo* texture, const ImGui_ImplSDLSurface2_RasterVertex& v0, const ImGui_ImplSDLSurface2_RasterVertex& v1, const ImGui_ImplSDLSurface2_RasterVertex& v2, int clip_min_x, int clip_min_y, int clip_max_x, int clip_max_y)
{
return (b.x - a.x) * (y - a.y) - (b.y - a.y) * (x - a.x);
int min_x = std::max((int)std::floor(std::min(v0.X, std::min(v1.X, v2.X))), clip_min_x);
int min_y = std::max((int)std::floor(std::min(v0.Y, std::min(v1.Y, v2.Y))), clip_min_y);
int max_x = std::min((int)std::ceil(std::max(v0.X, std::max(v1.X, v2.X))) - 1, clip_max_x - 1);
int max_y = std::min((int)std::ceil(std::max(v0.Y, std::max(v1.Y, v2.Y))) - 1, clip_max_y - 1);
if (min_x > max_x || min_y > max_y)
return;
float area = ImGui_ImplSDLSurface2_Edge(v0.X, v0.Y, v1.X, v1.Y, v2.X, v2.Y);
if (area == 0.0f)
return;
float sign = (area < 0.0f) ? -1.0f : 1.0f;
area *= sign;
float e0_dx = (v1.Y - v2.Y) * sign;
float e0_dy = (v2.X - v1.X) * sign;
float e1_dx = (v2.Y - v0.Y) * sign;
float e1_dy = (v0.X - v2.X) * sign;
float e2_dx = (v0.Y - v1.Y) * sign;
float e2_dy = (v1.X - v0.X) * sign;
float inv_area = 1.0f / area;
float dw0_dx = e0_dx * inv_area;
float dw0_dy = e0_dy * inv_area;
float dw1_dx = e1_dx * inv_area;
float dw1_dy = e1_dy * inv_area;
float dw2_dx = e2_dx * inv_area;
float dw2_dy = e2_dy * inv_area;
float dr_dx = dw0_dx * v0.R + dw1_dx * v1.R + dw2_dx * v2.R;
float dg_dx = dw0_dx * v0.G + dw1_dx * v1.G + dw2_dx * v2.G;
float db_dx = dw0_dx * v0.B + dw1_dx * v1.B + dw2_dx * v2.B;
float da_dx = dw0_dx * v0.A + dw1_dx * v1.A + dw2_dx * v2.A;
float du_dx = dw0_dx * v0.U + dw1_dx * v1.U + dw2_dx * v2.U;
float dv_dx = dw0_dx * v0.V + dw1_dx * v1.V + dw2_dx * v2.V;
float dr_dy = dw0_dy * v0.R + dw1_dy * v1.R + dw2_dy * v2.R;
float dg_dy = dw0_dy * v0.G + dw1_dy * v1.G + dw2_dy * v2.G;
float db_dy = dw0_dy * v0.B + dw1_dy * v1.B + dw2_dy * v2.B;
float da_dy = dw0_dy * v0.A + dw1_dy * v1.A + dw2_dy * v2.A;
float du_dy = dw0_dy * v0.U + dw1_dy * v1.U + dw2_dy * v2.U;
float dv_dy = dw0_dy * v0.V + dw1_dy * v1.V + dw2_dy * v2.V;
float start_x = (float)min_x + 0.5f;
float start_y = (float)min_y + 0.5f;
float e0_row = ImGui_ImplSDLSurface2_Edge(v1.X, v1.Y, v2.X, v2.Y, start_x, start_y) * sign;
float e1_row = ImGui_ImplSDLSurface2_Edge(v2.X, v2.Y, v0.X, v0.Y, start_x, start_y) * sign;
float e2_row = ImGui_ImplSDLSurface2_Edge(v0.X, v0.Y, v1.X, v1.Y, start_x, start_y) * sign;
float w0_row = e0_row * inv_area;
float w1_row = e1_row * inv_area;
float w2_row = e2_row * inv_area;
float r_row = w0_row * v0.R + w1_row * v1.R + w2_row * v2.R;
float g_row = w0_row * v0.G + w1_row * v1.G + w2_row * v2.G;
float b_row = w0_row * v0.B + w1_row * v1.B + w2_row * v2.B;
float a_row = w0_row * v0.A + w1_row * v1.A + w2_row * v2.A;
float u_row = w0_row * v0.U + w1_row * v1.U + w2_row * v2.U;
float v_row = w0_row * v0.V + w1_row * v1.V + w2_row * v2.V;
int texture_max_x = texture ? (texture->Width - 1) : 0;
int texture_max_y = texture ? (texture->Height - 1) : 0;
for (int y = min_y; y <= max_y; y++)
{
float e0 = e0_row;
float e1 = e1_row;
float e2 = e2_row;
float r = r_row;
float g = g_row;
float b = b_row;
float a = a_row;
float u = u_row;
float v = v_row;
for (int x = min_x; x <= max_x; x++)
{
if (e0 >= 0.0f && e1 >= 0.0f && e2 >= 0.0f)
{
Uint8 out_r = ImGui_ImplSDLSurface2_ClampByte(r);
Uint8 out_g = ImGui_ImplSDLSurface2_ClampByte(g);
Uint8 out_b = ImGui_ImplSDLSurface2_ClampByte(b);
Uint8 out_a = ImGui_ImplSDLSurface2_ClampByte(a);
if (texture != nullptr)
{
int tx = ImGui_ImplSDLSurface2_ClampInt((int)(u * (float)texture_max_x + 0.5f), 0, texture_max_x);
int ty = ImGui_ImplSDLSurface2_ClampInt((int)(v * (float)texture_max_y + 0.5f), 0, texture_max_y);
Uint8 tr, tg, tb, ta;
ImGui_ImplSDLSurface2_ReadPixelRGBA(*texture, tx, ty, &tr, &tg, &tb, &ta);
out_r = ImGui_ImplSDLSurface2_Mul255(out_r, tr);
out_g = ImGui_ImplSDLSurface2_Mul255(out_g, tg);
out_b = ImGui_ImplSDLSurface2_Mul255(out_b, tb);
out_a = ImGui_ImplSDLSurface2_Mul255(out_a, ta);
}
ImGui_ImplSDLSurface2_BlendPixelGeneric(target, x, y, out_r, out_g, out_b, out_a);
}
e0 += e0_dx;
e1 += e1_dx;
e2 += e2_dx;
r += dr_dx;
g += dg_dx;
b += db_dx;
a += da_dx;
u += du_dx;
v += dv_dx;
}
e0_row += e0_dy;
e1_row += e1_dy;
e2_row += e2_dy;
r_row += dr_dy;
g_row += dg_dy;
b_row += db_dy;
a_row += da_dy;
u_row += du_dy;
v_row += dv_dy;
}
}
SDL_Surface* ImGui_ImplSDLSurface2_CreateFontAtlasSurface()
{
ImGuiIO& io = ImGui::GetIO();
unsigned char* pixels = nullptr;
int width = 0, height = 0;
int width = 0;
int height = 0;
io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height);
if (!pixels || width <= 0 || height <= 0) return nullptr;
if (pixels == nullptr || width <= 0 || height <= 0)
return nullptr;
SDL_Surface* surf = SDL_CreateRGBSurfaceWithFormat(0, width, height, 32, SDL_PIXELFORMAT_RGBA32);
if (!surf) return nullptr;
SDL_Surface* surface = SDL_CreateRGBSurfaceWithFormat(0, width, height, 32, SDL_PIXELFORMAT_RGBA32);
if (surface == nullptr)
return nullptr;
if (SDL_MUSTLOCK(surface) && SDL_LockSurface(surface) != 0)
{
SDL_FreeSurface(surface);
return nullptr;
}
SDL_LockSurface(surf);
std::memcpy(surf->pixels, pixels, width * height * 4);
SDL_UnlockSurface(surf);
SDL_SetSurfaceBlendMode(surf, SDL_BLENDMODE_NONE);
return surf;
for (int y = 0; y < height; y++)
memcpy((Uint8*)surface->pixels + y * surface->pitch, pixels + (size_t)y * (size_t)width * 4, (size_t)width * 4);
if (SDL_MUSTLOCK(surface))
SDL_UnlockSurface(surface);
SDL_SetSurfaceBlendMode(surface, SDL_BLENDMODE_NONE);
return surface;
}
bool ImGui_ImplSDLSurface2_Init(SDL_Surface* surface)
{
if (!surface) return false;
if (surface == nullptr)
return false;
ImGuiIO& io = ImGui::GetIO();
IM_ASSERT(io.BackendRendererName == nullptr && "Already initialized a renderer backend!");
IMGUI_CHECKVERSION();
IM_ASSERT(io.BackendRendererUserData == nullptr && "Already initialized a renderer backend!");
ImGui_ImplSDLSurface2_Data* bd = IM_NEW(ImGui_ImplSDLSurface2_Data)();
io.BackendRendererUserData = (void*)bd;
io.BackendRendererName = "imgui_impl_sdlsurface2";
g_TargetSurface = surface;
g_FontSurface = ImGui_ImplSDLSurface2_CreateFontAtlasSurface();
if (g_FontSurface)
{
if (g_TargetSurface && g_FontSurface->format->format != g_TargetSurface->format->format)
{
SDL_Surface* converted = SDL_ConvertSurfaceFormat(g_FontSurface, g_TargetSurface->format->format, 0);
if (converted)
{
SDL_FreeSurface(g_FontSurface);
g_FontSurface = converted;
}
}
ImGui::GetIO().Fonts->TexID = (ImTextureID)g_FontSurface;
}
bd->TargetSurface = surface;
ImGui_ImplSDLSurface2_InitSurfaceInfo(&bd->TargetInfo, surface);
bd->FontSurface = ImGui_ImplSDLSurface2_CreateFontAtlasSurface();
if (bd->FontSurface != nullptr)
io.Fonts->TexID = (ImTextureID)bd->FontSurface;
return true;
}
void ImGui_ImplSDLSurface2_Shutdown()
{
ImGui_ImplSDLSurface2_Data* bd = ImGui_ImplSDLSurface2_GetBackendData();
IM_ASSERT(bd != nullptr && "No renderer backend to shutdown, or already shutdown?");
ImGuiIO& io = ImGui::GetIO();
io.BackendRendererName = nullptr;
io.BackendFlags &= ~ImGuiBackendFlags_RendererHasTextures;
ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO();
ImGui::GetIO().Fonts->TexID = nullptr;
if (g_FontSurface)
{
SDL_FreeSurface(g_FontSurface);
g_FontSurface = nullptr;
}
g_TargetSurface = nullptr;
io.Fonts->TexID = nullptr;
io.BackendRendererName = nullptr;
io.BackendRendererUserData = nullptr;
platform_io.ClearRendererHandlers();
if (bd->FontSurface != nullptr)
SDL_FreeSurface(bd->FontSurface);
IM_DELETE(bd);
}
void ImGui_ImplSDLSurface2_NewFrame()
{
// noop
ImGui_ImplSDLSurface2_Data* bd = ImGui_ImplSDLSurface2_GetBackendData();
IM_ASSERT(bd != nullptr && "Context or backend not initialized! Did you call ImGui_ImplSDLSurface2_Init()?");
IM_UNUSED(bd);
}
void ImGui_ImplSDLSurface2_RenderDrawData(ImDrawData* draw_data)
{
if (!draw_data || !g_TargetSurface) return;
ImGui_ImplSDLSurface2_Data* bd = ImGui_ImplSDLSurface2_GetBackendData();
if (bd == nullptr || draw_data == nullptr || bd->TargetSurface == nullptr)
return;
if (SDL_MUSTLOCK(g_TargetSurface)) SDL_LockSurface(g_TargetSurface);
if (SDL_MUSTLOCK(bd->TargetSurface) && SDL_LockSurface(bd->TargetSurface) != 0)
return;
const ImVec2 display_pos = draw_data->DisplayPos;
const ImVec2 fb_scale = draw_data->FramebufferScale;
ImGui_ImplSDLSurface2_InitSurfaceInfo(&bd->TargetInfo, bd->TargetSurface);
if (bd->TargetInfo.Width <= 0 || bd->TargetInfo.Height <= 0)
{
if (SDL_MUSTLOCK(bd->TargetSurface))
SDL_UnlockSurface(bd->TargetSurface);
return;
}
const ImVec2 clip_off = draw_data->DisplayPos;
const ImVec2 clip_scale = draw_data->FramebufferScale;
for (int n = 0; n < draw_data->CmdListsCount; n++)
{
const ImDrawList* cmd_list = draw_data->CmdLists[n];
const ImDrawVert* vtx_buffer = cmd_list->VtxBuffer.Data;
const ImDrawIdx* idx_buffer = cmd_list->IdxBuffer.Data;
const ImDrawList* draw_list = draw_data->CmdLists[n];
const ImDrawVert* vtx_buffer = draw_list->VtxBuffer.Data;
const ImDrawIdx* idx_buffer = draw_list->IdxBuffer.Data;
int idx_offset = 0;
for (int cmd_i = 0; cmd_i < cmd_list->CmdBuffer.Size; cmd_i++)
for (int cmd_i = 0; cmd_i < draw_list->CmdBuffer.Size; cmd_i++)
{
const ImDrawCmd* pcmd = &cmd_list->CmdBuffer[cmd_i];
const ImDrawCmd* pcmd = &draw_list->CmdBuffer[cmd_i];
if (pcmd->UserCallback != nullptr)
{
if (pcmd->UserCallback != ImDrawCallback_ResetRenderState)
pcmd->UserCallback(draw_list, pcmd);
continue;
}
if (pcmd->ElemCount == 0)
continue;
ImVec2 clip_min = ImVec2(
(pcmd->ClipRect.x - display_pos.x) * fb_scale.x,
(pcmd->ClipRect.y - display_pos.y) * fb_scale.y);
ImVec2 clip_max = ImVec2(
(pcmd->ClipRect.z - display_pos.x) * fb_scale.x,
(pcmd->ClipRect.w - display_pos.y) * fb_scale.y);
int cx0 = (int)std::floor(clip_min.x);
int cy0 = (int)std::floor(clip_min.y);
int cx1 = (int)std::ceil (clip_max.x);
int cy1 = (int)std::ceil (clip_max.y);
cx0 = std::max(cx0, 0);
cy0 = std::max(cy0, 0);
cx1 = std::min(cx1, g_TargetSurface->w);
cy1 = std::min(cy1, g_TargetSurface->h);
if (cx0 >= cx1 || cy0 >= cy1)
{
idx_offset += pcmd->ElemCount;
ImVec2 clip_min((pcmd->ClipRect.x - clip_off.x) * clip_scale.x, (pcmd->ClipRect.y - clip_off.y) * clip_scale.y);
ImVec2 clip_max((pcmd->ClipRect.z - clip_off.x) * clip_scale.x, (pcmd->ClipRect.w - clip_off.y) * clip_scale.y);
if (clip_min.x < 0.0f) clip_min.x = 0.0f;
if (clip_min.y < 0.0f) clip_min.y = 0.0f;
if (clip_max.x > (float)bd->TargetInfo.Width) clip_max.x = (float)bd->TargetInfo.Width;
if (clip_max.y > (float)bd->TargetInfo.Height) clip_max.y = (float)bd->TargetInfo.Height;
if (clip_max.x <= clip_min.x || clip_max.y <= clip_min.y)
continue;
}
SDL_Rect srect{ cx0, cy0, cx1 - cx0, cy1 - cy0 };
SDL_SetClipRect(g_TargetSurface, &srect);
int clip_min_x = (int)clip_min.x;
int clip_min_y = (int)clip_min.y;
int clip_max_x = (int)clip_max.x;
int clip_max_y = (int)clip_max.y;
SDL_Surface* tex = (SDL_Surface*)pcmd->GetTexID();
SDL_Surface* texture_surface = (SDL_Surface*)pcmd->GetTexID();
ImGui_ImplSDLSurface2_SurfaceInfo texture_info;
ImGui_ImplSDLSurface2_SurfaceInfo* texture_ptr = nullptr;
bool texture_locked = false;
for (unsigned int i = 0; i + 2 < (unsigned int)pcmd->ElemCount; i += 3)
if (texture_surface != nullptr)
{
ImDrawIdx i0 = idx_buffer[idx_offset + i + 0];
ImDrawIdx i1 = idx_buffer[idx_offset + i + 1];
ImDrawIdx i2 = idx_buffer[idx_offset + i + 2];
const ImDrawVert& v0 = vtx_buffer[i0];
const ImDrawVert& v1 = vtx_buffer[i1];
const ImDrawVert& v2 = vtx_buffer[i2];
ImVec2 p0 = ImVec2((v0.pos.x - display_pos.x) * fb_scale.x, (v0.pos.y - display_pos.y) * fb_scale.y);
ImVec2 p1 = ImVec2((v1.pos.x - display_pos.x) * fb_scale.x, (v1.pos.y - display_pos.y) * fb_scale.y);
ImVec2 p2 = ImVec2((v2.pos.x - display_pos.x) * fb_scale.x, (v2.pos.y - display_pos.y) * fb_scale.y);
int minx = (int)std::floor(std::min({ p0.x, p1.x, p2.x }));
int miny = (int)std::floor(std::min({ p0.y, p1.y, p2.y }));
int maxx = (int)std::ceil (std::max({ p0.x, p1.x, p2.x }));
int maxy = (int)std::ceil (std::max({ p0.y, p1.y, p2.y }));
minx = std::max(minx, cx0);
miny = std::max(miny, cy0);
maxx = std::min(maxx, cx1 - 1);
maxy = std::min(maxy, cy1 - 1);
if (minx > maxx || miny > maxy) continue;
float area = Edge(p0, p1, p2.x, p2.y);
if (area == 0.0f) continue;
auto unpack_col = [](ImU32 c, float out[4]) {
out[0] = (float)((c >> IM_COL32_R_SHIFT) & 0xFF) / 255.0f;
out[1] = (float)((c >> IM_COL32_G_SHIFT) & 0xFF) / 255.0f;
out[2] = (float)((c >> IM_COL32_B_SHIFT) & 0xFF) / 255.0f;
out[3] = (float)((c >> IM_COL32_A_SHIFT) & 0xFF) / 255.0f;
};
float c0[4], c1[4], c2[4];
unpack_col(v0.col, c0); unpack_col(v1.col, c1); unpack_col(v2.col, c2);
for (int y = miny; y <= maxy; y++)
if (SDL_MUSTLOCK(texture_surface))
{
for (int x = minx; x <= maxx; x++)
{
float px = (float)x + 0.5f;
float py = (float)y + 0.5f;
float w0 = Edge(p1, p2, px, py) / area;
float w1 = Edge(p2, p0, px, py) / area;
float w2 = Edge(p0, p1, px, py) / area;
if (w0 < 0.0f || w1 < 0.0f || w2 < 0.0f) continue;
float r = w0 * c0[0] + w1 * c1[0] + w2 * c2[0];
float g = w0 * c0[1] + w1 * c1[1] + w2 * c2[1];
float b = w0 * c0[2] + w1 * c1[2] + w2 * c2[2];
float a = w0 * c0[3] + w1 * c1[3] + w2 * c2[3];
Uint8 out_r = (Uint8)(ImClamp(r, 0.0f, 1.0f) * 255.0f);
Uint8 out_g = (Uint8)(ImClamp(g, 0.0f, 1.0f) * 255.0f);
Uint8 out_b = (Uint8)(ImClamp(b, 0.0f, 1.0f) * 255.0f);
Uint8 out_a = (Uint8)(ImClamp(a, 0.0f, 1.0f) * 255.0f);
if (tex)
{
ImVec2 uv0 = v0.uv, uv1 = v1.uv, uv2 = v2.uv;
float u = w0 * uv0.x + w1 * uv1.x + w2 * uv2.x;
float v = w0 * uv0.y + w1 * uv1.y + w2 * uv2.y;
int tx = (int)(u * (tex->w - 1) + 0.5f);
int ty = (int)(v * (tex->h - 1) + 0.5f);
tx = ImClamp(tx, 0, tex->w - 1);
ty = ImClamp(ty, 0, tex->h - 1);
Uint32 tpx = GetPixel(tex, tx, ty);
Uint8 tr, tg, tb, ta;
SDL_GetRGBA(tpx, tex->format, &tr, &tg, &tb, &ta);
Uint8 final_r = (Uint8)((tr * out_r) / 255);
Uint8 final_g = (Uint8)((tg * out_g) / 255);
Uint8 final_b = (Uint8)((tb * out_b) / 255);
Uint8 final_a = (Uint8)((ta * out_a) / 255);
BlendPixel(g_TargetSurface, x, y, final_r, final_g, final_b, final_a);
}
if (SDL_LockSurface(texture_surface) != 0)
texture_surface = nullptr;
else
texture_locked = true;
}
if (texture_surface != nullptr)
{
BlendPixel(g_TargetSurface, x, y, out_r, out_g, out_b, out_a);
}
}
ImGui_ImplSDLSurface2_InitSurfaceInfo(&texture_info, texture_surface);
if (texture_info.Width > 0 && texture_info.Height > 0)
texture_ptr = &texture_info;
}
}
idx_offset += pcmd->ElemCount;
for (unsigned int idx = 0; idx + 2 < (unsigned int)pcmd->ElemCount; idx += 3)
{
ImDrawIdx idx0 = idx_buffer[pcmd->IdxOffset + idx + 0];
ImDrawIdx idx1 = idx_buffer[pcmd->IdxOffset + idx + 1];
ImDrawIdx idx2 = idx_buffer[pcmd->IdxOffset + idx + 2];
ImGui_ImplSDLSurface2_RasterVertex v0;
ImGui_ImplSDLSurface2_RasterVertex v1;
ImGui_ImplSDLSurface2_RasterVertex v2;
ImGui_ImplSDLSurface2_SetupRasterVertex(&v0, vtx_buffer[pcmd->VtxOffset + idx0], clip_off, clip_scale);
ImGui_ImplSDLSurface2_SetupRasterVertex(&v1, vtx_buffer[pcmd->VtxOffset + idx1], clip_off, clip_scale);
ImGui_ImplSDLSurface2_SetupRasterVertex(&v2, vtx_buffer[pcmd->VtxOffset + idx2], clip_off, clip_scale);
if (bd->TargetInfo.IsFast)
ImGui_ImplSDLSurface2_RenderTriangleFast(bd->TargetInfo, texture_ptr, v0, v1, v2, clip_min_x, clip_min_y, clip_max_x, clip_max_y);
else
ImGui_ImplSDLSurface2_RenderTriangleGeneric(bd->TargetInfo, texture_ptr, v0, v1, v2, clip_min_x, clip_min_y, clip_max_x, clip_max_y);
}
if (texture_locked)
SDL_UnlockSurface(texture_surface);
}
}
SDL_SetClipRect(g_TargetSurface, nullptr);
if (SDL_MUSTLOCK(g_TargetSurface)) SDL_UnlockSurface(g_TargetSurface);
if (SDL_MUSTLOCK(bd->TargetSurface))
SDL_UnlockSurface(bd->TargetSurface);
}
#endif
+715
View File
@@ -0,0 +1,715 @@
#include "imgui_impl_sdlsurface3.h"
#include "imgui.h"
#ifndef IMGUI_DISABLE
#include <SDL3/SDL.h>
#include <stdint.h>
#include <algorithm>
#include <cmath>
#include <cstring>
struct ImGui_ImplSDLSurface3_FastFormat32
{
Uint32 Rmask;
Uint32 Gmask;
Uint32 Bmask;
Uint32 Amask;
Uint8 Rshift;
Uint8 Gshift;
Uint8 Bshift;
Uint8 Ashift;
bool HasAlpha;
bool Valid;
ImGui_ImplSDLSurface3_FastFormat32() { memset((void*)this, 0, sizeof(*this)); }
};
struct ImGui_ImplSDLSurface3_SurfaceInfo
{
SDL_Surface* Surface;
Uint8* Pixels;
int Pitch;
int Width;
int Height;
const SDL_PixelFormatDetails* Format;
SDL_Palette* Palette;
ImGui_ImplSDLSurface3_FastFormat32 FastFormat;
bool IsFast;
ImGui_ImplSDLSurface3_SurfaceInfo() { memset((void*)this, 0, sizeof(*this)); }
};
struct ImGui_ImplSDLSurface3_Data
{
SDL_Surface* TargetSurface;
SDL_Surface* FontSurface;
ImGui_ImplSDLSurface3_SurfaceInfo TargetInfo;
ImGui_ImplSDLSurface3_Data() { memset((void*)this, 0, sizeof(*this)); }
};
struct ImGui_ImplSDLSurface3_RasterVertex
{
float X;
float Y;
float U;
float V;
float R;
float G;
float B;
float A;
};
static ImGui_ImplSDLSurface3_Data* ImGui_ImplSDLSurface3_GetBackendData()
{
return ImGui::GetCurrentContext() ? (ImGui_ImplSDLSurface3_Data*)ImGui::GetIO().BackendRendererUserData : nullptr;
}
static inline float ImGui_ImplSDLSurface3_Edge(float ax, float ay, float bx, float by, float px, float py)
{
return (bx - ax) * (py - ay) - (by - ay) * (px - ax);
}
static inline int ImGui_ImplSDLSurface3_ClampInt(int v, int lo, int hi)
{
return (v < lo) ? lo : (v > hi ? hi : v);
}
static inline Uint8 ImGui_ImplSDLSurface3_ClampByte(float v)
{
if (v <= 0.0f)
return 0;
if (v >= 255.0f)
return 255;
return (Uint8)(v + 0.5f);
}
static inline Uint8 ImGui_ImplSDLSurface3_Mul255(Uint32 a, Uint32 b)
{
Uint32 t = a * b + 128;
return (Uint8)((t + (t >> 8)) >> 8);
}
static ImGui_ImplSDLSurface3_FastFormat32 ImGui_ImplSDLSurface3_BuildFastFormat(const SDL_PixelFormatDetails* format)
{
ImGui_ImplSDLSurface3_FastFormat32 out;
if (format == nullptr)
return out;
if (format->bits_per_pixel != 32 || format->bytes_per_pixel != 4)
return out;
if (format->Rbits != 8 || format->Gbits != 8 || format->Bbits != 8)
return out;
if (format->Amask != 0 && format->Abits != 8)
return out;
out.Rmask = format->Rmask;
out.Gmask = format->Gmask;
out.Bmask = format->Bmask;
out.Amask = format->Amask;
out.Rshift = format->Rshift;
out.Gshift = format->Gshift;
out.Bshift = format->Bshift;
out.Ashift = format->Ashift;
out.HasAlpha = format->Amask != 0;
out.Valid = true;
return out;
}
static bool ImGui_ImplSDLSurface3_CanUseFastPath(SDL_Surface* surface, const ImGui_ImplSDLSurface3_FastFormat32& format)
{
#ifdef IMGUI_IMPL_SDLSURFACE_DISABLE_FAST_PATH
IM_UNUSED(surface);
IM_UNUSED(format);
return false;
#else
if (surface == nullptr || !format.Valid)
return false;
if ((surface->pitch & 3) != 0)
return false;
if ((((uintptr_t)surface->pixels) & 3) != 0)
return false;
return true;
#endif
}
static void ImGui_ImplSDLSurface3_InitSurfaceInfo(ImGui_ImplSDLSurface3_SurfaceInfo* out, SDL_Surface* surface)
{
out->Surface = surface;
out->Pixels = surface ? (Uint8*)surface->pixels : nullptr;
out->Pitch = surface ? surface->pitch : 0;
out->Width = surface ? surface->w : 0;
out->Height = surface ? surface->h : 0;
out->Format = surface ? SDL_GetPixelFormatDetails(surface->format) : nullptr;
out->Palette = surface ? SDL_GetSurfacePalette(surface) : nullptr;
out->FastFormat = ImGui_ImplSDLSurface3_BuildFastFormat(out->Format);
out->IsFast = ImGui_ImplSDLSurface3_CanUseFastPath(surface, out->FastFormat);
}
static inline Uint32 ImGui_ImplSDLSurface3_ReadPixelRaw(const ImGui_ImplSDLSurface3_SurfaceInfo& surface, int x, int y)
{
const Uint8* p = surface.Pixels + y * surface.Pitch + x * surface.Format->bytes_per_pixel;
switch (surface.Format->bytes_per_pixel)
{
case 1:
return *p;
case 2:
return *(const Uint16*)p;
case 3:
if (SDL_BYTEORDER == SDL_BIG_ENDIAN)
return (Uint32)((p[0] << 16) | (p[1] << 8) | p[2]);
return (Uint32)(p[0] | (p[1] << 8) | (p[2] << 16));
case 4:
return *(const Uint32*)p;
default:
return 0;
}
}
static inline void ImGui_ImplSDLSurface3_WritePixelRaw(const ImGui_ImplSDLSurface3_SurfaceInfo& surface, int x, int y, Uint32 pixel)
{
Uint8* p = surface.Pixels + y * surface.Pitch + x * surface.Format->bytes_per_pixel;
switch (surface.Format->bytes_per_pixel)
{
case 1:
*p = (Uint8)pixel;
return;
case 2:
*(Uint16*)p = (Uint16)pixel;
return;
case 3:
if (SDL_BYTEORDER == SDL_BIG_ENDIAN)
{
p[0] = (Uint8)((pixel >> 16) & 0xFF);
p[1] = (Uint8)((pixel >> 8) & 0xFF);
p[2] = (Uint8)(pixel & 0xFF);
}
else
{
p[0] = (Uint8)(pixel & 0xFF);
p[1] = (Uint8)((pixel >> 8) & 0xFF);
p[2] = (Uint8)((pixel >> 16) & 0xFF);
}
return;
case 4:
*(Uint32*)p = pixel;
return;
default:
return;
}
}
static inline void ImGui_ImplSDLSurface3_UnpackFastRGBA(const ImGui_ImplSDLSurface3_FastFormat32& format, Uint32 pixel, Uint8* r, Uint8* g, Uint8* b, Uint8* a)
{
*r = (Uint8)((pixel & format.Rmask) >> format.Rshift);
*g = (Uint8)((pixel & format.Gmask) >> format.Gshift);
*b = (Uint8)((pixel & format.Bmask) >> format.Bshift);
*a = format.HasAlpha ? (Uint8)((pixel & format.Amask) >> format.Ashift) : 255;
}
static inline Uint32 ImGui_ImplSDLSurface3_PackFastRGBA(const ImGui_ImplSDLSurface3_FastFormat32& format, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
{
Uint32 pixel = (((Uint32)r << format.Rshift) & format.Rmask)
| (((Uint32)g << format.Gshift) & format.Gmask)
| (((Uint32)b << format.Bshift) & format.Bmask);
if (format.HasAlpha)
pixel |= (((Uint32)a << format.Ashift) & format.Amask);
return pixel;
}
static inline void ImGui_ImplSDLSurface3_ReadPixelRGBA(const ImGui_ImplSDLSurface3_SurfaceInfo& surface, int x, int y, Uint8* r, Uint8* g, Uint8* b, Uint8* a)
{
if (surface.IsFast)
{
const Uint32* src = (const Uint32*)(surface.Pixels + y * surface.Pitch) + x;
ImGui_ImplSDLSurface3_UnpackFastRGBA(surface.FastFormat, *src, r, g, b, a);
return;
}
Uint32 pixel = ImGui_ImplSDLSurface3_ReadPixelRaw(surface, x, y);
SDL_GetRGBA(pixel, surface.Format, surface.Palette, r, g, b, a);
}
static inline void ImGui_ImplSDLSurface3_BlendPixelFast(const ImGui_ImplSDLSurface3_SurfaceInfo& target, Uint32* dst, Uint8 sr, Uint8 sg, Uint8 sb, Uint8 sa)
{
if (sa == 0)
return;
if (sa == 255)
{
*dst = ImGui_ImplSDLSurface3_PackFastRGBA(target.FastFormat, sr, sg, sb, 255);
return;
}
Uint8 dr, dg, db, da;
ImGui_ImplSDLSurface3_UnpackFastRGBA(target.FastFormat, *dst, &dr, &dg, &db, &da);
Uint8 inv_a = (Uint8)(255 - sa);
Uint8 out_r = (Uint8)(ImGui_ImplSDLSurface3_Mul255(sr, sa) + ImGui_ImplSDLSurface3_Mul255(dr, inv_a));
Uint8 out_g = (Uint8)(ImGui_ImplSDLSurface3_Mul255(sg, sa) + ImGui_ImplSDLSurface3_Mul255(dg, inv_a));
Uint8 out_b = (Uint8)(ImGui_ImplSDLSurface3_Mul255(sb, sa) + ImGui_ImplSDLSurface3_Mul255(db, inv_a));
Uint8 out_a = (target.Format != nullptr && target.Format->Amask != 0) ? (Uint8)(sa + ImGui_ImplSDLSurface3_Mul255(da, inv_a)) : 255;
*dst = ImGui_ImplSDLSurface3_PackFastRGBA(target.FastFormat, out_r, out_g, out_b, out_a);
}
static inline void ImGui_ImplSDLSurface3_BlendPixelGeneric(const ImGui_ImplSDLSurface3_SurfaceInfo& target, int x, int y, Uint8 sr, Uint8 sg, Uint8 sb, Uint8 sa)
{
if (sa == 0)
return;
if (sa == 255)
{
Uint32 pixel = SDL_MapRGBA(target.Format, target.Palette, sr, sg, sb, 255);
ImGui_ImplSDLSurface3_WritePixelRaw(target, x, y, pixel);
return;
}
Uint8 dr, dg, db, da;
Uint32 dst_pixel = ImGui_ImplSDLSurface3_ReadPixelRaw(target, x, y);
SDL_GetRGBA(dst_pixel, target.Format, target.Palette, &dr, &dg, &db, &da);
Uint8 inv_a = (Uint8)(255 - sa);
Uint8 out_r = (Uint8)(ImGui_ImplSDLSurface3_Mul255(sr, sa) + ImGui_ImplSDLSurface3_Mul255(dr, inv_a));
Uint8 out_g = (Uint8)(ImGui_ImplSDLSurface3_Mul255(sg, sa) + ImGui_ImplSDLSurface3_Mul255(dg, inv_a));
Uint8 out_b = (Uint8)(ImGui_ImplSDLSurface3_Mul255(sb, sa) + ImGui_ImplSDLSurface3_Mul255(db, inv_a));
Uint8 out_a = target.FastFormat.HasAlpha ? (Uint8)(sa + ImGui_ImplSDLSurface3_Mul255(da, inv_a)) : 255;
Uint32 pixel = SDL_MapRGBA(target.Format, target.Palette, out_r, out_g, out_b, out_a);
ImGui_ImplSDLSurface3_WritePixelRaw(target, x, y, pixel);
}
static inline void ImGui_ImplSDLSurface3_SetupRasterVertex(ImGui_ImplSDLSurface3_RasterVertex* out, const ImDrawVert& v, const ImVec2& display_pos, const ImVec2& framebuffer_scale)
{
out->X = (v.pos.x - display_pos.x) * framebuffer_scale.x;
out->Y = (v.pos.y - display_pos.y) * framebuffer_scale.y;
out->U = v.uv.x;
out->V = v.uv.y;
out->R = (float)((v.col >> IM_COL32_R_SHIFT) & 0xFF);
out->G = (float)((v.col >> IM_COL32_G_SHIFT) & 0xFF);
out->B = (float)((v.col >> IM_COL32_B_SHIFT) & 0xFF);
out->A = (float)((v.col >> IM_COL32_A_SHIFT) & 0xFF);
}
static void ImGui_ImplSDLSurface3_RenderTriangleFast(const ImGui_ImplSDLSurface3_SurfaceInfo& target, const ImGui_ImplSDLSurface3_SurfaceInfo* texture, const ImGui_ImplSDLSurface3_RasterVertex& v0, const ImGui_ImplSDLSurface3_RasterVertex& v1, const ImGui_ImplSDLSurface3_RasterVertex& v2, int clip_min_x, int clip_min_y, int clip_max_x, int clip_max_y)
{
int min_x = std::max((int)std::floor(std::min(v0.X, std::min(v1.X, v2.X))), clip_min_x);
int min_y = std::max((int)std::floor(std::min(v0.Y, std::min(v1.Y, v2.Y))), clip_min_y);
int max_x = std::min((int)std::ceil(std::max(v0.X, std::max(v1.X, v2.X))) - 1, clip_max_x - 1);
int max_y = std::min((int)std::ceil(std::max(v0.Y, std::max(v1.Y, v2.Y))) - 1, clip_max_y - 1);
if (min_x > max_x || min_y > max_y)
return;
float area = ImGui_ImplSDLSurface3_Edge(v0.X, v0.Y, v1.X, v1.Y, v2.X, v2.Y);
if (area == 0.0f)
return;
float sign = (area < 0.0f) ? -1.0f : 1.0f;
area *= sign;
float e0_dx = (v1.Y - v2.Y) * sign;
float e0_dy = (v2.X - v1.X) * sign;
float e1_dx = (v2.Y - v0.Y) * sign;
float e1_dy = (v0.X - v2.X) * sign;
float e2_dx = (v0.Y - v1.Y) * sign;
float e2_dy = (v1.X - v0.X) * sign;
float inv_area = 1.0f / area;
float dw0_dx = e0_dx * inv_area;
float dw0_dy = e0_dy * inv_area;
float dw1_dx = e1_dx * inv_area;
float dw1_dy = e1_dy * inv_area;
float dw2_dx = e2_dx * inv_area;
float dw2_dy = e2_dy * inv_area;
float dr_dx = dw0_dx * v0.R + dw1_dx * v1.R + dw2_dx * v2.R;
float dg_dx = dw0_dx * v0.G + dw1_dx * v1.G + dw2_dx * v2.G;
float db_dx = dw0_dx * v0.B + dw1_dx * v1.B + dw2_dx * v2.B;
float da_dx = dw0_dx * v0.A + dw1_dx * v1.A + dw2_dx * v2.A;
float du_dx = dw0_dx * v0.U + dw1_dx * v1.U + dw2_dx * v2.U;
float dv_dx = dw0_dx * v0.V + dw1_dx * v1.V + dw2_dx * v2.V;
float dr_dy = dw0_dy * v0.R + dw1_dy * v1.R + dw2_dy * v2.R;
float dg_dy = dw0_dy * v0.G + dw1_dy * v1.G + dw2_dy * v2.G;
float db_dy = dw0_dy * v0.B + dw1_dy * v1.B + dw2_dy * v2.B;
float da_dy = dw0_dy * v0.A + dw1_dy * v1.A + dw2_dy * v2.A;
float du_dy = dw0_dy * v0.U + dw1_dy * v1.U + dw2_dy * v2.U;
float dv_dy = dw0_dy * v0.V + dw1_dy * v1.V + dw2_dy * v2.V;
float start_x = (float)min_x + 0.5f;
float start_y = (float)min_y + 0.5f;
float e0_row = ImGui_ImplSDLSurface3_Edge(v1.X, v1.Y, v2.X, v2.Y, start_x, start_y) * sign;
float e1_row = ImGui_ImplSDLSurface3_Edge(v2.X, v2.Y, v0.X, v0.Y, start_x, start_y) * sign;
float e2_row = ImGui_ImplSDLSurface3_Edge(v0.X, v0.Y, v1.X, v1.Y, start_x, start_y) * sign;
float w0_row = e0_row * inv_area;
float w1_row = e1_row * inv_area;
float w2_row = e2_row * inv_area;
float r_row = w0_row * v0.R + w1_row * v1.R + w2_row * v2.R;
float g_row = w0_row * v0.G + w1_row * v1.G + w2_row * v2.G;
float b_row = w0_row * v0.B + w1_row * v1.B + w2_row * v2.B;
float a_row = w0_row * v0.A + w1_row * v1.A + w2_row * v2.A;
float u_row = w0_row * v0.U + w1_row * v1.U + w2_row * v2.U;
float v_row = w0_row * v0.V + w1_row * v1.V + w2_row * v2.V;
int texture_max_x = texture ? (texture->Width - 1) : 0;
int texture_max_y = texture ? (texture->Height - 1) : 0;
for (int y = min_y; y <= max_y; y++)
{
float e0 = e0_row;
float e1 = e1_row;
float e2 = e2_row;
float r = r_row;
float g = g_row;
float b = b_row;
float a = a_row;
float u = u_row;
float v = v_row;
Uint32* dst = (Uint32*)(target.Pixels + y * target.Pitch) + min_x;
for (int x = min_x; x <= max_x; x++)
{
if (e0 >= 0.0f && e1 >= 0.0f && e2 >= 0.0f)
{
Uint8 out_r = ImGui_ImplSDLSurface3_ClampByte(r);
Uint8 out_g = ImGui_ImplSDLSurface3_ClampByte(g);
Uint8 out_b = ImGui_ImplSDLSurface3_ClampByte(b);
Uint8 out_a = ImGui_ImplSDLSurface3_ClampByte(a);
if (texture != nullptr)
{
int tx = ImGui_ImplSDLSurface3_ClampInt((int)(u * (float)texture_max_x + 0.5f), 0, texture_max_x);
int ty = ImGui_ImplSDLSurface3_ClampInt((int)(v * (float)texture_max_y + 0.5f), 0, texture_max_y);
Uint8 tr, tg, tb, ta;
ImGui_ImplSDLSurface3_ReadPixelRGBA(*texture, tx, ty, &tr, &tg, &tb, &ta);
out_r = ImGui_ImplSDLSurface3_Mul255(out_r, tr);
out_g = ImGui_ImplSDLSurface3_Mul255(out_g, tg);
out_b = ImGui_ImplSDLSurface3_Mul255(out_b, tb);
out_a = ImGui_ImplSDLSurface3_Mul255(out_a, ta);
}
ImGui_ImplSDLSurface3_BlendPixelFast(target, dst, out_r, out_g, out_b, out_a);
}
dst++;
e0 += e0_dx;
e1 += e1_dx;
e2 += e2_dx;
r += dr_dx;
g += dg_dx;
b += db_dx;
a += da_dx;
u += du_dx;
v += dv_dx;
}
e0_row += e0_dy;
e1_row += e1_dy;
e2_row += e2_dy;
r_row += dr_dy;
g_row += dg_dy;
b_row += db_dy;
a_row += da_dy;
u_row += du_dy;
v_row += dv_dy;
}
}
static void ImGui_ImplSDLSurface3_RenderTriangleGeneric(const ImGui_ImplSDLSurface3_SurfaceInfo& target, const ImGui_ImplSDLSurface3_SurfaceInfo* texture, const ImGui_ImplSDLSurface3_RasterVertex& v0, const ImGui_ImplSDLSurface3_RasterVertex& v1, const ImGui_ImplSDLSurface3_RasterVertex& v2, int clip_min_x, int clip_min_y, int clip_max_x, int clip_max_y)
{
int min_x = std::max((int)std::floor(std::min(v0.X, std::min(v1.X, v2.X))), clip_min_x);
int min_y = std::max((int)std::floor(std::min(v0.Y, std::min(v1.Y, v2.Y))), clip_min_y);
int max_x = std::min((int)std::ceil(std::max(v0.X, std::max(v1.X, v2.X))) - 1, clip_max_x - 1);
int max_y = std::min((int)std::ceil(std::max(v0.Y, std::max(v1.Y, v2.Y))) - 1, clip_max_y - 1);
if (min_x > max_x || min_y > max_y)
return;
float area = ImGui_ImplSDLSurface3_Edge(v0.X, v0.Y, v1.X, v1.Y, v2.X, v2.Y);
if (area == 0.0f)
return;
float sign = (area < 0.0f) ? -1.0f : 1.0f;
area *= sign;
float e0_dx = (v1.Y - v2.Y) * sign;
float e0_dy = (v2.X - v1.X) * sign;
float e1_dx = (v2.Y - v0.Y) * sign;
float e1_dy = (v0.X - v2.X) * sign;
float e2_dx = (v0.Y - v1.Y) * sign;
float e2_dy = (v1.X - v0.X) * sign;
float inv_area = 1.0f / area;
float dw0_dx = e0_dx * inv_area;
float dw0_dy = e0_dy * inv_area;
float dw1_dx = e1_dx * inv_area;
float dw1_dy = e1_dy * inv_area;
float dw2_dx = e2_dx * inv_area;
float dw2_dy = e2_dy * inv_area;
float dr_dx = dw0_dx * v0.R + dw1_dx * v1.R + dw2_dx * v2.R;
float dg_dx = dw0_dx * v0.G + dw1_dx * v1.G + dw2_dx * v2.G;
float db_dx = dw0_dx * v0.B + dw1_dx * v1.B + dw2_dx * v2.B;
float da_dx = dw0_dx * v0.A + dw1_dx * v1.A + dw2_dx * v2.A;
float du_dx = dw0_dx * v0.U + dw1_dx * v1.U + dw2_dx * v2.U;
float dv_dx = dw0_dx * v0.V + dw1_dx * v1.V + dw2_dx * v2.V;
float dr_dy = dw0_dy * v0.R + dw1_dy * v1.R + dw2_dy * v2.R;
float dg_dy = dw0_dy * v0.G + dw1_dy * v1.G + dw2_dy * v2.G;
float db_dy = dw0_dy * v0.B + dw1_dy * v1.B + dw2_dy * v2.B;
float da_dy = dw0_dy * v0.A + dw1_dy * v1.A + dw2_dy * v2.A;
float du_dy = dw0_dy * v0.U + dw1_dy * v1.U + dw2_dy * v2.U;
float dv_dy = dw0_dy * v0.V + dw1_dy * v1.V + dw2_dy * v2.V;
float start_x = (float)min_x + 0.5f;
float start_y = (float)min_y + 0.5f;
float e0_row = ImGui_ImplSDLSurface3_Edge(v1.X, v1.Y, v2.X, v2.Y, start_x, start_y) * sign;
float e1_row = ImGui_ImplSDLSurface3_Edge(v2.X, v2.Y, v0.X, v0.Y, start_x, start_y) * sign;
float e2_row = ImGui_ImplSDLSurface3_Edge(v0.X, v0.Y, v1.X, v1.Y, start_x, start_y) * sign;
float w0_row = e0_row * inv_area;
float w1_row = e1_row * inv_area;
float w2_row = e2_row * inv_area;
float r_row = w0_row * v0.R + w1_row * v1.R + w2_row * v2.R;
float g_row = w0_row * v0.G + w1_row * v1.G + w2_row * v2.G;
float b_row = w0_row * v0.B + w1_row * v1.B + w2_row * v2.B;
float a_row = w0_row * v0.A + w1_row * v1.A + w2_row * v2.A;
float u_row = w0_row * v0.U + w1_row * v1.U + w2_row * v2.U;
float v_row = w0_row * v0.V + w1_row * v1.V + w2_row * v2.V;
int texture_max_x = texture ? (texture->Width - 1) : 0;
int texture_max_y = texture ? (texture->Height - 1) : 0;
for (int y = min_y; y <= max_y; y++)
{
float e0 = e0_row;
float e1 = e1_row;
float e2 = e2_row;
float r = r_row;
float g = g_row;
float b = b_row;
float a = a_row;
float u = u_row;
float v = v_row;
for (int x = min_x; x <= max_x; x++)
{
if (e0 >= 0.0f && e1 >= 0.0f && e2 >= 0.0f)
{
Uint8 out_r = ImGui_ImplSDLSurface3_ClampByte(r);
Uint8 out_g = ImGui_ImplSDLSurface3_ClampByte(g);
Uint8 out_b = ImGui_ImplSDLSurface3_ClampByte(b);
Uint8 out_a = ImGui_ImplSDLSurface3_ClampByte(a);
if (texture != nullptr)
{
int tx = ImGui_ImplSDLSurface3_ClampInt((int)(u * (float)texture_max_x + 0.5f), 0, texture_max_x);
int ty = ImGui_ImplSDLSurface3_ClampInt((int)(v * (float)texture_max_y + 0.5f), 0, texture_max_y);
Uint8 tr, tg, tb, ta;
ImGui_ImplSDLSurface3_ReadPixelRGBA(*texture, tx, ty, &tr, &tg, &tb, &ta);
out_r = ImGui_ImplSDLSurface3_Mul255(out_r, tr);
out_g = ImGui_ImplSDLSurface3_Mul255(out_g, tg);
out_b = ImGui_ImplSDLSurface3_Mul255(out_b, tb);
out_a = ImGui_ImplSDLSurface3_Mul255(out_a, ta);
}
ImGui_ImplSDLSurface3_BlendPixelGeneric(target, x, y, out_r, out_g, out_b, out_a);
}
e0 += e0_dx;
e1 += e1_dx;
e2 += e2_dx;
r += dr_dx;
g += dg_dx;
b += db_dx;
a += da_dx;
u += du_dx;
v += dv_dx;
}
e0_row += e0_dy;
e1_row += e1_dy;
e2_row += e2_dy;
r_row += dr_dy;
g_row += dg_dy;
b_row += db_dy;
a_row += da_dy;
u_row += du_dy;
v_row += dv_dy;
}
}
SDL_Surface* ImGui_ImplSDLSurface3_CreateFontAtlasSurface()
{
ImGuiIO& io = ImGui::GetIO();
unsigned char* pixels = nullptr;
int width = 0;
int height = 0;
io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height);
if (pixels == nullptr || width <= 0 || height <= 0)
return nullptr;
SDL_Surface* surface = SDL_CreateSurface(width, height, SDL_PIXELFORMAT_RGBA32);
if (surface == nullptr)
return nullptr;
if (SDL_MUSTLOCK(surface) && !SDL_LockSurface(surface))
{
SDL_DestroySurface(surface);
return nullptr;
}
for (int y = 0; y < height; y++)
memcpy((Uint8*)surface->pixels + y * surface->pitch, pixels + (size_t)y * (size_t)width * 4, (size_t)width * 4);
if (SDL_MUSTLOCK(surface))
SDL_UnlockSurface(surface);
SDL_SetSurfaceBlendMode(surface, SDL_BLENDMODE_NONE);
return surface;
}
bool ImGui_ImplSDLSurface3_Init(SDL_Surface* surface)
{
if (surface == nullptr)
return false;
ImGuiIO& io = ImGui::GetIO();
IMGUI_CHECKVERSION();
IM_ASSERT(io.BackendRendererUserData == nullptr && "Already initialized a renderer backend!");
ImGui_ImplSDLSurface3_Data* bd = IM_NEW(ImGui_ImplSDLSurface3_Data)();
io.BackendRendererUserData = (void*)bd;
io.BackendRendererName = "imgui_impl_sdlsurface3";
bd->TargetSurface = surface;
ImGui_ImplSDLSurface3_InitSurfaceInfo(&bd->TargetInfo, surface);
bd->FontSurface = ImGui_ImplSDLSurface3_CreateFontAtlasSurface();
if (bd->FontSurface != nullptr)
io.Fonts->TexID = (ImTextureID)bd->FontSurface;
return true;
}
void ImGui_ImplSDLSurface3_Shutdown()
{
ImGui_ImplSDLSurface3_Data* bd = ImGui_ImplSDLSurface3_GetBackendData();
IM_ASSERT(bd != nullptr && "No renderer backend to shutdown, or already shutdown?");
ImGuiIO& io = ImGui::GetIO();
ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO();
io.Fonts->TexID = nullptr;
io.BackendRendererName = nullptr;
io.BackendRendererUserData = nullptr;
platform_io.ClearRendererHandlers();
if (bd->FontSurface != nullptr)
SDL_DestroySurface(bd->FontSurface);
IM_DELETE(bd);
}
void ImGui_ImplSDLSurface3_NewFrame()
{
ImGui_ImplSDLSurface3_Data* bd = ImGui_ImplSDLSurface3_GetBackendData();
IM_ASSERT(bd != nullptr && "Context or backend not initialized! Did you call ImGui_ImplSDLSurface3_Init()?");
IM_UNUSED(bd);
}
void ImGui_ImplSDLSurface3_RenderDrawData(ImDrawData* draw_data)
{
ImGui_ImplSDLSurface3_Data* bd = ImGui_ImplSDLSurface3_GetBackendData();
if (bd == nullptr || draw_data == nullptr || bd->TargetSurface == nullptr)
return;
if (SDL_MUSTLOCK(bd->TargetSurface) && !SDL_LockSurface(bd->TargetSurface))
return;
ImGui_ImplSDLSurface3_InitSurfaceInfo(&bd->TargetInfo, bd->TargetSurface);
if (bd->TargetInfo.Width <= 0 || bd->TargetInfo.Height <= 0)
{
if (SDL_MUSTLOCK(bd->TargetSurface))
SDL_UnlockSurface(bd->TargetSurface);
return;
}
const ImVec2 clip_off = draw_data->DisplayPos;
const ImVec2 clip_scale = draw_data->FramebufferScale;
for (int n = 0; n < draw_data->CmdListsCount; n++)
{
const ImDrawList* draw_list = draw_data->CmdLists[n];
const ImDrawVert* vtx_buffer = draw_list->VtxBuffer.Data;
const ImDrawIdx* idx_buffer = draw_list->IdxBuffer.Data;
for (int cmd_i = 0; cmd_i < draw_list->CmdBuffer.Size; cmd_i++)
{
const ImDrawCmd* pcmd = &draw_list->CmdBuffer[cmd_i];
if (pcmd->UserCallback != nullptr)
{
if (pcmd->UserCallback != ImDrawCallback_ResetRenderState)
pcmd->UserCallback(draw_list, pcmd);
continue;
}
if (pcmd->ElemCount == 0)
continue;
ImVec2 clip_min((pcmd->ClipRect.x - clip_off.x) * clip_scale.x, (pcmd->ClipRect.y - clip_off.y) * clip_scale.y);
ImVec2 clip_max((pcmd->ClipRect.z - clip_off.x) * clip_scale.x, (pcmd->ClipRect.w - clip_off.y) * clip_scale.y);
if (clip_min.x < 0.0f) clip_min.x = 0.0f;
if (clip_min.y < 0.0f) clip_min.y = 0.0f;
if (clip_max.x > (float)bd->TargetInfo.Width) clip_max.x = (float)bd->TargetInfo.Width;
if (clip_max.y > (float)bd->TargetInfo.Height) clip_max.y = (float)bd->TargetInfo.Height;
if (clip_max.x <= clip_min.x || clip_max.y <= clip_min.y)
continue;
int clip_min_x = (int)clip_min.x;
int clip_min_y = (int)clip_min.y;
int clip_max_x = (int)clip_max.x;
int clip_max_y = (int)clip_max.y;
SDL_Surface* texture_surface = (SDL_Surface*)pcmd->GetTexID();
ImGui_ImplSDLSurface3_SurfaceInfo texture_info;
ImGui_ImplSDLSurface3_SurfaceInfo* texture_ptr = nullptr;
bool texture_locked = false;
if (texture_surface != nullptr)
{
if (SDL_MUSTLOCK(texture_surface))
{
if (!SDL_LockSurface(texture_surface))
texture_surface = nullptr;
else
texture_locked = true;
}
if (texture_surface != nullptr)
{
ImGui_ImplSDLSurface3_InitSurfaceInfo(&texture_info, texture_surface);
if (texture_info.Width > 0 && texture_info.Height > 0)
texture_ptr = &texture_info;
}
}
for (unsigned int idx = 0; idx + 2 < (unsigned int)pcmd->ElemCount; idx += 3)
{
ImDrawIdx idx0 = idx_buffer[pcmd->IdxOffset + idx + 0];
ImDrawIdx idx1 = idx_buffer[pcmd->IdxOffset + idx + 1];
ImDrawIdx idx2 = idx_buffer[pcmd->IdxOffset + idx + 2];
ImGui_ImplSDLSurface3_RasterVertex v0;
ImGui_ImplSDLSurface3_RasterVertex v1;
ImGui_ImplSDLSurface3_RasterVertex v2;
ImGui_ImplSDLSurface3_SetupRasterVertex(&v0, vtx_buffer[pcmd->VtxOffset + idx0], clip_off, clip_scale);
ImGui_ImplSDLSurface3_SetupRasterVertex(&v1, vtx_buffer[pcmd->VtxOffset + idx1], clip_off, clip_scale);
ImGui_ImplSDLSurface3_SetupRasterVertex(&v2, vtx_buffer[pcmd->VtxOffset + idx2], clip_off, clip_scale);
if (bd->TargetInfo.IsFast)
ImGui_ImplSDLSurface3_RenderTriangleFast(bd->TargetInfo, texture_ptr, v0, v1, v2, clip_min_x, clip_min_y, clip_max_x, clip_max_y);
else
ImGui_ImplSDLSurface3_RenderTriangleGeneric(bd->TargetInfo, texture_ptr, v0, v1, v2, clip_min_x, clip_min_y, clip_max_x, clip_max_y);
}
if (texture_locked)
SDL_UnlockSurface(texture_surface);
}
}
if (SDL_MUSTLOCK(bd->TargetSurface))
SDL_UnlockSurface(bd->TargetSurface);
}
#endif
+11
View File
@@ -0,0 +1,11 @@
#pragma once
#include "imgui.h"
#include <SDL3/SDL.h>
IMGUI_API bool ImGui_ImplSDLSurface3_Init(SDL_Surface* surface);
IMGUI_API void ImGui_ImplSDLSurface3_Shutdown();
IMGUI_API void ImGui_ImplSDLSurface3_NewFrame();
IMGUI_API void ImGui_ImplSDLSurface3_RenderDrawData(ImDrawData* draw_data);
IMGUI_API SDL_Surface* ImGui_ImplSDLSurface3_CreateFontAtlasSurface();
+2
View File
@@ -94,6 +94,8 @@ List of Renderer Backends:
imgui_impl_sdlgpu3.cpp ; SDL_GPU (portable 3D graphics API of SDL3)
imgui_impl_sdlrenderer2.cpp ; SDL_Renderer (optional component of SDL2 available from SDL 2.0.18+)
imgui_impl_sdlrenderer3.cpp ; SDL_Renderer (optional component of SDL3. Prefer using SDL_GPU!).
imgui_impl_sdlsurface2.cpp ; SDL_Surface CPU renderer for SDL2
imgui_impl_sdlsurface3.cpp ; SDL_Surface CPU renderer for SDL3
imgui_impl_vulkan.cpp ; Vulkan
imgui_impl_wgpu.cpp ; WebGPU (web + desktop)
+8 -1
View File
@@ -145,6 +145,10 @@ SDL2 (Win32, Mac, Linux, etc.) + SDL_Renderer for SDL2 example.<BR>
= main.cpp + imgui_impl_sdl2.cpp + imgui_impl_sdlrenderer2.cpp <BR>
This requires SDL 2.0.18+ (released November 2021) <BR>
[example_sdl2_surface/](https://github.com/ocornut/imgui/blob/master/examples/example_sdl2_surface/) <BR>
SDL2 (Win32, Mac, Linux, etc.) + SDL_Surface CPU renderer example.<BR>
= main.cpp + imgui_impl_sdl2.cpp + imgui_impl_sdlsurface2.cpp <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>
@@ -178,6 +182,10 @@ SDL3 (Win32, Mac, Linux, etc.) + SDL_GPU for SDL3 example.<BR>
SDL3 (Win32, Mac, Linux, etc.) + SDL_Renderer for SDL3 example.<BR>
= main.cpp + imgui_impl_sdl3.cpp + imgui_impl_sdlrenderer3.cpp <BR>
[example_sdl3_surface/](https://github.com/ocornut/imgui/blob/master/examples/example_sdl3_surface/) <BR>
SDL3 (Win32, Mac, Linux, etc.) + SDL_Surface CPU renderer example.<BR>
= main.cpp + imgui_impl_sdl3.cpp + imgui_impl_sdlsurface3.cpp <BR>
[example_sdl3_vulkan/](https://github.com/ocornut/imgui/blob/master/examples/example_sdl3_vulkan/) <BR>
SDL3 (Win32, Mac, Linux, etc.) + Vulkan example. <BR>
= main.cpp + imgui_impl_sdl3.cpp + imgui_impl_vulkan.cpp <BR>
@@ -253,4 +261,3 @@ when an interactive drag is in progress.
Note that some setup configurations or GPU drivers may introduce additional display lag depending on their settings.
If you notice that dragging windows is laggy and you are not sure what the cause is: try drawing a simple
2D shape directly under the mouse cursor to help identify the issue!
+53
View File
@@ -0,0 +1,53 @@
EXE = example_sdl3_surface
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_sdl3.cpp $(IMGUI_DIR)/backends/imgui_impl_sdlsurface3.cpp
OBJS = $(addsuffix .o, $(basename $(notdir $(SOURCES))))
UNAME_S := $(shell uname -s)
CXXFLAGS = -std=c++11 -I$(IMGUI_DIR) -I$(IMGUI_DIR)/backends
CXXFLAGS += -g -Wall -Wformat
LIBS =
ifeq ($(UNAME_S), Linux)
ECHO_MESSAGE = "Linux"
LIBS += -ldl `pkg-config sdl3 --libs`
CXXFLAGS += `pkg-config sdl3 --cflags`
CFLAGS = $(CXXFLAGS)
endif
ifeq ($(UNAME_S), Darwin)
ECHO_MESSAGE = "Mac OS X"
LIBS += -framework Cocoa -framework IOKit -framework CoreVideo
LIBS += `pkg-config --libs sdl3`
LIBS += -L/usr/local/lib -L/opt/local/lib
CXXFLAGS += `pkg-config --cflags sdl3`
CXXFLAGS += -I/usr/local/include -I/opt/local/include
CFLAGS = $(CXXFLAGS)
endif
ifeq ($(OS), Windows_NT)
ECHO_MESSAGE = "MinGW"
LIBS += -lgdi32 -limm32 `pkg-config --static --libs sdl3`
CXXFLAGS += `pkg-config --cflags sdl3`
CFLAGS = $(CXXFLAGS)
endif
%.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)
+33
View File
@@ -0,0 +1,33 @@
# How to Build
## Windows with Visual Studio's IDE
Use the provided project file (`example_sdl3_surface.vcxproj`) or open `imgui_examples.sln`.
## Windows with Visual Studio's CLI
Use `build_win32.bat` or directly:
```bat
set SDL3_DIR=path_to_your_sdl3_folder
cl /Zi /MD /utf-8 /I.. /I..\.. /I%SDL3_DIR%\include main.cpp ..\..\backends\imgui_impl_sdl3.cpp ..\..\backends\imgui_impl_sdlsurface3.cpp ..\..\imgui*.cpp /FeDebug/example_sdl3_surface.exe /FoDebug/ /link /libpath:%SDL3_DIR%\lib\x86 SDL3.lib /subsystem:console
cl /Zi /MD /utf-8 /I.. /I..\.. /I%SDL3_DIR%\include main.cpp ..\..\backends\imgui_impl_sdl3.cpp ..\..\backends\imgui_impl_sdlsurface3.cpp ..\..\imgui*.cpp /FeDebug/example_sdl3_surface.exe /FoDebug/ /link /libpath:%SDL3_DIR%\lib\x64 SDL3.lib /subsystem:console
```
## Linux and similar Unixes
Use the provided `Makefile` or directly:
```sh
c++ `pkg-config --cflags sdl3` -I .. -I ../.. -I ../../backends \
main.cpp ../../backends/imgui_impl_sdl3.cpp ../../backends/imgui_impl_sdlsurface3.cpp ../../imgui*.cpp \
-ldl `pkg-config --libs sdl3`
```
## macOS
Use the provided `Makefile` or directly:
```sh
brew install sdl3
c++ `pkg-config --cflags sdl3` -I .. -I ../.. -I ../../backends \
main.cpp ../../backends/imgui_impl_sdl3.cpp ../../backends/imgui_impl_sdlsurface3.cpp ../../imgui*.cpp \
-framework Cocoa -framework IOKit -framework CoreVideo `pkg-config --libs sdl3`
```
@@ -0,0 +1,7 @@
@set OUT_DIR=Debug
@set OUT_EXE=example_sdl3_surface
@set INCLUDES=/I..\.. /I..\..\backends /I%SDL3_DIR%\include
@set SOURCES=main.cpp ..\..\backends\imgui_impl_sdl3.cpp ..\..\backends\imgui_impl_sdlsurface3.cpp ..\..\imgui*.cpp
@set LIBS=/LIBPATH:%SDL3_DIR%\lib\x86 SDL3.lib
mkdir %OUT_DIR%
cl /nologo /Zi /MD /utf-8 %INCLUDES% %SOURCES% /Fe%OUT_DIR%/%OUT_EXE%.exe /Fo%OUT_DIR%/ /link %LIBS% /subsystem:console
@@ -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>{08DD87C0-C734-45D6-9B44-D23F19F2D4B6}</ProjectGuid>
<RootNamespace>example_sdl3_surface</RootNamespace>
<WindowsTargetPlatformVersion>8.1</WindowsTargetPlatformVersion>
<ProjectName>example_sdl3_surface</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;%SDL3_DIR%\include;$(VcpkgCurrentInstalledDir)include\SDL3;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<AdditionalOptions>/utf-8 %(AdditionalOptions)</AdditionalOptions>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalLibraryDirectories>%SDL3_DIR%\lib\x86;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<AdditionalDependencies>SDL3.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;%SDL3_DIR%\include;$(VcpkgCurrentInstalledDir)include\SDL3;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<AdditionalOptions>/utf-8 %(AdditionalOptions)</AdditionalOptions>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalLibraryDirectories>%SDL3_DIR%\lib\x64;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<AdditionalDependencies>SDL3.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;%SDL3_DIR%\include;$(VcpkgCurrentInstalledDir)include\SDL3;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<BufferSecurityCheck>false</BufferSecurityCheck>
<AdditionalOptions>/utf-8 %(AdditionalOptions)</AdditionalOptions>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<AdditionalLibraryDirectories>%SDL3_DIR%\lib\x86;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<AdditionalDependencies>SDL3.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;%SDL3_DIR%\include;$(VcpkgCurrentInstalledDir)include\SDL3;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<BufferSecurityCheck>false</BufferSecurityCheck>
<AdditionalOptions>/utf-8 %(AdditionalOptions)</AdditionalOptions>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<AdditionalLibraryDirectories>%SDL3_DIR%\lib\x64;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<AdditionalDependencies>SDL3.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_sdl3.cpp" />
<ClCompile Include="..\..\backends\imgui_impl_sdlsurface3.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_sdl3.h" />
<ClInclude Include="..\..\backends\imgui_impl_sdlsurface3.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_sdl3.cpp">
<Filter>sources</Filter>
</ClCompile>
<ClCompile Include="..\..\backends\imgui_impl_sdlsurface3.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_sdl3.h">
<Filter>sources</Filter>
</ClInclude>
<ClInclude Include="..\..\backends\imgui_impl_sdlsurface3.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>
+176
View File
@@ -0,0 +1,176 @@
#include "imgui.h"
#include "imgui_impl_sdl3.h"
#include "imgui_impl_sdlsurface3.h"
#include <SDL3/SDL.h>
#include <stdio.h>
int main(int, char**)
{
if (!SDL_Init(SDL_INIT_VIDEO | SDL_INIT_GAMEPAD))
{
printf("Error: SDL_Init(): %s\n", SDL_GetError());
return 1;
}
float main_scale = SDL_GetDisplayContentScale(SDL_GetPrimaryDisplay());
SDL_WindowFlags window_flags = SDL_WINDOW_RESIZABLE | SDL_WINDOW_HIDDEN | SDL_WINDOW_HIGH_PIXEL_DENSITY;
SDL_Window* window = SDL_CreateWindow("Dear ImGui SDL3+Surface Example", (int)(1280 * main_scale), (int)(800 * main_scale), window_flags);
if (window == nullptr)
{
printf("Error: SDL_CreateWindow(): %s\n", SDL_GetError());
return 1;
}
SDL_SetWindowPosition(window, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED);
SDL_ShowWindow(window);
SDL_Surface* window_surface = SDL_GetWindowSurface(window);
if (window_surface == nullptr)
{
printf("Error: SDL_GetWindowSurface(): %s\n", SDL_GetError());
SDL_DestroyWindow(window);
SDL_Quit();
return 1;
}
SDL_SetWindowSurfaceVSync(window, 1);
int framebuffer_w = window_surface->w;
int framebuffer_h = window_surface->h;
SDL_Surface* framebuffer = SDL_CreateSurface(framebuffer_w, framebuffer_h, SDL_PIXELFORMAT_RGBA32);
if (framebuffer == nullptr)
{
printf("Error: SDL_CreateSurface(): %s\n", SDL_GetError());
SDL_DestroyWindow(window);
SDL_Quit();
return 1;
}
IMGUI_CHECKVERSION();
ImGui::CreateContext();
ImGuiIO& io = ImGui::GetIO();
io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard;
io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad;
ImGui::StyleColorsDark();
ImGuiStyle& style = ImGui::GetStyle();
style.ScaleAllSizes(main_scale);
style.FontScaleDpi = main_scale;
ImGui_ImplSDL3_InitForOther(window);
ImGui_ImplSDLSurface3_Init(framebuffer);
bool show_demo_window = true;
bool show_another_window = false;
ImVec4 clear_color = ImVec4(0.45f, 0.55f, 0.60f, 1.00f);
bool done = false;
while (!done)
{
SDL_Event event;
while (SDL_PollEvent(&event))
{
ImGui_ImplSDL3_ProcessEvent(&event);
if (event.type == SDL_EVENT_QUIT)
done = true;
if (event.type == SDL_EVENT_WINDOW_CLOSE_REQUESTED && event.window.windowID == SDL_GetWindowID(window))
done = true;
if ((event.type == SDL_EVENT_WINDOW_RESIZED || event.type == SDL_EVENT_WINDOW_PIXEL_SIZE_CHANGED) && event.window.windowID == SDL_GetWindowID(window))
{
window_surface = SDL_GetWindowSurface(window);
if (window_surface != nullptr)
{
int new_w = window_surface->w;
int new_h = window_surface->h;
if (new_w != framebuffer_w || new_h != framebuffer_h)
{
SDL_DestroySurface(framebuffer);
framebuffer = SDL_CreateSurface(new_w, new_h, SDL_PIXELFORMAT_RGBA32);
if (framebuffer == nullptr)
{
printf("Error: SDL_CreateSurface(): %s\n", SDL_GetError());
done = true;
break;
}
framebuffer_w = new_w;
framebuffer_h = new_h;
ImGui_ImplSDLSurface3_Shutdown();
ImGui_ImplSDLSurface3_Init(framebuffer);
}
}
}
}
if (done)
break;
if (SDL_GetWindowFlags(window) & SDL_WINDOW_MINIMIZED)
{
SDL_Delay(10);
continue;
}
ImGui_ImplSDLSurface3_NewFrame();
ImGui_ImplSDL3_NewFrame();
ImGui::NewFrame();
if (show_demo_window)
ImGui::ShowDemoWindow(&show_demo_window);
{
static float f = 0.0f;
static int counter = 0;
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("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / io.Framerate, io.Framerate);
ImGui::End();
}
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();
}
ImGui::Render();
SDL_FillSurfaceRect(framebuffer, nullptr, SDL_MapSurfaceRGBA(framebuffer,
(Uint8)(clear_color.x * 255.0f),
(Uint8)(clear_color.y * 255.0f),
(Uint8)(clear_color.z * 255.0f),
(Uint8)(clear_color.w * 255.0f)));
ImGui_ImplSDLSurface3_RenderDrawData(ImGui::GetDrawData());
window_surface = SDL_GetWindowSurface(window);
if (window_surface != nullptr)
{
SDL_BlitSurface(framebuffer, nullptr, window_surface, nullptr);
SDL_UpdateWindowSurface(window);
}
}
ImGui_ImplSDLSurface3_Shutdown();
ImGui_ImplSDL3_Shutdown();
ImGui::DestroyContext();
SDL_DestroySurface(framebuffer);
SDL_DestroyWindowSurface(window);
SDL_DestroyWindow(window);
SDL_Quit();
return 0;
}
+10
View File
@@ -35,6 +35,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "example_sdl3_opengl3", "exa
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "example_sdl3_sdlrenderer3", "example_sdl3_sdlrenderer3\example_sdl3_sdlrenderer3.vcxproj", "{C0290D21-3AD2-4A35-ABBC-A2F5F48326DA}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "example_sdl3_surface", "example_sdl3_surface\example_sdl3_surface.vcxproj", "{08DD87C0-C734-45D6-9B44-D23F19F2D4B6}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "example_sdl3_vulkan", "example_sdl3_vulkan\example_sdl3_vulkan.vcxproj", "{663A7E89-1E42-4222-921C-177F5B5910DF}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "example_win32_vulkan", "example_win32_vulkan\example_win32_vulkan.vcxproj", "{0A1E32DF-E0F4-4CCE-B3DC-9644C503BD88}"
@@ -181,6 +183,14 @@ Global
{C0290D21-3AD2-4A35-ABBC-A2F5F48326DA}.Release|Win32.Build.0 = Release|Win32
{C0290D21-3AD2-4A35-ABBC-A2F5F48326DA}.Release|x64.ActiveCfg = Release|x64
{C0290D21-3AD2-4A35-ABBC-A2F5F48326DA}.Release|x64.Build.0 = Release|x64
{08DD87C0-C734-45D6-9B44-D23F19F2D4B6}.Debug|Win32.ActiveCfg = Debug|Win32
{08DD87C0-C734-45D6-9B44-D23F19F2D4B6}.Debug|Win32.Build.0 = Debug|Win32
{08DD87C0-C734-45D6-9B44-D23F19F2D4B6}.Debug|x64.ActiveCfg = Debug|x64
{08DD87C0-C734-45D6-9B44-D23F19F2D4B6}.Debug|x64.Build.0 = Debug|x64
{08DD87C0-C734-45D6-9B44-D23F19F2D4B6}.Release|Win32.ActiveCfg = Release|Win32
{08DD87C0-C734-45D6-9B44-D23F19F2D4B6}.Release|Win32.Build.0 = Release|Win32
{08DD87C0-C734-45D6-9B44-D23F19F2D4B6}.Release|x64.ActiveCfg = Release|x64
{08DD87C0-C734-45D6-9B44-D23F19F2D4B6}.Release|x64.Build.0 = Release|x64
{663A7E89-1E42-4222-921C-177F5B5910DF}.Debug|Win32.ActiveCfg = Debug|Win32
{663A7E89-1E42-4222-921C-177F5B5910DF}.Debug|Win32.Build.0 = Debug|Win32
{663A7E89-1E42-4222-921C-177F5B5910DF}.Debug|x64.ActiveCfg = Debug|x64