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 * Can be overloaded for user defined layers. 42 */ 43 abstract class Layer { 44 protected RenderFunc mainRenderingFunction; ///Used to implement changeable renderers for each layers 45 /+protected @nogc pure nothrow void function(ushort* src, uint* dest, uint* palette, size_t length) 46 mainColorLookupFunction;+/ 47 //protected @nogc void function(uint* src, int length) mainHorizontalMirroringFunction; 48 /+protected @nogc pure nothrow void function(ubyte* src, uint* dest, uint* palette, size_t length) 49 main8BitColorLookupFunction;+/ 50 /+protected @nogc pure nothrow void function(ubyte* src, uint* dest, uint* palette, size_t length, int offset) 51 main4BitColorLookupFunction;+/ 52 alias mainColorLookupFunction = colorLookup!(ushort,uint); 53 alias main8BitColorLookupFunction = colorLookup!(ubyte,uint); 54 alias main4BitColorLookupFunction = colorLookup4Bit!uint; 55 protected RenderingMode renderMode; 56 57 // scrolling position 58 //protected int sX, sY, rasterX, rasterY; 59 protected int sX; ///Horizontal scroll position 60 protected int sY; ///Vertical scroll position 61 protected int rasterX;///Raster width (visible) 62 protected int rasterY;///Haster height 63 64 /** 65 * Sets up the layer for the current rasterizer. 66 * Params: 67 * rX = Width of the raster. 68 * rY = Height of the raster. 69 * Note: These values define the visible area that need to be worked with. Some overscan can be defined, 70 * and `updateRaster`'s `pitch` parameter defines the per-line stepping. Note that too much overscan can 71 * negatively impact performance. 72 */ 73 public void setRasterizer(int rX, int rY) @safe pure nothrow { 74 rasterX=rX; 75 rasterY=rY; 76 } 77 /** 78 * Sets the global rendering mode for this layer. 79 * Params: 80 * mode = The enumerator that describes built-in rendering functions. 81 */ 82 public void setRenderingMode(RenderingMode mode) @nogc @safe pure nothrow { 83 renderMode = mode; 84 mainRenderingFunction = getRenderingFunc(mode); 85 //mainColorLookupFunction = &colorLookup!(ushort,uint); 86 //mainHorizontalMirroringFunction = &flipHorizontal; 87 //main8BitColorLookupFunction = &colorLookup!(ubyte,uint); 88 //main4BitColorLookupFunction = &colorLookup4Bit!uint; 89 } 90 /** 91 * Scrolls the layer to the given position. 92 * Params: 93 * x = Horizontal coordinate. 94 * y = Vertical coordinate. 95 */ 96 public void scroll(int x, int y) @safe nothrow { 97 sX = x; 98 sY = y; 99 } 100 /** 101 * Relatively scrolls the layer by the given amount. 102 * Formula is: 103 * `[sX,sY] = [sX,sY] + [x,y]` 104 * Params: 105 * x = Horizontal amount. 106 * y = Vertical amount. 107 */ 108 public void relScroll(int x, int y) @safe nothrow { 109 sX += x; 110 sY += y; 111 } 112 ///Getter for the X scroll position. 113 public int getSX() @nogc @safe pure nothrow const { 114 return sX; 115 } 116 ///Getter for the Y scroll position. 117 public int getSY() @nogc @safe pure nothrow const { 118 return sY; 119 } 120 /** 121 * Renders the layer's output to the raster. Function is called sequentially for all layers. Layers with higher 122 * priority number will render to the raster in a later time. Function is marked as @nogc, as render-time 123 * allocation has negative impact on performance. For errors, either use asserts for unrecoverable errors, or 124 * errorcodes for less severe cases. 125 * Params: 126 * workpad = The pointer to the workpad's first pixel to be shown. Does not have to be equal with the actual 127 * first pixel of the workpad. 128 * pitch = The difference between lines in the amount of bytes. Must also contain any padding bytes, e.g. 129 * pixels, etc. 130 * palette = Pointer to the first element on the palette. 131 * Note: Due to the nature of how rendering functions work on vector extensions, arrays are not as feasible as 132 * in other places, so that's why pointers are used instead. 133 */ 134 public abstract void updateRaster(void* workpad, int pitch, Color* palette) @nogc ; 135 ///Returns the type of the layer. 136 ///Useful with certain scripting languages. 137 public abstract LayerType getLayerType() @nogc @safe pure nothrow const; 138 ///Standard algorithm for horizontal mirroring, used for tile mirroring 139 protected void flipHorizontal(T)(T[] target) @nogc pure nothrow { 140 //sizediff_t j = target.length - 1; 141 for (sizediff_t i, j = target.length - 1 ; i < j ; i++, j--) { 142 const T s = target[i]; 143 target[i] = target[j]; 144 target[j] = s; 145 //j--; 146 } 147 } 148 } 149 /** 150 * Mostly used for internal communication and scripting. 151 */ 152 public enum LayerType { 153 init, 154 Tile, 155 TransformableTile, 156 Sprite, 157 Effects, 158 } 159 /** 160 * Defines how the layer or sprite will be rendered. 161 * See each value's documentation individually for more information on each mode. 162 */ 163 public enum RenderingMode : ubyte { 164 init, ///Rendering mode is not set 165 Copy, ///Copies the pixels without any transparencies. The fastest as it only reads once. Best use is either GUI or lowest-layer. 166 Blitter, ///Copies the pixels to the target using simple transparency. No effect from master-alpha values. Can be faster on less memory-bound machines. 167 AlphaBlend, ///Blends the source onto the target, using both per-pixel alpha and master alpha. 168 Multiply, ///Multiplies pixel channel values, then stores it in the destination. 169 MultiplyBl, ///Multiply with alpha used as a blend between the original and target value. 170 Screen, ///Composes the source to the destination using the following formula: 1 - (1 - dest) * (1 - src) 171 ScreenBl, ///Screen with alpha used as a blend between the original and target value. 172 Add, ///Adds with saturation the source to the destination. 173 AddBl, ///Add with alpha used as a blend between the original and target value. 174 Subtract, ///Subtracts with saturation the source from the destination. 175 SubtractBl, ///Subtracts with saturation the source from the destination. Alpha determines how much of the source's other channels is used. 176 Diff, ///Calculates the difference between the source and destination. 177 DiffBl, ///Calculates the difference between the source and destination. Alpha determines how much of the source's other channels is used. 178 AND, ///Logically ANDs the source to the destination. Alpha value is ignored. 179 OR, ///Logically ORs the source to the destination. Alpha value is ignored. 180 XOR, ///Logically XORs the source to the destination. Alpha value is ignored. 181 } 182 /** 183 * Returns the rendering function that belongs to the enumeration value. 184 */ 185 public RenderFunc getRenderingFunc (RenderingMode mode) @nogc @safe pure nothrow { 186 final switch (mode) with (RenderingMode) { 187 case init: 188 return null; 189 case Copy: 190 return &localCpy; 191 case Blitter: 192 return &localBlt; 193 case AlphaBlend: 194 return (uint* src, uint* dest, size_t length, ubyte value) {alphaBlendMV(src, dest, length, value);}; 195 case Multiply: 196 return (uint* src, uint* dest, size_t length, ubyte value) {multMV(src, dest, length, value);}; 197 case MultiplyBl: 198 return (uint* src, uint* dest, size_t length, ubyte value) {multMVBl(src, dest, length, value);}; 199 case Screen: 200 return (uint* src, uint* dest, size_t length, ubyte value) {screenMV(src, dest, length, value);}; 201 case ScreenBl: 202 return (uint* src, uint* dest, size_t length, ubyte value) {screenMVBl(src, dest, length, value);}; 203 case Add: 204 return (uint* src, uint* dest, size_t length, ubyte value) {addMV!(false)(src, dest, length, value);}; 205 case AddBl: 206 return (uint* src, uint* dest, size_t length, ubyte value) {addMV!(true)(src, dest, length, value);}; 207 case Subtract: 208 return (uint* src, uint* dest, size_t length, ubyte value) {subMV!(false)(src, dest, length, value);}; 209 case SubtractBl: 210 return (uint* src, uint* dest, size_t length, ubyte value) {subMV!(true)(src, dest, length, value);}; 211 case Diff: 212 return (uint* src, uint* dest, size_t length, ubyte value) {diffMV(src, dest, length, value);}; 213 case DiffBl: 214 return (uint* src, uint* dest, size_t length, ubyte value) {diffMVBl(src, dest, length, value);}; 215 case AND: 216 return null; 217 case OR: 218 return null; 219 case XOR: 220 return &localXOR; 221 } 222 } 223 /** 224 * Sets the WarpMode for any tile layer. 225 */ 226 public enum WarpMode : ubyte { 227 Off, /// Content shown only once. 228 MapRepeat, /// Tilemap is repeated on the layer. 229 TileRepeat /// Out of bounds areas repeat tile 0x0000. Tile 0xFFFF is still reserved as transparency. 230 } 231 /** 232 * Mapping element, that is used on most if not all layers in this engine. 233 * It reserves: 234 * * 16 bits for tile selection. 235 * * 6 bits for extra purposes (can be user defined if the layer doesn't use it for anything else). 236 * * 1 bit for vertical mirroring. 237 * * 1 bit for horizontal mirroring. 238 * * 8 bits for palette selection (can be used for user-defined purposes if tiles are either 16 or 32 bit). 239 * User defined purposes may include marking tiles with special purpose for the game logic. 240 */ 241 public struct MappingElement { 242 wchar tileID; ///Determines which tile is being used for the given instance. 0xFFFF is reserved for transparency. 243 BitmapAttrib attributes; ///General attributes, such as vertical and horizontal mirroring. The extra 6 bits can be used for various purposes 244 ubyte paletteSel; ///Selects the palette for the bitmap if supported 245 ///Default constructor 246 this(wchar tileID, BitmapAttrib attributes = BitmapAttrib(false, false), ubyte paletteSel = 0) @nogc @safe pure nothrow { 247 this.tileID = tileID; 248 this.attributes = attributes; 249 this.paletteSel = paletteSel; 250 } 251 public string toString() const { 252 import std.conv : to; 253 return "[tileID:" ~ to!string(cast(int)tileID) ~ "; attributes:" ~ attributes.toString ~ "; paletteSel:" ~ 254 to!string(paletteSel) ~ "]"; 255 } 256 }