1 /*
2  * Copyright (C) 2015-2020, by Laszlo Szeremi under the Boost license.
3  *
4  * Pixel Perfect Engine, graphics.layers.base module
5  */
6 
7 module PixelPerfectEngine.graphics.layers.base;
8 
9 public import PixelPerfectEngine.graphics.bitmap;
10 public import PixelPerfectEngine.graphics.common;
11 public import PixelPerfectEngine.graphics.layers.interfaces;
12 package import PixelPerfectEngine.graphics.transformFunctions;
13 package import PixelPerfectEngine.system.etc;
14 //package import PixelPerfectEngine.system.platform;
15 
16 package import std.bitmanip : bitfields;
17 public import PixelPerfectEngine.system.exc;
18 package import bindbc.sdl;
19 package import core.stdc.stdlib;
20 package import CPUblit.composing;
21 package import CPUblit.composing.specblt : xorBlitter;
22 package import CPUblit.colorlookup;
23 package import CPUblit.transform;
24 
25 import inteli.emmintrin;
26 alias RenderFunc = @nogc pure nothrow void function(uint* src, uint* dest, size_t length, ubyte value);
27 /// For generating a blitter function with value modifier
28 @nogc pure nothrow void localBlt(uint* src, uint* dest, size_t length, ubyte value) {
29 	blitter!uint(src, dest, length);
30 }
31 /// For generating a copy function with value modifier
32 @nogc pure nothrow void localCpy(uint* src, uint* dest, size_t length, ubyte value) {
33 	copy!uint(src, dest, length);
34 }
35 /// For generating a XOR blitter function with value modifier
36 @nogc pure nothrow void localXOR(uint* src, uint* dest, size_t length, ubyte value) {
37 	xorBlitter!uint(src, dest, length);
38 }
39 /**
40  * The basis of all layer classes, containing function pointers for rendering.
41  */
42 abstract class Layer {
43 	protected RenderFunc mainRenderingFunction;		///Used to implement changeable renderers for each layers
44 	/+protected @nogc pure nothrow void function(ushort* src, uint* dest, uint* palette, size_t length) 
45 			mainColorLookupFunction;+/
46 	//protected @nogc void function(uint* src, int length) mainHorizontalMirroringFunction;
47 	/+protected @nogc pure nothrow void function(ubyte* src, uint* dest, uint* palette, size_t length) 
48 			main8BitColorLookupFunction;+/
49 	/+protected @nogc pure nothrow void function(ubyte* src, uint* dest, uint* palette, size_t length, int offset) 
50 			main4BitColorLookupFunction;+/
51 	alias mainColorLookupFunction = colorLookup!(ushort,uint);
52 	alias main8BitColorLookupFunction = colorLookup!(ubyte,uint);
53 	alias main4BitColorLookupFunction = colorLookup4Bit!uint;
54 	protected RenderingMode renderMode;
55 
56 	// scrolling position
57 	//protected int sX, sY, rasterX, rasterY;
58 	protected int		sX;		///Horizontal scroll position
59 	protected int       sY;		///Vertical scroll position
60 	protected int		rasterX;///Raster width (visible)
61 	protected int		rasterY;///Haster height
62 
63 	/// Sets the main rasterizer
64 	public void setRasterizer(int rX, int rY) @safe pure nothrow {
65 		rasterX=rX;
66 		rasterY=rY;
67 	}
68 	///Sets the rendering mode
69 	public void setRenderingMode(RenderingMode mode) @nogc @safe pure nothrow {
70 		renderMode = mode;
71 		mainRenderingFunction = getRenderingFunc(mode);
72 		//mainColorLookupFunction = &colorLookup!(ushort,uint);
73 		//mainHorizontalMirroringFunction = &flipHorizontal;
74 		//main8BitColorLookupFunction = &colorLookup!(ubyte,uint);
75 		//main4BitColorLookupFunction = &colorLookup4Bit!uint;
76 	}
77 	///Absolute scrolling.
78 	public void scroll(int x, int y) @safe pure nothrow {
79 		sX = x;
80 		sY = y;
81 	}
82 	///Relative scrolling. Positive values scrolls the layer left and up, negative values scrolls the layer down and right.
83 	public void relScroll(int x, int y) @safe pure nothrow {
84 		sX += x;
85 		sY += y;
86 	}
87 	///Getter for the X scroll position.
88 	public int getSX() @nogc @safe pure nothrow const {
89 		return sX;
90 	}
91 	///Getter for the Y scroll position.
92 	public int getSY() @nogc @safe pure nothrow const {
93 		return sY;
94 	}
95 	/// Override this to enable output to the raster
96 	public abstract void updateRaster(void* workpad, int pitch, Color* palette) @nogc ;
97 	///Standard algorithm for horizontal mirroring, used for tile mirroring
98 	protected void flipHorizontal(T)(T[] target) @nogc pure nothrow {
99 		//sizediff_t j = target.length - 1;
100 		for (sizediff_t i, j = target.length - 1 ; i < j ; i++, j--) {
101 			const T s = target[i];
102 			target[i] = target[j];
103 			target[j] = s;
104 			//j--;
105 		}
106 	}
107 }
108 /**
109  * Mostly used for internal communication.
110  */
111 public enum LayerType {
112 	init,
113 	Tile,
114 	TransformableTile,
115 	Sprite,
116 	Effects,
117 }
118 /**
119  * Defines how the layer or sprite will be rendered.
120  * See each value's documentation individually for more information on each mode.
121  */
122 public enum RenderingMode : ubyte {
123 	init,			///Rendering mode is not set
124 	Copy,			///Copies the pixels without any transparencies. The fastest as it only reads once. Best use is either GUI or lowest-layer.
125 	Blitter,		///Copies the pixels to the target using simple transparency. No effect from master-alpha values. Can be faster on less memory-bound machines.
126 	AlphaBlend,		///Blends the source onto the target, using both per-pixel alpha and master alpha. 
127 	Multiply,		///Multiplies pixel channel values, then stores it in the destination.
128 	MultiplyBl,		///Multiply with alpha used as a blend between the original and target value.
129 	Screen,			///Composes the source to the destination using the following formula: 1 - (1 - dest) * (1 - src)
130 	ScreenBl,		///Screen with alpha used as a blend between the original and target value.
131 	Add,			///Adds with saturation the source to the destination.
132 	AddBl,			///Add with alpha used as a blend between the original and target value.
133 	Subtract,		///Subtracts with saturation the source from the destination.
134 	SubtractBl,		///Subtracts with saturation the source from the destination. Alpha determines how much of the source's other channels is used.
135 	Diff,			///Calculates the difference between the source and destination.
136 	DiffBl,			///Calculates the difference between the source and destination. Alpha determines how much of the source's other channels is used.
137 	AND,			///Logically ANDs the source to the destination. Alpha value is ignored.
138 	OR,				///Logically ORs the source to the destination. Alpha value is ignored.
139 	XOR,			///Logically XORs the source to the destination. Alpha value is ignored.
140 }
141 /**
142  * Returns the rendering function that belongs to the enumeration value.
143  */
144 public RenderFunc getRenderingFunc (RenderingMode mode) @nogc @safe pure nothrow {
145 	final switch (mode) with (RenderingMode) {
146 		case init:
147 			return null;
148 		case Copy:
149 			return &localCpy;
150 		case Blitter:
151 			return &localBlt;
152 		case AlphaBlend:
153 			return (uint* src, uint* dest, size_t length, ubyte value) {alphaBlendMV(src, dest, length, value);};
154 		case Multiply:
155 			return (uint* src, uint* dest, size_t length, ubyte value) {multMV(src, dest, length, value);};
156 		case MultiplyBl:
157 			return (uint* src, uint* dest, size_t length, ubyte value) {multMVBl(src, dest, length, value);};
158 		case Screen:
159 			return (uint* src, uint* dest, size_t length, ubyte value) {screenMV(src, dest, length, value);};
160 		case ScreenBl:
161 			return (uint* src, uint* dest, size_t length, ubyte value) {screenMVBl(src, dest, length, value);};
162 		case Add:
163 			return (uint* src, uint* dest, size_t length, ubyte value) {addMV!(false)(src, dest, length, value);};
164 		case AddBl:
165 			return (uint* src, uint* dest, size_t length, ubyte value) {addMV!(true)(src, dest, length, value);};
166 		case Subtract:
167 			return (uint* src, uint* dest, size_t length, ubyte value) {subMV!(false)(src, dest, length, value);};
168 		case SubtractBl:
169 			return (uint* src, uint* dest, size_t length, ubyte value) {subMV!(true)(src, dest, length, value);};
170 		case Diff:
171 			return (uint* src, uint* dest, size_t length, ubyte value) {diffMV(src, dest, length, value);};
172 		case DiffBl:
173 			return (uint* src, uint* dest, size_t length, ubyte value) {diffMVBl(src, dest, length, value);};
174 		case AND:
175 			return null;
176 		case OR:
177 			return null;
178 		case XOR:
179 			return &localXOR;
180 	}
181 }
182 /**
183  * Sets the WarpMode for any tile layer.
184  */
185 public enum WarpMode : ubyte {
186 	Off,				/// Content shown only once.
187 	MapRepeat,			/// Tilemap is repeated on the layer.
188 	TileRepeat			/// Out of bounds areas repeat tile 0x0000. Tile 0xFFFF is still reserved as transparency.
189 }
190 /**
191  * Universal Mapping element, that is stored on 32 bit.
192  */
193 public struct MappingElement {
194 	wchar tileID;				///Determines which tile is being used for the given instance
195 	BitmapAttrib attributes;	///General attributes, such as vertical and horizontal mirroring. The extra 6 bits can be used for various purposes
196 	ubyte paletteSel;			///Selects the palette for the bitmap if supported
197 	///Default constructor
198 	this(wchar tileID, BitmapAttrib attributes = BitmapAttrib(false, false), ubyte paletteSel = 0) @nogc @safe pure nothrow {
199 		this.tileID = tileID;
200 		this.attributes = attributes;
201 		this.paletteSel = paletteSel;
202 	}
203 	public string toString() const {
204 		import std.conv : to;
205 		return "[tileID:" ~ to!string(cast(int)tileID) ~ "; attributes:" ~ attributes.toString ~ "; paletteSel:" ~
206 				to!string(paletteSel) ~ "]";
207 	}
208 }