From 073ce5fa4d83937acce3956a5abcd993237d39ca Mon Sep 17 00:00:00 2001
From: CasualPokePlayer <50538166+CasualPokePlayer@users.noreply.github.com>
Date: Thu, 19 Sep 2024 22:00:55 -0700
Subject: [PATCH] Do alpha blending more faithfully to GDI+
fixes #4043
---
.../D3D11/D3D11Resources.cs | 5 -
.../D3D11/IGL_D3D11.cs | 6 +-
.../GDIPlus/IGL_GDIPlus.cs | 9 +-
.../ImGuiResourceCache.cs | 96 ++++++-
.../Interfaces/IGL.cs | 8 +-
.../OpenGL/IGL_OpenGL.cs | 9 +-
.../Renderers/GDIPlusGuiRenderer.cs | 2 +-
.../Renderers/GuiRenderer.cs | 2 +-
.../Renderers/ImGui2DRenderer.cs | 238 +++++++++++++-----
.../Renderers/SDLImGui2DRenderer.cs | 5 +-
10 files changed, 262 insertions(+), 118 deletions(-)
diff --git a/src/BizHawk.Bizware.Graphics/D3D11/D3D11Resources.cs b/src/BizHawk.Bizware.Graphics/D3D11/D3D11Resources.cs
index 416b2309a0..168673172f 100644
--- a/src/BizHawk.Bizware.Graphics/D3D11/D3D11Resources.cs
+++ b/src/BizHawk.Bizware.Graphics/D3D11/D3D11Resources.cs
@@ -18,7 +18,6 @@ namespace BizHawk.Bizware.Graphics
public IDXGIFactory1 Factory1;
public IDXGIFactory2 Factory2;
public ID3D11BlendState BlendNormalState;
- public ID3D11BlendState BlendAlphaState;
public ID3D11BlendState BlendDisableState;
public ID3D11SamplerState PointSamplerState;
public ID3D11SamplerState LinearSamplerState;
@@ -89,8 +88,6 @@ namespace BizHawk.Bizware.Graphics
bd.RenderTarget[0].SourceBlend = Blend.One;
bd.RenderTarget[0].DestinationBlend = Blend.Zero;
- BlendAlphaState = Device.CreateBlendState(bd);
-
bd.RenderTarget[0].BlendEnable = false;
BlendDisableState = Device.CreateBlendState(bd);
@@ -154,8 +151,6 @@ namespace BizHawk.Bizware.Graphics
BlendNormalState?.Dispose();
BlendNormalState = null;
- BlendAlphaState?.Dispose();
- BlendAlphaState = null;
BlendDisableState?.Dispose();
BlendDisableState = null;
diff --git a/src/BizHawk.Bizware.Graphics/D3D11/IGL_D3D11.cs b/src/BizHawk.Bizware.Graphics/D3D11/IGL_D3D11.cs
index bcc76f8d8f..a0ae2797d1 100644
--- a/src/BizHawk.Bizware.Graphics/D3D11/IGL_D3D11.cs
+++ b/src/BizHawk.Bizware.Graphics/D3D11/IGL_D3D11.cs
@@ -25,7 +25,6 @@ namespace BizHawk.Bizware.Graphics
private IDXGIFactory1 Factory1 => _resources.Factory1;
private IDXGIFactory2 Factory2 => _resources.Factory2;
private ID3D11BlendState BlendNormalState => _resources.BlendNormalState;
- private ID3D11BlendState BlendAlphaState => _resources.BlendAlphaState;
private ID3D11BlendState BlendDisableState => _resources.BlendDisableState;
private ID3D11RasterizerState RasterizerState => _resources.RasterizerState;
@@ -186,12 +185,9 @@ namespace BizHawk.Bizware.Graphics
public void ClearColor(Color color)
=> Context.ClearRenderTargetView(CurRenderTarget?.RTV ?? _controlSwapChain.RTV, new(color.R, color.B, color.G, color.A));
- public void EnableBlendNormal()
+ public void EnableBlending()
=> Context.OMSetBlendState(BlendNormalState);
- public void EnableBlendAlpha()
- => Context.OMSetBlendState(BlendAlphaState);
-
public void DisableBlending()
=> Context.OMSetBlendState(BlendDisableState);
diff --git a/src/BizHawk.Bizware.Graphics/GDIPlus/IGL_GDIPlus.cs b/src/BizHawk.Bizware.Graphics/GDIPlus/IGL_GDIPlus.cs
index 17534c1fc4..3a9cb3239d 100644
--- a/src/BizHawk.Bizware.Graphics/GDIPlus/IGL_GDIPlus.cs
+++ b/src/BizHawk.Bizware.Graphics/GDIPlus/IGL_GDIPlus.cs
@@ -27,14 +27,7 @@ namespace BizHawk.Bizware.Graphics
public void ClearColor(Color color)
=> GetCurrentGraphics().Clear(color);
- public void EnableBlendNormal()
- {
- var g = GetCurrentGraphics();
- g.CompositingMode = CompositingMode.SourceOver;
- g.CompositingQuality = CompositingQuality.Default;
- }
-
- public void EnableBlendAlpha()
+ public void EnableBlending()
{
var g = GetCurrentGraphics();
g.CompositingMode = CompositingMode.SourceOver;
diff --git a/src/BizHawk.Bizware.Graphics/ImGuiResourceCache.cs b/src/BizHawk.Bizware.Graphics/ImGuiResourceCache.cs
index aac5be832e..0c7eea3cbd 100644
--- a/src/BizHawk.Bizware.Graphics/ImGuiResourceCache.cs
+++ b/src/BizHawk.Bizware.Graphics/ImGuiResourceCache.cs
@@ -1,5 +1,6 @@
using System.Collections.Generic;
using System.Drawing;
+using System.Numerics;
namespace BizHawk.Bizware.Graphics
{
@@ -51,6 +52,7 @@ namespace BizHawk.Bizware.Graphics
igl.BindPipeline(Pipeline);
SetTexture(null);
+ SetBlendingParamters(null, true);
igl.BindPipeline(null);
}
}
@@ -67,6 +69,18 @@ namespace BizHawk.Bizware.Graphics
Pipeline.SetUniformSampler("uSampler0", texture2D);
}
+ internal void SetBlendingParamters(ITexture2D secondaryTexture, bool doBlendPass)
+ {
+ Pipeline.SetUniformSampler("uSampler1", secondaryTexture);
+ Pipeline.SetUniform("uBlendEnable", secondaryTexture != null);
+ Pipeline.SetUniform("uBlendPass", doBlendPass);
+
+ if (secondaryTexture != null)
+ {
+ Pipeline.SetUniform("uSamplerSize", new Vector2(secondaryTexture.Width, secondaryTexture.Height));
+ }
+ }
+
public void Dispose()
{
foreach (var cachedTex in TextureCache.Values)
@@ -94,6 +108,8 @@ namespace BizHawk.Bizware.Graphics
TextureCache.Clear();
}
+ // ReSharper disable UseRawString
+
public const string ImGuiVertexShader_d3d11 = @"
//vertex shader uniforms
float4x4 um44Projection;
@@ -125,9 +141,10 @@ VS_OUTPUT vsmain(VS_INPUT src)
public const string ImGuiPixelShader_d3d11 = @"
//pixel shader uniforms
-bool uSamplerEnable;
-Texture2D uTexture0;
-sampler uSampler0;
+bool uSamplerEnable, uBlendPass, uBlendEnable;
+float2 uSamplerSize;
+Texture2D uTexture0, uTexture1;
+sampler uSampler0, uSampler1;
struct PS_INPUT
{
@@ -138,9 +155,37 @@ struct PS_INPUT
float4 psmain(PS_INPUT src) : SV_Target
{
- float4 temp = src.vColor0;
- if(uSamplerEnable) temp *= uTexture0.Sample(uSampler0,src.vTexcoord0);
- return temp;
+ if (uBlendPass)
+ {
+ float4 temp = src.vColor0;
+ if(uSamplerEnable) temp *= uTexture0.Sample(uSampler0, src.vTexcoord0);
+
+ if (uBlendEnable)
+ {
+ if (temp.a != 1.0)
+ {
+ float4 prev = uTexture1.Sample(uSampler1, src.vPosition.xy / uSamplerSize);
+ if (temp.a == 0.0)
+ {
+ temp = prev;
+ }
+ else
+ {
+ float alpha = prev.a + temp.a - (prev.a * temp.a);
+ temp.r = ((temp.r * temp.a) + (prev.r * prev.a * (1.0 - temp.a))) / alpha;
+ temp.g = ((temp.g * temp.a) + (prev.g * prev.a * (1.0 - temp.a))) / alpha;
+ temp.b = ((temp.b * temp.a) + (prev.b * prev.a * (1.0 - temp.a))) / alpha;
+ temp.a = alpha;
+ }
+ }
+ }
+
+ return temp;
+ }
+ else
+ {
+ return uTexture1.Sample(uSampler1, src.vPosition.xy / uSamplerSize);
+ }
}
";
@@ -167,8 +212,9 @@ void main()
public const string ImGuiPixelShader_gl = @"
//opengl 3.2
#version 150
-uniform bool uSamplerEnable;
-uniform sampler2D uSampler0;
+uniform bool uSamplerEnable, uBlendPass, uBlendEnable;
+uniform vec2 uSamplerSize;
+uniform sampler2D uSampler0, uSampler1;
in vec2 vTexcoord0;
in vec4 vColor0;
@@ -177,9 +223,37 @@ out vec4 FragColor;
void main()
{
- vec4 temp = vColor0;
- if(uSamplerEnable) temp *= texture(uSampler0, vTexcoord0);
- FragColor = temp;
+ if (uBlendPass)
+ {
+ vec4 temp = vColor0;
+ if(uSamplerEnable) temp *= texture(uSampler0, vTexcoord0);
+
+ if (uBlendEnable)
+ {
+ if (temp.a != 1.0)
+ {
+ vec4 prev = texture(uSampler1, gl_FragCoord.xy / uSamplerSize);
+ if (temp.a == 0.0)
+ {
+ temp = prev;
+ }
+ else
+ {
+ float alpha = prev.a + temp.a - (prev.a * temp.a);
+ temp.r = ((temp.r * temp.a) + (prev.r * prev.a * (1.0 - temp.a))) / alpha;
+ temp.g = ((temp.g * temp.a) + (prev.g * prev.a * (1.0 - temp.a))) / alpha;
+ temp.b = ((temp.b * temp.a) + (prev.b * prev.a * (1.0 - temp.a))) / alpha;
+ temp.a = alpha;
+ }
+ }
+ }
+
+ FragColor = temp;
+ }
+ else
+ {
+ FragColor = texture(uSampler1, gl_FragCoord.xy / uSamplerSize);
+ }
}";
}
}
diff --git a/src/BizHawk.Bizware.Graphics/Interfaces/IGL.cs b/src/BizHawk.Bizware.Graphics/Interfaces/IGL.cs
index b08b6c4836..9ee78ed56e 100644
--- a/src/BizHawk.Bizware.Graphics/Interfaces/IGL.cs
+++ b/src/BizHawk.Bizware.Graphics/Interfaces/IGL.cs
@@ -62,13 +62,7 @@ namespace BizHawk.Bizware.Graphics
///
/// Enables normal (non-premultiplied) alpha blending.
///
- void EnableBlendNormal();
-
- ///
- /// Enables alpha blending (non-alpha values are copied from the source fragment).
- /// This mimics GDI+ blending
- ///
- void EnableBlendAlpha();
+ void EnableBlending();
///
/// Disables blending (alpha values are copied from the source fragment)
diff --git a/src/BizHawk.Bizware.Graphics/OpenGL/IGL_OpenGL.cs b/src/BizHawk.Bizware.Graphics/OpenGL/IGL_OpenGL.cs
index 85c18dccd5..c59fe4b233 100644
--- a/src/BizHawk.Bizware.Graphics/OpenGL/IGL_OpenGL.cs
+++ b/src/BizHawk.Bizware.Graphics/OpenGL/IGL_OpenGL.cs
@@ -58,20 +58,13 @@ namespace BizHawk.Bizware.Graphics
GL.Clear(ClearBufferMask.ColorBufferBit);
}
- public void EnableBlendNormal()
+ public void EnableBlending()
{
GL.Enable(EnableCap.Blend);
GL.BlendEquation(GLEnum.FuncAdd);
GL.BlendFuncSeparate(BlendingFactor.SrcAlpha, BlendingFactor.OneMinusSrcAlpha, BlendingFactor.One, BlendingFactor.OneMinusSrcAlpha);
}
- public void EnableBlendAlpha()
- {
- GL.Enable(EnableCap.Blend);
- GL.BlendEquation(GLEnum.FuncAdd);
- GL.BlendFuncSeparate(BlendingFactor.One, BlendingFactor.Zero, BlendingFactor.One, BlendingFactor.OneMinusSrcAlpha);
- }
-
public void DisableBlending()
=> GL.Disable(EnableCap.Blend);
diff --git a/src/BizHawk.Bizware.Graphics/Renderers/GDIPlusGuiRenderer.cs b/src/BizHawk.Bizware.Graphics/Renderers/GDIPlusGuiRenderer.cs
index dfd621c31b..1724ac3c01 100644
--- a/src/BizHawk.Bizware.Graphics/Renderers/GDIPlusGuiRenderer.cs
+++ b/src/BizHawk.Bizware.Graphics/Renderers/GDIPlusGuiRenderer.cs
@@ -87,7 +87,7 @@ namespace BizHawk.Bizware.Graphics
}
public void EnableBlending()
- => Owner.EnableBlendNormal();
+ => Owner.EnableBlending();
public void DisableBlending()
=> Owner.DisableBlending();
diff --git a/src/BizHawk.Bizware.Graphics/Renderers/GuiRenderer.cs b/src/BizHawk.Bizware.Graphics/Renderers/GuiRenderer.cs
index e9781a46f5..3252adc24f 100644
--- a/src/BizHawk.Bizware.Graphics/Renderers/GuiRenderer.cs
+++ b/src/BizHawk.Bizware.Graphics/Renderers/GuiRenderer.cs
@@ -116,7 +116,7 @@ namespace BizHawk.Bizware.Graphics
public void EnableBlending()
{
Flush();
- Owner.EnableBlendNormal();
+ Owner.EnableBlending();
}
public void DisableBlending()
diff --git a/src/BizHawk.Bizware.Graphics/Renderers/ImGui2DRenderer.cs b/src/BizHawk.Bizware.Graphics/Renderers/ImGui2DRenderer.cs
index 0ec1adc910..05905765f2 100644
--- a/src/BizHawk.Bizware.Graphics/Renderers/ImGui2DRenderer.cs
+++ b/src/BizHawk.Bizware.Graphics/Renderers/ImGui2DRenderer.cs
@@ -53,6 +53,8 @@ namespace BizHawk.Bizware.Graphics
}
private readonly HashSet _gcHandles = [ ];
+ private ITexture2D _stringTexture;
+ private IRenderTarget _pass1RenderTarget;
protected virtual float RenderThickness => 1;
@@ -63,8 +65,7 @@ namespace BizHawk.Bizware.Graphics
protected bool _hasClearPending;
protected Bitmap _stringOutput;
protected SDGraphics _stringGraphics;
- protected ITexture2D _stringTexture;
- protected IRenderTarget _renderTarget;
+ protected IRenderTarget _pass2RenderTarget;
public ImGui2DRenderer(IGL igl, ImGuiResourceCache resourceCache)
{
@@ -83,8 +84,10 @@ namespace BizHawk.Bizware.Graphics
public void Dispose()
{
ClearGCHandles();
- _renderTarget?.Dispose();
- _renderTarget = null;
+ _pass2RenderTarget?.Dispose();
+ _pass2RenderTarget = null;
+ _pass1RenderTarget?.Dispose();
+ _pass1RenderTarget = null;
_stringTexture?.Dispose();
_stringTexture = null;
_stringGraphics?.Dispose();
@@ -160,21 +163,34 @@ namespace BizHawk.Bizware.Graphics
{
None,
DisableBlending,
- EnableBlendAlpha,
- EnableBlendNormal,
+ EnableBlending,
DrawString,
}
+ private void PerformPasses(ImDrawCmdPtr cmd)
+ {
+ if (EnableBlending)
+ {
+ _pass1RenderTarget.Bind();
+ _resourceCache.SetBlendingParamters(_pass2RenderTarget, false);
+ _igl.DrawIndexed((int)cmd.ElemCount, (int)cmd.IdxOffset, (int)cmd.VtxOffset);
+
+ _pass2RenderTarget.Bind();
+ _resourceCache.SetBlendingParamters(_pass1RenderTarget, true);
+ _igl.DrawIndexed((int)cmd.ElemCount, (int)cmd.IdxOffset, (int)cmd.VtxOffset);
+ }
+ else
+ {
+ _resourceCache.SetBlendingParamters(null, true);
+ _igl.DrawIndexed((int)cmd.ElemCount, (int)cmd.IdxOffset, (int)cmd.VtxOffset);
+ }
+ }
+
protected virtual void RenderInternal(int width, int height)
{
- if (EnableBlending)
- {
- _igl.EnableBlendAlpha();
- }
- else
- {
- _igl.DisableBlending();
- }
+ // we handle blending programmatically with 2 passes
+ // therefore, we disable normal blending operations
+ _igl.DisableBlending();
_igl.BindPipeline(_resourceCache.Pipeline);
_resourceCache.SetProjection(width, height);
@@ -229,21 +245,16 @@ namespace BizHawk.Bizware.Graphics
_resourceCache.SetTexture(null);
}
- _igl.DrawIndexed((int)cmd.ElemCount, (int)cmd.IdxOffset, (int)cmd.VtxOffset);
+ PerformPasses(cmd);
tempTex?.Dispose();
break;
}
case DrawCallbackId.DisableBlending:
- _igl.DisableBlending();
EnableBlending = false;
break;
- case DrawCallbackId.EnableBlendAlpha:
- _igl.EnableBlendAlpha();
+ case DrawCallbackId.EnableBlending:
EnableBlending = true;
break;
- case DrawCallbackId.EnableBlendNormal:
- _igl.EnableBlendNormal();
- break;
case DrawCallbackId.DrawString:
{
var stringArgs = (DrawStringArgs)GCHandle.FromIntPtr(cmd.UserCallbackData).Target!;
@@ -264,21 +275,9 @@ namespace BizHawk.Bizware.Graphics
throw new InvalidOperationException("Unexpected bitmap mismatch!");
}
- // we want to normal blend the text image rather than alpha blend it (matches GDI+ behavior it seems?)
- if (EnableBlending)
- {
- _igl.EnableBlendNormal();
- }
-
- _stringTexture.LoadFrom(new BitmapBuffer(userTex.Bitmap, new()));
+ _stringTexture.LoadFrom(new BitmapBuffer(_stringOutput, new()));
_resourceCache.SetTexture(_stringTexture);
- _igl.DrawIndexed((int)lastCmd.ElemCount, (int)lastCmd.IdxOffset, (int)lastCmd.VtxOffset);
-
- if (EnableBlending)
- {
- _igl.EnableBlendAlpha();
- }
-
+ PerformPasses(lastCmd);
ClearStringOutput();
}
@@ -294,10 +293,12 @@ namespace BizHawk.Bizware.Graphics
{
var needsRender = _imGuiDrawList.VtxBuffer.Size > 0 || _imGuiDrawList.IdxBuffer.Size > 0 || _hasDrawStringCommand;
var needsClear = needsRender || _hasClearPending;
- if (_renderTarget == null || _renderTarget.Width != width || _renderTarget.Height != height)
+ if (_pass1RenderTarget == null || _pass1RenderTarget.Width != width || _pass1RenderTarget.Height != height)
{
- _renderTarget?.Dispose();
- _renderTarget = _igl.CreateRenderTarget(width, height);
+ _pass1RenderTarget?.Dispose();
+ _pass1RenderTarget = _igl.CreateRenderTarget(width, height);
+ _pass2RenderTarget?.Dispose();
+ _pass2RenderTarget = _igl.CreateRenderTarget(width, height);
needsClear = true;
}
@@ -314,7 +315,7 @@ namespace BizHawk.Bizware.Graphics
_stringTexture = _igl.CreateTexture(width, height);
}
- _renderTarget.Bind();
+ _pass2RenderTarget.Bind();
_igl.SetViewport(width, height);
if (needsClear)
@@ -347,7 +348,7 @@ namespace BizHawk.Bizware.Graphics
ResetDrawList();
}
- return _renderTarget;
+ return _pass2RenderTarget;
}
public void Clear()
@@ -375,7 +376,7 @@ namespace BizHawk.Bizware.Graphics
break;
// CompositingMode.SourceOver means enable blending
case false when value == CompositingMode.SourceOver:
- _imGuiDrawList.AddCallback((IntPtr)DrawCallbackId.EnableBlendAlpha, IntPtr.Zero);
+ _imGuiDrawList.AddCallback((IntPtr)DrawCallbackId.EnableBlending, IntPtr.Zero);
_pendingBlendEnable = true;
break;
}
@@ -384,6 +385,11 @@ namespace BizHawk.Bizware.Graphics
public void DrawBezier(Color color, Point pt1, Point pt2, Point pt3, Point pt4)
{
+ if (color.A != 0xFF)
+ {
+ _imGuiDrawList.AddDrawCmd();
+ }
+
_imGuiDrawList.AddBezierCubic(
p1: pt1.ToVector(),
p2: pt2.ToVector(),
@@ -391,6 +397,11 @@ namespace BizHawk.Bizware.Graphics
p4: pt4.ToVector(),
col: (uint)color.ToArgb(),
thickness: RenderThickness);
+
+ if (color.A != 0xFF)
+ {
+ _imGuiDrawList.AddDrawCmd();
+ }
}
public void DrawBeziers(Color color, Point[] points)
@@ -404,6 +415,11 @@ namespace BizHawk.Bizware.Graphics
var col = (uint)color.ToArgb();
for (var i = 1; i < points.Length; i += 3)
{
+ if (color.A != 0xFF)
+ {
+ _imGuiDrawList.AddDrawCmd();
+ }
+
_imGuiDrawList.AddBezierCubic(
p1: startPt.ToVector(),
p2: points[i + 0].ToVector(),
@@ -412,11 +428,21 @@ namespace BizHawk.Bizware.Graphics
col: col,
thickness: RenderThickness);
startPt = points[i + 2];
+
+ if (color.A != 0xFF)
+ {
+ _imGuiDrawList.AddDrawCmd();
+ }
}
}
public void DrawRectangle(Color color, int x, int y, int width, int height)
{
+ if (color.A != 0xFF)
+ {
+ _imGuiDrawList.AddDrawCmd();
+ }
+
// we don't use AddRect as we want to avoid double drawing at the corners
// as that produces artifacts with alpha blending
@@ -428,30 +454,56 @@ namespace BizHawk.Bizware.Graphics
if (width == 1 || height == 1)
{
// width or height of 1 is just a single line
- DrawLine(color, x, y, right, bottom);
+ DrawLineInternal(color, x, y, right, bottom);
+
+ if (color.A != 0xFF)
+ {
+ _imGuiDrawList.AddDrawCmd();
+ }
+
return;
}
// top left to top right
- DrawLine(color, x, y, right, y);
+ DrawLineInternal(color, x, y, right, y);
// top right (and 1 pixel down) to bottom right
- DrawLine(color, right, y + 1, right, bottom);
+ DrawLineInternal(color, right, y + 1, right, bottom);
// bottom right (and 1 pixel left) to bottom left
- DrawLine(color, right - 1, bottom, x, bottom);
+ DrawLineInternal(color, right - 1, bottom, x, bottom);
// bottom left (and 1 pixel up) to top left (and 1 pixel down)
- DrawLine(color, x, bottom - 1, x, y + 1);
+ DrawLineInternal(color, x, bottom - 1, x, y + 1);
+
+ if (color.A != 0xFF)
+ {
+ _imGuiDrawList.AddDrawCmd();
+ }
}
public void FillRectangle(Color color, int x, int y, int width, int height)
{
+ if (color.A != 0xFF)
+ {
+ _imGuiDrawList.AddDrawCmd();
+ }
+
_imGuiDrawList.AddRectFilled(
p_min: new(x, y),
p_max: new(x + width, y + height),
col: (uint)color.ToArgb());
+
+ if (color.A != 0xFF)
+ {
+ _imGuiDrawList.AddDrawCmd();
+ }
}
public void DrawEllipse(Color color, int x, int y, int width, int height)
{
+ if (color.A != 0xFF)
+ {
+ _imGuiDrawList.AddDrawCmd();
+ }
+
var radius = new Vector2(width / 2.0f, height / 2.0f);
_imGuiDrawList.AddEllipse(
center: new(x + radius.X, y + radius.Y),
@@ -460,25 +512,34 @@ namespace BizHawk.Bizware.Graphics
rot: 0,
num_segments: 0,
RenderThickness);
+
+ if (color.A != 0xFF)
+ {
+ _imGuiDrawList.AddDrawCmd();
+ }
}
public void FillEllipse(Color color, int x, int y, int width, int height)
{
+ if (color.A != 0xFF)
+ {
+ _imGuiDrawList.AddDrawCmd();
+ }
+
var radius = new Vector2(width / 2.0f, height / 2.0f);
_imGuiDrawList.AddEllipseFilled(
center: new(x + radius.X, y + radius.Y),
radius: radius,
col: (uint)color.ToArgb());
+
+ if (color.A != 0xFF)
+ {
+ _imGuiDrawList.AddDrawCmd();
+ }
}
public void DrawImage(Bitmap image, int x, int y)
{
- // use normal blending for images
- if (_pendingBlendEnable)
- {
- _imGuiDrawList.AddCallback((IntPtr)DrawCallbackId.EnableBlendNormal, IntPtr.Zero);
- }
-
var texture = new ImGuiUserTexture { Bitmap = image, WantCache = false };
var handle = GCHandle.Alloc(texture, GCHandleType.Normal);
_gcHandles.Add(handle);
@@ -486,21 +547,10 @@ namespace BizHawk.Bizware.Graphics
user_texture_id: GCHandle.ToIntPtr(handle),
p_min: new(x, y),
p_max: new(x + image.Width, y + image.Height));
-
- if (_pendingBlendEnable)
- {
- _imGuiDrawList.AddCallback((IntPtr)DrawCallbackId.EnableBlendAlpha, IntPtr.Zero);
- }
}
public void DrawImage(Bitmap image, Rectangle destRect, int srcX, int srcY, int srcWidth, int srcHeight, bool cache)
{
- // use normal blending for images
- if (_pendingBlendEnable)
- {
- _imGuiDrawList.AddCallback((IntPtr)DrawCallbackId.EnableBlendNormal, IntPtr.Zero);
- }
-
var texture = new ImGuiUserTexture { Bitmap = image, WantCache = cache };
var handle = GCHandle.Alloc(texture, GCHandleType.Normal);
_gcHandles.Add(handle);
@@ -512,14 +562,9 @@ namespace BizHawk.Bizware.Graphics
p_max: new(destRect.Right, destRect.Bottom),
uv_min: new(srcX / imgWidth, srcY / imgHeight),
uv_max: new((srcX + srcWidth) / imgWidth, (srcY + srcHeight) / imgHeight));
-
- if (_pendingBlendEnable)
- {
- _imGuiDrawList.AddCallback((IntPtr)DrawCallbackId.EnableBlendAlpha, IntPtr.Zero);
- }
}
- public void DrawLine(Color color, int x1, int y1, int x2, int y2)
+ private void DrawLineInternal(Color color, int x1, int y1, int x2, int y2)
{
var p1 = new Vector2(x1, y1);
var p2 = new Vector2(x2, y2);
@@ -553,8 +598,28 @@ namespace BizHawk.Bizware.Graphics
_imGuiDrawList.PathStroke((uint)color.ToArgb(), 0, RenderThickness);
}
+ public void DrawLine(Color color, int x1, int y1, int x2, int y2)
+ {
+ if (color.A != 0xFF)
+ {
+ _imGuiDrawList.AddDrawCmd();
+ }
+
+ DrawLineInternal(color, x1, y1, x2, y2);
+
+ if (color.A != 0xFF)
+ {
+ _imGuiDrawList.AddDrawCmd();
+ }
+ }
+
public void DrawPie(Color color, int x, int y, int width, int height, int startAngle, int sweepAngle)
{
+ if (color.A != 0xFF)
+ {
+ _imGuiDrawList.AddDrawCmd();
+ }
+
var radius = new Vector2(width / 2.0f, height / 2.0f);
var center = new Vector2(x + radius.X, y + radius.Y);
var aMin = (float)(Math.PI / 180 * startAngle);
@@ -562,10 +627,20 @@ namespace BizHawk.Bizware.Graphics
_imGuiDrawList.PathEllipticalArcTo(center, radius, 0, aMin, aMax);
_imGuiDrawList.PathLineTo(center);
_imGuiDrawList.PathStroke((uint)color.ToArgb(), ImDrawFlags.Closed, RenderThickness);
+
+ if (color.A != 0xFF)
+ {
+ _imGuiDrawList.AddDrawCmd();
+ }
}
public void FillPie(Color color, int x, int y, int width, int height, int startAngle, int sweepAngle)
{
+ if (color.A != 0xFF)
+ {
+ _imGuiDrawList.AddDrawCmd();
+ }
+
var radius = new Vector2(width / 2.0f, height / 2.0f);
var center = new Vector2(x + radius.X, y + radius.Y);
var aMin = (float)(Math.PI / 180 * startAngle);
@@ -573,6 +648,11 @@ namespace BizHawk.Bizware.Graphics
_imGuiDrawList.PathEllipticalArcTo(center, radius, 0, aMin, aMax);
_imGuiDrawList.PathLineTo(center);
_imGuiDrawList.PathFillConvex((uint)color.ToArgb());
+
+ if (color.A != 0xFF)
+ {
+ _imGuiDrawList.AddDrawCmd();
+ }
}
public unsafe void DrawPolygon(Color color, Point[] points)
@@ -580,12 +660,22 @@ namespace BizHawk.Bizware.Graphics
var vectorPoints = Array.ConvertAll(points, static p => new Vector2(p.X + 0.5f, p.Y + 0.5f));
fixed (Vector2* p = vectorPoints)
{
+ if (color.A != 0xFF)
+ {
+ _imGuiDrawList.AddDrawCmd();
+ }
+
_imGuiDrawList.AddPolyline(
points: ref *p,
num_points: vectorPoints.Length,
col: (uint)color.ToArgb(),
flags: ImDrawFlags.Closed,
thickness: RenderThickness);
+
+ if (color.A != 0xFF)
+ {
+ _imGuiDrawList.AddDrawCmd();
+ }
}
}
@@ -594,10 +684,20 @@ namespace BizHawk.Bizware.Graphics
var vectorPoints = Array.ConvertAll(points, static p => new Vector2(p.X + 0.5f, p.Y + 0.5f));
fixed (Vector2* p = vectorPoints)
{
+ if (color.A != 0xFF)
+ {
+ _imGuiDrawList.AddDrawCmd();
+ }
+
_imGuiDrawList.AddConcavePolyFilled(
points: ref *p,
num_points: vectorPoints.Length,
col: (uint)color.ToArgb());
+
+ if (color.A != 0xFF)
+ {
+ _imGuiDrawList.AddDrawCmd();
+ }
}
}
diff --git a/src/BizHawk.Bizware.Graphics/Renderers/SDLImGui2DRenderer.cs b/src/BizHawk.Bizware.Graphics/Renderers/SDLImGui2DRenderer.cs
index 264c154610..30f1f477bc 100644
--- a/src/BizHawk.Bizware.Graphics/Renderers/SDLImGui2DRenderer.cs
+++ b/src/BizHawk.Bizware.Graphics/Renderers/SDLImGui2DRenderer.cs
@@ -102,7 +102,7 @@ namespace BizHawk.Bizware.Graphics
protected override void RenderInternal(int width, int height)
{
- var rt = (GDIPlusRenderTarget)_renderTarget;
+ var rt = (GDIPlusRenderTarget)_pass2RenderTarget;
var bmpData = rt.SDBitmap.LockBits(rt.GetRectangle(), ImageLockMode.WriteOnly, PixelFormat.Format32bppArgb);
try
{
@@ -172,8 +172,7 @@ namespace BizHawk.Bizware.Graphics
case DrawCallbackId.DisableBlending:
_ = SDL_SetRenderDrawBlendMode(sdlRenderer, SDL_BlendMode.SDL_BLENDMODE_NONE);
break;
- case DrawCallbackId.EnableBlendAlpha:
- case DrawCallbackId.EnableBlendNormal:
+ case DrawCallbackId.EnableBlending:
_ = SDL_SetRenderDrawBlendMode(sdlRenderer, SDL_BlendMode.SDL_BLENDMODE_BLEND);
break;
case DrawCallbackId.DrawString: