1
1
mirror of https://github.com/OpenDiablo2/OpenDiablo2 synced 2024-09-28 14:16:01 -04:00

Tons of performance gained.

This commit is contained in:
Tim Sarbin 2018-11-23 15:22:35 -05:00
parent 8f1d43863d
commit e348d7b1e1
5 changed files with 78 additions and 65 deletions

View File

@ -26,15 +26,15 @@ namespace OpenDiablo2.Common.Models
ImageData = new Int16[0]; ImageData = new Int16[0];
} }
public Color GetColor(int x, int y, Palette palette) public UInt32 GetColor(int x, int y, Palette palette)
{ {
var index = ImageData[x + (y * Width)]; var index = ImageData[x + (y * Width)];
if (index == -1) if (index == -1)
return Color.Transparent; return 0;
var color = palette.Colors[(int)index]; var color = palette.Colors[index];
return Color.FromArgb(255, color.R, color.G, color.B); return ((UInt32)255 << 24) + ((UInt32)color.R << 16) + ((UInt32)color.G << 8) + (UInt32)color.B;
} }
} }

View File

@ -13,6 +13,7 @@ namespace OpenDiablo2.Core
{ {
private readonly GlobalConfiguration globalConfiguration; private readonly GlobalConfiguration globalConfiguration;
private readonly MPQ[] mpqs; private readonly MPQ[] mpqs;
private Dictionary<string, int> mpqLookup = new Dictionary<string, int>();
public MPQProvider(GlobalConfiguration globalConfiguration) public MPQProvider(GlobalConfiguration globalConfiguration)
{ {
@ -22,12 +23,22 @@ namespace OpenDiablo2.Core
.Where(x => !Path.GetFileName(x).StartsWith("patch")) .Where(x => !Path.GetFileName(x).StartsWith("patch"))
.Select(file => new MPQ(file)) .Select(file => new MPQ(file))
.ToArray(); .ToArray();
for(var i = 0; i < mpqs.Count(); i++)
{
foreach(var file in mpqs[i].Files)
{
mpqLookup[file.ToLower()] = i;
}
}
} }
public IEnumerable<MPQ> GetMPQs() => mpqs; public IEnumerable<MPQ> GetMPQs() => mpqs;
public Stream GetStream(string fileName) public Stream GetStream(string fileName)
=> mpqs.First(x => x.Files.Any(z =>z.ToLower() == fileName.ToLower())).OpenFile(fileName); {
return mpqs[mpqLookup[fileName.ToLower()]].OpenFile(fileName);
}
public IEnumerable<IEnumerable<string>> GetTextFile(string fileName) public IEnumerable<IEnumerable<string>> GetTextFile(string fileName)
{ {

View File

@ -111,8 +111,9 @@ namespace OpenDiablo2.SDL2_
h = font.sprite.FrameSize.Height h = font.sprite.FrameSize.Height
}; };
SDL.SDL_SetTextureColorMod(font.sprite.textures[character], TextColor.R, TextColor.G, TextColor.B); font.sprite.Frame = character;
SDL.SDL_RenderCopy(renderer, font.sprite.textures[character], IntPtr.Zero, ref rect); SDL.SDL_SetTextureColorMod(font.sprite.texture, TextColor.R, TextColor.G, TextColor.B);
SDL.SDL_RenderCopy(renderer, font.sprite.texture, IntPtr.Zero, ref rect);
} }

View File

