1 /* 2 ******************************************************************************************* 3 * Dgame (a D game framework) - Copyright (c) Randy Schütt 4 * 5 * This software is provided 'as-is', without any express or implied warranty. 6 * In no event will the authors be held liable for any damages arising from 7 * the use of this software. 8 * 9 * Permission is granted to anyone to use this software for any purpose, 10 * including commercial applications, and to alter it and redistribute it 11 * freely, subject to the following restrictions: 12 * 13 * 1. The origin of this software must not be misrepresented; you must not claim 14 * that you wrote the original software. If you use this software in a product, 15 * an acknowledgment in the product documentation would be appreciated but is 16 * not required. 17 * 18 * 2. Altered source versions must be plainly marked as such, and must not be 19 * misrepresented as being the original software. 20 * 21 * 3. This notice may not be removed or altered from any source distribution. 22 ******************************************************************************************* 23 */ 24 module Dgame.Graphics.RendererTexture; 25 26 private { 27 debug import std.stdio : writeln; 28 29 import derelict.sdl2.sdl; 30 31 import Dgame.Graphics.Surface; 32 import Dgame.Graphics.Color; 33 import Dgame.Graphics.Renderer; 34 import Dgame.Math.Rect; 35 import Dgame.Internal.Shared; 36 } 37 38 ///version = Develop; 39 40 /** 41 * This is a wrapper for the hardware acceleration of SDL_Surfaces, called SDL_Textures. 42 * That means it is the same as if you use the HW_ACCEL Flag in SDL 1.2. 43 * 44 * Author: rschuett 45 */ 46 struct RendererTexture { 47 private: 48 shared_ptr!(SDL_Texture) _target; 49 50 public: 51 /** 52 * Supported Access modes 53 */ 54 enum Access { 55 Static = SDL_TEXTUREACCESS_STATIC, /** changes rarely, not lockable */ 56 Stream = SDL_TEXTUREACCESS_STREAMING /** changes frequently, lockable */ 57 } 58 59 const Access access; 60 61 /** 62 * CTor 63 */ 64 this(SDL_Texture* tex, Access access) { 65 this._target = make_shared(tex, (SDL_Texture* tex) => SDL_DestroyTexture(tex)); 66 67 this.access = access; 68 } 69 70 version (Develop) 71 ~this() { 72 debug writeln("DTor RendererTexture"); 73 } 74 75 /** 76 * Destroy the RendererTexture <b>and all</b> which are linked to this. 77 */ 78 void free() { 79 this._target.release(); 80 } 81 82 /** 83 * Returns a two dimensional array filled with the width and the height 84 */ 85 int[2] getSize() { 86 int w, h; 87 int access; 88 uint format; 89 90 SDL_QueryTexture(this._target, &format, &access, &w, &h); 91 92 return [w, h]; 93 } 94 95 /** 96 * Returns the width 97 */ 98 @property 99 ushort width() { 100 int[2] size = this.getSize(); 101 102 return cast(ushort) size[0]; 103 } 104 105 /** 106 * Returns the width 107 */ 108 @property 109 ushort height() { 110 int[2] size = this.getSize(); 111 112 return cast(ushort) size[1]; 113 } 114 115 /** 116 * Checks whether this Surface is lockable and therefore accessable. 117 */ 118 bool isLockable() const pure nothrow { 119 return !(this.access & Access.Static); 120 } 121 122 /** 123 * Use this function to lock a portion of the texture for write-only pixel access. 124 * Returns the pixel data of given area. 125 * If area is null, the whole pixel data returns. 126 */ 127 void* lock(out int pitch, const ShortRect* area = null) { 128 if (this.access & Access.Static) 129 return null; 130 131 SDL_Rect a = void; 132 const SDL_Rect* rect_ptr = transfer(area, &a); 133 134 void* pixels; 135 SDL_LockTexture(this._target, rect_ptr, &pixels, &pitch); 136 137 return pixels; 138 } 139 140 /** 141 * Use this function to unlock a texture, uploading the changes to video memory, if needed. 142 */ 143 void unlock() { 144 SDL_UnlockTexture(this._target); 145 } 146 147 /** 148 * Returns a pointer of the SDL_Texture* struct. 149 */ 150 @property 151 inout(SDL_Texture)* ptr() inout { 152 return this._target.ptr; 153 } 154 155 /** 156 * Checks whether the RendererTexture is valid. 157 */ 158 bool isValid() const pure nothrow { 159 return this._target.isValid(); 160 } 161 162 /** 163 * Use this function to update the given texture rectangle with new pixel data. 164 */ 165 void update(const void* pixels, const ShortRect* rect = null, int pitch = -1) { 166 SDL_Rect a = void; 167 const SDL_Rect* dst_ptr = transfer(rect, &a); 168 169 SDL_UpdateTexture(this._target, dst_ptr, pixels, !pitch ? this.width * 4 : pitch); 170 } 171 172 /** 173 * Copy hw onto this RendererTexture. rect is the position and size. 174 */ 175 void copy(ref RendererTexture hw, const ShortRect* rect) in { 176 assert(hw.isValid(), "Invalid Surface."); 177 } body { 178 int pitch; 179 void* pixels = hw.lock(pitch); 180 scope(exit) hw.unlock(); 181 182 this.update(pixels, rect, pitch); 183 } 184 185 /** 186 * Copy srfc onto this RendererTexture. rect is the position and size. 187 */ 188 void copy(ref Surface srfc, ShortRect* rect) in { 189 assert(srfc.isValid(), "Invalid Surface."); 190 } body { 191 ShortRect clipRect = srfc.getClipRect(); 192 if (rect is null) 193 rect = &clipRect; 194 195 this.update(srfc.pixels, rect, srfc.ptr.pitch); 196 } 197 198 /** 199 * Use this function to set the blend mode for a texture, used by 'copy'. 200 */ 201 void setBlendMode(Renderer.BlendMode bmode) { 202 SDL_SetTextureBlendMode(this._target, bmode); 203 } 204 205 /** 206 * Use this function to get the blend mode used for texture copy operations. 207 */ 208 Renderer.BlendMode getBlendMode() { 209 SDL_BlendMode blendMode; 210 SDL_GetTextureBlendMode(this._target, &blendMode); 211 212 return cast(Renderer.BlendMode) blendMode; 213 } 214 215 /** 216 * Use this function to set an additional alpha value multiplied into render copy operations. 217 */ 218 void setAlphaMod(ubyte alpha) { 219 SDL_SetTextureAlphaMod(this._target, alpha); 220 } 221 222 /** 223 * Use this function to get the additional alpha value multiplied into render copy operations. 224 */ 225 ubyte getAlphaMod() { 226 ubyte alpha; 227 SDL_GetTextureAlphaMod(this._target, &alpha); 228 229 return alpha; 230 } 231 232 /** 233 * Use this function to set an additional color value multiplied into render copy operations. 234 */ 235 void setColorMod(ref const Color col) { 236 this.setColorMod(col.red, col.green, col.blue); 237 } 238 239 /** 240 * Rvalue version 241 */ 242 void setColorMod(const Color col) { 243 this.setColorMod(col); 244 } 245 246 /** 247 * Use this function to set an additional color value multiplied into render copy operations. 248 */ 249 void setColorMod(ubyte r, ubyte g, ubyte b) { 250 SDL_SetTextureColorMod(this._target, r, g, b); 251 } 252 253 /** 254 * Use this function to get the additional color value multiplied into render copy operations 255 */ 256 Color getColorMod() { 257 ubyte r, g, b; 258 SDL_GetTextureColorMod(this._target, &r, &g, &b); 259 260 return Color(r, g, b); 261 } 262 }