2014-12-07 02:26:52 +00:00
|
|
|
//this is full of bugs probably, related to state from old rendering sessions being all messed up. its only barely good enough to work at all
|
|
|
|
|
|
|
|
using System;
|
|
|
|
using System.Diagnostics;
|
|
|
|
using System.Collections;
|
|
|
|
using System.Collections.Generic;
|
|
|
|
using sd = System.Drawing;
|
|
|
|
using System.Drawing.Imaging;
|
|
|
|
|
|
|
|
using OpenTK;
|
|
|
|
using OpenTK.Graphics.OpenGL;
|
|
|
|
|
|
|
|
namespace BizHawk.Bizware.BizwareGL.Drivers.GdiPlus
|
|
|
|
{
|
|
|
|
public class GDIPlusGuiRenderer : IGuiRenderer
|
|
|
|
{
|
|
|
|
public GDIPlusGuiRenderer(IGL_GdiPlus gl)
|
|
|
|
{
|
|
|
|
Owner = gl;
|
|
|
|
Gdi = gl as IGL_GdiPlus;
|
|
|
|
}
|
|
|
|
|
|
|
|
OpenTK.Graphics.Color4[] CornerColors = new OpenTK.Graphics.Color4[4] {
|
|
|
|
new OpenTK.Graphics.Color4(1.0f,1.0f,1.0f,1.0f),new OpenTK.Graphics.Color4(1.0f,1.0f,1.0f,1.0f),new OpenTK.Graphics.Color4(1.0f,1.0f,1.0f,1.0f),new OpenTK.Graphics.Color4(1.0f,1.0f,1.0f,1.0f)
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
public void SetCornerColor(int which, OpenTK.Graphics.Color4 color)
|
|
|
|
{
|
|
|
|
CornerColors[which] = color;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public void SetCornerColors(OpenTK.Graphics.Color4[] colors)
|
|
|
|
{
|
|
|
|
Flush(); //dont really need to flush with current implementation. we might as well roll modulate color into it too.
|
|
|
|
if (colors.Length != 4) throw new ArgumentException("array must be size 4", "colors");
|
|
|
|
for (int i = 0; i < 4; i++)
|
|
|
|
CornerColors[i] = colors[i];
|
|
|
|
}
|
|
|
|
|
|
|
|
public void Dispose()
|
|
|
|
{
|
|
|
|
if (CurrentImageAttributes != null)
|
|
|
|
CurrentImageAttributes.Dispose();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public void SetPipeline(Pipeline pipeline)
|
|
|
|
{
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
public void SetDefaultPipeline()
|
|
|
|
{
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
public void SetModulateColorWhite()
|
|
|
|
{
|
|
|
|
SetModulateColor(sd.Color.White);
|
|
|
|
}
|
|
|
|
|
|
|
|
ImageAttributes CurrentImageAttributes;
|
|
|
|
public void SetModulateColor(sd.Color color)
|
|
|
|
{
|
|
|
|
//white is really no color at all
|
|
|
|
if (color.ToArgb() == sd.Color.White.ToArgb())
|
|
|
|
{
|
|
|
|
CurrentImageAttributes.ClearColorMatrix(ColorAdjustType.Bitmap);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
float r = color.R / 255.0f;
|
|
|
|
float g = color.G / 255.0f;
|
|
|
|
float b = color.B / 255.0f;
|
|
|
|
float a = color.A / 255.0f;
|
|
|
|
|
|
|
|
float[][] colorMatrixElements = {
|
|
|
|
new float[] {r, 0, 0, 0, 0},
|
|
|
|
new float[] {0, g, 0, 0, 0},
|
|
|
|
new float[] {0, 0, b, 0, 0},
|
|
|
|
new float[] {0, 0, 0, a, 0},
|
|
|
|
new float[] {0, 0, 0, 0, 1}};
|
|
|
|
|
|
|
|
ColorMatrix colorMatrix = new ColorMatrix(colorMatrixElements);
|
|
|
|
CurrentImageAttributes.SetColorMatrix(colorMatrix,ColorMatrixFlag.Default, ColorAdjustType.Bitmap);
|
|
|
|
}
|
|
|
|
|
|
|
|
sd.Color CurrentModulateColor = sd.Color.White;
|
|
|
|
|
2014-12-13 23:04:22 +00:00
|
|
|
IBlendState CurrentBlendState;
|
2014-12-07 02:26:52 +00:00
|
|
|
public void SetBlendState(IBlendState rsBlend)
|
|
|
|
{
|
2014-12-13 23:04:22 +00:00
|
|
|
CurrentBlendState = rsBlend;
|
2014-12-07 02:26:52 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
MatrixStack _Projection, _Modelview;
|
|
|
|
public MatrixStack Projection
|
|
|
|
{
|
|
|
|
get { return _Projection; }
|
|
|
|
set
|
|
|
|
{
|
|
|
|
_Projection = value;
|
|
|
|
_Projection.IsDirty = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
public MatrixStack Modelview
|
|
|
|
{
|
|
|
|
get { return _Modelview; }
|
|
|
|
set
|
|
|
|
{
|
|
|
|
_Modelview = value;
|
|
|
|
_Modelview.IsDirty = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public void Begin(sd.Size size) { Begin(size.Width, size.Height); }
|
|
|
|
|
|
|
|
|
2015-08-30 14:19:49 +00:00
|
|
|
public void Begin(int width, int height)
|
2014-12-07 02:26:52 +00:00
|
|
|
{
|
|
|
|
Begin();
|
|
|
|
|
2014-12-13 23:04:22 +00:00
|
|
|
CurrentBlendState = Gdi.BlendNormal;
|
|
|
|
|
2014-12-07 02:26:52 +00:00
|
|
|
Projection = Owner.CreateGuiProjectionMatrix(width, height);
|
|
|
|
Modelview = Owner.CreateGuiViewMatrix(width, height);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public void Begin()
|
|
|
|
{
|
|
|
|
//uhhmmm I want to throw an exception if its already active, but its annoying.
|
|
|
|
IsActive = true;
|
|
|
|
CurrentImageAttributes = new ImageAttributes();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public void Flush()
|
|
|
|
{
|
|
|
|
//no batching, nothing to do here yet
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public void End()
|
|
|
|
{
|
|
|
|
if (!IsActive)
|
|
|
|
throw new InvalidOperationException("GuiRenderer is not active!");
|
|
|
|
IsActive = false;
|
|
|
|
if (CurrentImageAttributes != null)
|
|
|
|
{
|
|
|
|
CurrentImageAttributes.Dispose();
|
|
|
|
CurrentImageAttributes = null;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public void RectFill(float x, float y, float w, float h)
|
|
|
|
{
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public void DrawSubrect(Texture2d tex, float x, float y, float w, float h, float u0, float v0, float u1, float v1)
|
|
|
|
{
|
2015-08-29 07:26:08 +00:00
|
|
|
var tw = tex.Opaque as IGL_GdiPlus.TextureWrapper;
|
2014-12-07 02:26:52 +00:00
|
|
|
var g = Gdi.GetCurrentGraphics();
|
2015-08-29 07:26:08 +00:00
|
|
|
PrepDraw(g, tex);
|
2015-07-26 02:06:43 +00:00
|
|
|
SetupMatrix(g);
|
|
|
|
|
2014-12-07 02:26:52 +00:00
|
|
|
float x0 = u0 * tex.Width;
|
|
|
|
float y0 = v0 * tex.Height;
|
|
|
|
float x1 = u1 * tex.Width;
|
|
|
|
float y1 = v1 * tex.Height;
|
2015-07-25 22:25:10 +00:00
|
|
|
|
2014-12-07 02:26:52 +00:00
|
|
|
sd.PointF[] destPoints = new sd.PointF[] {
|
2015-07-26 02:06:43 +00:00
|
|
|
new sd.PointF(x,y),
|
|
|
|
new sd.PointF(x+w,y),
|
|
|
|
new sd.PointF(x,y+h),
|
2014-12-07 02:26:52 +00:00
|
|
|
};
|
2014-12-13 23:04:22 +00:00
|
|
|
|
2014-12-07 02:26:52 +00:00
|
|
|
g.DrawImage(tw.SDBitmap, destPoints, new sd.RectangleF(x0, y0, x1 - x0, y1 - y0), sd.GraphicsUnit.Pixel, CurrentImageAttributes);
|
2015-07-26 02:06:43 +00:00
|
|
|
g.Transform = new sd.Drawing2D.Matrix(); //.Reset() doesnt work ? ?
|
2014-12-07 02:26:52 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public void Draw(Art art) { DrawInternal(art, 0, 0, art.Width, art.Height, false, false); }
|
|
|
|
public void Draw(Art art, float x, float y) { DrawInternal(art, x, y, art.Width, art.Height, false, false); }
|
|
|
|
public void Draw(Art art, float x, float y, float width, float height) { DrawInternal(art, x, y, width, height, false, false); }
|
|
|
|
public void Draw(Art art, Vector2 pos) { DrawInternal(art, pos.X, pos.Y, art.Width, art.Height, false, false); }
|
|
|
|
public void Draw(Texture2d tex) { DrawInternal(tex, 0, 0, tex.Width, tex.Height); }
|
|
|
|
public void Draw(Texture2d tex, float x, float y) { DrawInternal(tex, x, y, tex.Width, tex.Height); }
|
|
|
|
public void DrawFlipped(Art art, bool xflip, bool yflip) { DrawInternal(art, 0, 0, art.Width, art.Height, xflip, yflip); }
|
|
|
|
|
|
|
|
public void Draw(Texture2d art, float x, float y, float width, float height)
|
|
|
|
{
|
|
|
|
DrawInternal(art, x, y, width, height);
|
|
|
|
}
|
|
|
|
|
2015-08-29 07:26:08 +00:00
|
|
|
void PrepDraw(sd.Graphics g, Texture2d tex)
|
2014-12-07 02:26:52 +00:00
|
|
|
{
|
2015-08-29 07:26:08 +00:00
|
|
|
var tw = tex.Opaque as IGL_GdiPlus.TextureWrapper;
|
2014-12-07 02:26:52 +00:00
|
|
|
//TODO - we can support bicubic for the final presentation..
|
|
|
|
if ((int)tw.MagFilter != (int)tw.MinFilter)
|
|
|
|
throw new InvalidOperationException("tw.MagFilter != tw.MinFilter");
|
|
|
|
if (tw.MagFilter == TextureMagFilter.Linear)
|
|
|
|
g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.Bilinear;
|
|
|
|
if (tw.MagFilter == TextureMagFilter.Nearest)
|
|
|
|
g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.NearestNeighbor;
|
2014-12-13 23:04:22 +00:00
|
|
|
|
|
|
|
|
|
|
|
//---------
|
|
|
|
|
|
|
|
if (CurrentBlendState == Gdi.BlendNormal)
|
|
|
|
{
|
|
|
|
g.CompositingMode = sd.Drawing2D.CompositingMode.SourceOver;
|
|
|
|
g.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.Default; //?
|
|
|
|
|
|
|
|
//CurrentImageAttributes.ClearColorMatrix(ColorAdjustType.Bitmap);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
//if(CurrentBlendState == Gdi.BlendNoneCopy)
|
|
|
|
//if(CurrentBlendState == Gdi.BlendNoneOpaque)
|
|
|
|
{
|
|
|
|
g.CompositingMode = sd.Drawing2D.CompositingMode.SourceCopy;
|
|
|
|
g.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighSpeed;
|
|
|
|
|
|
|
|
//WARNING : DO NOT USE COLOR MATRIX TO WIPE THE ALPHA
|
|
|
|
//ITS SOOOOOOOOOOOOOOOOOOOOOOOOOOOO SLOW
|
|
|
|
//instead, we added kind of hacky support for 24bpp images
|
|
|
|
}
|
|
|
|
|
2014-12-07 02:26:52 +00:00
|
|
|
}
|
|
|
|
|
2015-07-26 02:06:43 +00:00
|
|
|
private void SetupMatrix(sd.Graphics g)
|
2014-12-07 02:26:52 +00:00
|
|
|
{
|
2015-08-30 14:19:49 +00:00
|
|
|
//projection is always identity, so who cares i guess
|
|
|
|
//Matrix4 mat = Projection.Top * Modelview.Top;
|
|
|
|
Matrix4 mat = Modelview.Top;
|
2015-07-26 02:06:43 +00:00
|
|
|
g.Transform = new sd.Drawing2D.Matrix(mat.M11, mat.M12, mat.M21, mat.M22, mat.M41, mat.M42);
|
|
|
|
}
|
|
|
|
|
|
|
|
unsafe void DrawInternal(Texture2d tex, float x, float y, float w, float h)
|
|
|
|
{
|
|
|
|
var g = Gdi.GetCurrentGraphics();
|
2015-08-29 07:26:08 +00:00
|
|
|
PrepDraw(g, tex);
|
2015-07-26 02:06:43 +00:00
|
|
|
|
|
|
|
SetupMatrix(g);
|
|
|
|
|
2015-07-25 22:25:10 +00:00
|
|
|
sd.PointF[] destPoints = new sd.PointF[] {
|
2015-07-26 02:06:43 +00:00
|
|
|
new sd.PointF(x,y),
|
|
|
|
new sd.PointF(x+w,y),
|
|
|
|
new sd.PointF(x,y+h),
|
2015-07-25 22:25:10 +00:00
|
|
|
};
|
|
|
|
|
2015-08-29 07:26:08 +00:00
|
|
|
var tw = tex.Opaque as IGL_GdiPlus.TextureWrapper;
|
2015-07-26 02:06:43 +00:00
|
|
|
g.PixelOffsetMode = sd.Drawing2D.PixelOffsetMode.Half;
|
2015-07-25 22:25:10 +00:00
|
|
|
g.DrawImage(tw.SDBitmap, destPoints, new sd.RectangleF(0, 0, tex.Width, tex.Height), sd.GraphicsUnit.Pixel, CurrentImageAttributes);
|
2015-07-26 02:06:43 +00:00
|
|
|
g.Transform = new sd.Drawing2D.Matrix(); //.Reset() doesnt work ? ?
|
2014-12-07 02:26:52 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
unsafe void DrawInternal(Art art, float x, float y, float w, float h, bool fx, bool fy)
|
|
|
|
{
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public bool IsActive { get; private set; }
|
|
|
|
public IGL Owner { get; private set; }
|
|
|
|
public IGL_GdiPlus Gdi;
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|