@ -70,6 +70,8 @@ namespace OpenDiablo2.SDL2_
public void Clear() public void Clear()
{ {
SDL.SDL_SetRenderTarget(renderer, IntPtr.Zero);
SDL.SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);
SDL.SDL_RenderClear(renderer); SDL.SDL_RenderClear(renderer);
} }
@ -148,7 +150,7 @@ namespace OpenDiablo2.SDL2_
w = spr.FrameSize.Width, w = spr.FrameSize.Width,
h = spr.FrameSize.Height h = spr.FrameSize.Height
}; };
SDL.SDL_RenderCopy(renderer, spr.textures[spr.Frame], IntPtr.Zero, ref destRect); SDL.SDL_RenderCopy(renderer, spr.texture, IntPtr.Zero, ref destRect);
} }
@ -162,9 +164,7 @@ namespace OpenDiablo2.SDL2_
for (var x = 0; x < xSegments; x++) for (var x = 0; x < xSegments; x++)
{ {
var textureIndex = x + (y * xSegments) + (offset * xSegments * ySegments); var textureIndex = x + (y * xSegments) + (offset * xSegments * ySegments);
textureIndex = Math.Min(spr.textures.Count() - 1, Math.Max(0, textureIndex)); spr.Frame = Math.Min(spr.TotalFrames - 1, Math.Max(0, textureIndex));
if (textureIndex >= spr.textures.Count())
continue;
var destRect = new SDL.SDL_Rect var destRect = new SDL.SDL_Rect
{ {
@ -173,7 +173,7 @@ namespace OpenDiablo2.SDL2_
w = spr.FrameSize.Width, w = spr.FrameSize.Width,
h = spr.FrameSize.Height h = spr.FrameSize.Height
}; };
SDL.SDL_RenderCopy(renderer, spr.textures[textureIndex], IntPtr.Zero, ref destRect); SDL.SDL_RenderCopy(renderer, spr.texture, IntPtr.Zero, ref destRect);
} }
} }
} }

View File

@ -1,14 +1,10 @@
using OpenDiablo2.Common.Interfaces; using System;
using System;
using System.Collections.Generic;
using System.Drawing; using System.Drawing;
using System.IO;
using System.Linq; using System.Linq;
using System.Text;
using System.Threading.Tasks;
using SDL2;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using OpenDiablo2.Common.Interfaces;
using OpenDiablo2.Common.Models; using OpenDiablo2.Common.Models;
using SDL2;
namespace OpenDiablo2.SDL2_ namespace OpenDiablo2.SDL2_
{ {
@ -16,16 +12,24 @@ namespace OpenDiablo2.SDL2_
{ {
static readonly log4net.ILog log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); static readonly log4net.ILog log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
internal readonly ImageSet source;
private readonly IntPtr renderer;
internal IntPtr texture = IntPtr.Zero;
public Point Location { get; set; } = new Point(); public Point Location { get; set; } = new Point();
public Size FrameSize { get; set; } = new Size(); public Size FrameSize { get; set; } = new Size();
private int frame; private int frame = -1;
public int Frame public int Frame
{ {
get => frame; get => frame;
set set
{ {
if (frame == value && texture != IntPtr.Zero)
return;
frame = Math.Max(0, Math.Min(value, TotalFrames)); frame = Math.Max(0, Math.Min(value, TotalFrames));
LoadFrame(frame);
} }
} }
public int TotalFrames { get; internal set; } public int TotalFrames { get; internal set; }
@ -37,9 +41,7 @@ namespace OpenDiablo2.SDL2_
set set
{ {
blend = value; blend = value;
SDL.SDL_SetTextureBlendMode(texture, blend ? SDL.SDL_BlendMode.SDL_BLENDMODE_ADD : SDL.SDL_BlendMode.SDL_BLENDMODE_BLEND);
foreach (var texture in textures)
SDL.SDL_SetTextureBlendMode(texture, blend ? SDL.SDL_BlendMode.SDL_BLENDMODE_ADD : SDL.SDL_BlendMode.SDL_BLENDMODE_BLEND);
} }
} }
@ -53,9 +55,7 @@ namespace OpenDiablo2.SDL2_
UpdateTextureData(); UpdateTextureData();
} }
} }
internal readonly ImageSet source;
private readonly IntPtr renderer;
internal IntPtr[] textures = new IntPtr[0];
public SDL2Sprite(ImageSet source, IntPtr renderer) public SDL2Sprite(ImageSet source, IntPtr renderer)
{ {
@ -63,14 +63,8 @@ namespace OpenDiablo2.SDL2_
this.renderer = renderer; this.renderer = renderer;
this.TotalFrames = source.Frames.Count(); TotalFrames = source.Frames.Count();
this.FrameSize = new Size(Pow2((int)source.Frames.Max(x => x.Width)), Pow2((int)source.Frames.Max(x => x.Height))); FrameSize = new Size(Pow2((int)source.Frames.Max(x => x.Width)), Pow2((int)source.Frames.Max(x => x.Height)));
this.textures = new IntPtr[TotalFrames];
for(var i = 0; i < this.textures.Count(); i++)
{
this.textures[i] = IntPtr.Zero;
}
} }
internal Point GetRenderPoint() internal Point GetRenderPoint()
@ -84,8 +78,16 @@ namespace OpenDiablo2.SDL2_
// TODO: This is slow. Make fix. // TODO: This is slow. Make fix.
private void UpdateTextureData() private void UpdateTextureData()
{ {
for (var i = 0; i < source.Frames.Count(); i++) if (texture == IntPtr.Zero)
LoadFrame(i, renderer); {
texture = SDL.SDL_CreateTexture(renderer, SDL.SDL_PIXELFORMAT_ARGB8888, (int)SDL.SDL_TextureAccess.SDL_TEXTUREACCESS_STREAMING, Pow2(FrameSize.Width), Pow2(FrameSize.Height));
if (texture == IntPtr.Zero)
throw new ApplicationException("Unaple to initialize texture.");
Frame = 0;
}
} }
// TODO: Less dumb color correction // TODO: Less dumb color correction
@ -97,39 +99,41 @@ namespace OpenDiablo2.SDL2_
(byte)Math.Min((float)source.B * 1.2, 255) (byte)Math.Min((float)source.B * 1.2, 255)
); );
object bob = new object(); private unsafe void LoadFrame(int index)
private void LoadFrame(int index, IntPtr renderer)
{ {
var frame = source.Frames[index]; var frame = source.Frames[index];
if (textures[index] == IntPtr.Zero) IntPtr pixels;
textures[index] = SDL.SDL_CreateTexture(renderer, SDL.SDL_PIXELFORMAT_ARGB8888, (int)SDL.SDL_TextureAccess.SDL_TEXTUREACCESS_TARGET, Pow2(FrameSize.Width), Pow2(FrameSize.Height)); int pitch;
var fullRect = new SDL.SDL_Rect { x = 0, y = 0, w = FrameSize.Width, h = FrameSize.Height };
SDL.SDL_SetTextureBlendMode(texture, blend ? SDL.SDL_BlendMode.SDL_BLENDMODE_ADD : SDL.SDL_BlendMode.SDL_BLENDMODE_BLEND);
if (textures[index] == IntPtr.Zero) SDL.SDL_LockTexture(texture, IntPtr.Zero, out pixels, out pitch);
throw new ApplicationException("Unaple to initialize texture."); try
SDL.SDL_SetTextureBlendMode(textures[index], SDL.SDL_BlendMode.SDL_BLENDMODE_BLEND);
SDL.SDL_SetRenderTarget(renderer, textures[index]);
SDL.SDL_SetRenderDrawColor(renderer, 0, 0, 0, 0);
SDL.SDL_RenderFillRect(renderer, IntPtr.Zero);
SDL.SDL_SetRenderTarget(renderer, IntPtr.Zero);
var binaryData = new UInt32[frame.Width * frame.Height];
for (var y = 0; y < frame.Height; y++)
{ {
for (int x = 0; x < frame.Width; x++) UInt32* data = (UInt32*)pixels;
var frameOffset = FrameSize.Height - frame.Height;
for (var y = 0; y < FrameSize.Height; y++)
{ {
var palColor = frame.GetColor(x, (int)y, CurrentPalette); for (int x = 0; x < FrameSize.Width; x++)
//var col = AdjustColor(palColor); {
binaryData[x + y * frame.Width] = (uint)palColor.ToArgb(); if ((x >= frame.Width) || (y < frameOffset))
{
data[x + (y * (pitch / 4))] = 0;
continue;
}
var palColor = frame.GetColor(x, (int)(y - frameOffset), CurrentPalette);
//var col = AdjustColor(palColor);
data[x + (y * (pitch / 4))] = palColor;
}
} }
} }
finally
{
var rect = new SDL.SDL_Rect { x = 0, y = FrameSize.Height - (int)frame.Height, w = (int)frame.Width, h = (int)frame.Height }; SDL.SDL_UnlockTexture(texture);
GCHandle pinnedArray = GCHandle.Alloc(binaryData, GCHandleType.Pinned); }
SDL.SDL_UpdateTexture(textures[index], ref rect, pinnedArray.AddrOfPinnedObject(), (int)frame.Width * 4);
pinnedArray.Free();
} }
@ -144,10 +148,7 @@ namespace OpenDiablo2.SDL2_
public void Dispose() public void Dispose()
{ {
foreach (var texture in textures) SDL.SDL_DestroyTexture(texture);
{
SDL.SDL_DestroyTexture(texture);
}
} }
} }
} }