1 module gfm.sdl2.renderer; 2 3 import std.string; 4 5 import derelict.sdl2.sdl; 6 7 import std.logger; 8 9 import gfm.core.text, 10 gfm.math.vector, 11 gfm.math.box, 12 gfm.sdl2.sdl, 13 gfm.sdl2.window, 14 gfm.sdl2.texture, 15 gfm.sdl2.surface; 16 17 /// SDL Renderer wrapper. 18 final class SDL2Renderer 19 { 20 public 21 { 22 /// Creates a SDL renderer which targets a window. 23 /// See_also: $(LINK http://wiki.libsdl.org/SDL_CreateRenderer) 24 /// Throws: $(D SDL2Exception) on error. 25 this(SDL2Window window, int flags) 26 { 27 _sdl2 = window._sdl2; 28 _renderer = SDL_CreateRenderer(window._window, -1, flags); 29 if (_renderer is null) 30 _sdl2.throwSDL2Exception("SDL_CreateRenderer"); 31 } 32 33 /// Create a software renderer which targets a surface. 34 /// See_also: $(LINK http://wiki.libsdl.org/SDL_CreateSoftwareRenderer) 35 /// Throws: $(D SDL2Exception) on error. 36 this(SDL2Surface surface) 37 { 38 _sdl2 = surface._sdl2; 39 _renderer = SDL_CreateSoftwareRenderer(surface._surface); 40 if (_renderer is null) 41 _sdl2.throwSDL2Exception("SDL_CreateSoftwareRenderer"); 42 } 43 44 /// Releases the SDL ressource. 45 /// See_also: $(LINK http://wiki.libsdl.org/SDL_DestroyRenderer) 46 void close() 47 { 48 if (_renderer !is null) 49 { 50 SDL_DestroyRenderer(_renderer); 51 _renderer = null; 52 } 53 } 54 55 ~this() 56 { 57 close(); 58 } 59 60 /// Clear the current rendering target with the drawing color. 61 /// See_also: $(LINK http://wiki.libsdl.org/SDL_RenderClear) 62 /// Throws: $(D SDL2Exception) on error. 63 void clear() 64 { 65 if (0 != SDL_RenderClear(_renderer)) 66 _sdl2.throwSDL2Exception("SDL_RenderClear"); 67 } 68 69 /// Update the screen with rendering performed. 70 /// See_also: $(LINK http://wiki.libsdl.org/SDL_RenderPresent) 71 void present() 72 { 73 SDL_RenderPresent(_renderer); 74 } 75 76 /// Sets the color used for drawing operations. 77 /// See_also: $(LINK http://wiki.libsdl.org/SDL_SetRenderDrawColor) 78 /// Throws: $(D SDL2Exception) on error. 79 void setColor(ubyte r, ubyte g, ubyte b, ubyte a) 80 { 81 if (0 != SDL_SetRenderDrawColor(_renderer, r, g, b, a)) 82 _sdl2.throwSDL2Exception("SDL_SetRenderDrawColor"); 83 } 84 85 /// Sets the window drawing area. 86 /// See_also: $(LINK http://wiki.libsdl.org/SDL_RenderSetViewport) 87 /// Throws: $(D SDL2Exception) on error. 88 void setViewport(box2i b) 89 { 90 SDL_Rect r = box2i_to_SDL_Rect(b); 91 if (0 != SDL_RenderSetViewport(_renderer, &r)) 92 _sdl2.throwSDL2Exception("SDL_RenderSetViewport"); 93 } 94 95 /// Sets the whole window as drawing area. 96 /// See_also: $(LINK http://wiki.libsdl.org/SDL_RenderSetViewport) 97 /// Throws: $(D SDL2Exception) on error. 98 void setViewportFull() 99 { 100 if (0 != SDL_RenderSetViewport(_renderer, null)) 101 _sdl2.throwSDL2Exception("SDL_RenderSetViewport"); 102 } 103 104 /// Sets SDL blend mode. 105 /// See_also: $(LINK http://wiki.libsdl.org/SDL_SetRenderDrawBlendMode) 106 /// Throws: $(D SDL2Exception) on error. 107 void setBlend(int blendMode) 108 { 109 if (0 != SDL_SetRenderDrawBlendMode(_renderer, blendMode)) 110 _sdl2.throwSDL2Exception("SDL_SetRenderDrawBlendMode"); 111 } 112 113 /// Draw a line. 114 /// See_also: $(LINK http://wiki.libsdl.org/SDL_RenderDrawLine) 115 /// Throws: $(D SDL2Exception) on error. 116 void drawLine(vec2i a, vec2i b) 117 { 118 if (0 != SDL_RenderDrawLine(_renderer, a.x, a.y, b.x, b.y)) 119 _sdl2.throwSDL2Exception("SDL_RenderDrawLine"); 120 121 } 122 123 /// Draw several lines at once. 124 /// See_also: $(LINK http://wiki.libsdl.org/SDL_RenderDrawLines) 125 /// Throws: $(D SDL2Exception) on error. 126 void drawLines(vec2i[] points) 127 { 128 if (0 != SDL_RenderDrawLines(_renderer, cast(SDL_Point*)(points.ptr), cast(int)(points.length))) 129 _sdl2.throwSDL2Exception("SDL_RenderDrawLines"); 130 } 131 132 /// Draw a point. 133 /// See_also: $(LINK http://wiki.libsdl.org/SDL_RenderDrawPoint) 134 /// Throws: $(D SDL2Exception) on error. 135 void drawPoint(vec2i point) 136 { 137 if (0 != SDL_RenderDrawPoint(_renderer, point.x, point.y)) 138 _sdl2.throwSDL2Exception("SDL_RenderDrawPoint"); 139 } 140 141 /// Draw several point at once. 142 /// See_also: $(LINK http://wiki.libsdl.org/SDL_RenderDrawPoints) 143 /// Throws: $(D SDL2Exception) on error. 144 void drawPoints(vec2i[] points) 145 { 146 if (0 != SDL_RenderDrawPoints(_renderer, cast(SDL_Point*)(points.ptr), cast(int)(points.length))) 147 _sdl2.throwSDL2Exception("SDL_RenderDrawPoints"); 148 } 149 150 /// Draw a rectangle outline. 151 /// See_also: $(LINK http://wiki.libsdl.org/SDL_RenderDrawRect) 152 /// Throws: $(D SDL2Exception) on error. 153 void drawRect(box2i rect) 154 { 155 SDL_Rect r = box2i_to_SDL_Rect(rect); 156 if (0 != SDL_RenderDrawRect(_renderer, &r)) 157 _sdl2.throwSDL2Exception("SDL_RenderDrawRect"); 158 } 159 160 /// Draw a filled rectangle. 161 /// See_also: $(LINK http://wiki.libsdl.org/SDL_RenderFillRect) 162 /// Throws: $(D SDL2Exception) on error. 163 void fillRect(box2i rect) 164 { 165 SDL_Rect r = box2i_to_SDL_Rect(rect); 166 if (0 != SDL_RenderFillRect(_renderer, &r)) 167 _sdl2.throwSDL2Exception("SDL_RenderFillRect"); 168 } 169 170 /// Blit a rectangle from a texture. 171 /// See_also: $(LINK http://wiki.libsdl.org/SDL_RenderCopy) 172 /// Throws: $(D SDL2Exception) on error. 173 void copy(SDL2Texture texture, box2i srcRect, box2i dstRect) 174 { 175 auto f = texture.format(); 176 SDL_Rect src = box2i_to_SDL_Rect(srcRect); 177 SDL_Rect dst = box2i_to_SDL_Rect(dstRect); 178 if (0 != SDL_RenderCopy(_renderer, texture._handle, &src, &dst)) 179 _sdl2.throwSDL2Exception("SDL_RenderCopy"); 180 } 181 } 182 183 package 184 { 185 SDL2 _sdl2; 186 SDL_Renderer* _renderer; 187 } 188 189 private 190 { 191 static SDL_Rect box2i_to_SDL_Rect(box2i b) pure 192 { 193 SDL_Rect res = void; 194 res.x = b.min.x; 195 res.y = b.min.y; 196 res.w = b.width; 197 res.h = b.height; 198 return res; 199 } 200 } 201 } 202 203 /// SDL Renderer information. 204 final class SDL2RendererInfo 205 { 206 public 207 { 208 this(Logger logger, int index, SDL_RendererInfo info) 209 { 210 _logger = logger; 211 _index = index; 212 _info = info; 213 } 214 215 /// Returns: Renderer name. 216 string name() 217 { 218 return sanitizeUTF8(_info.name, _logger, "SDL2 renderer name"); 219 } 220 221 /// Returns: true if this renderer is software. 222 bool isSoftware() 223 { 224 return (_info.flags & SDL_RENDERER_SOFTWARE) != 0; 225 } 226 227 /// Returns: true if this renderer is accelerated. 228 bool isAccelerated() 229 { 230 return (_info.flags & SDL_RENDERER_ACCELERATED) != 0; 231 } 232 233 /// Returns: true if this renderer can render to a texture. 234 bool hasRenderToTexture() 235 { 236 return (_info.flags & SDL_RENDERER_TARGETTEXTURE) != 0; 237 } 238 239 /// Returns: true if this renderer support vertical synchronization. 240 bool isVsyncEnabled() 241 { 242 return (_info.flags & SDL_RENDERER_PRESENTVSYNC) != 0; 243 } 244 245 /// Returns: Pretty string describing the renderer. 246 override string toString() 247 { 248 string res = format("renderer #%d: %s [flags:", _index, name()); 249 if (isSoftware()) res ~= " software"; 250 if (isAccelerated()) res ~= " accelerated"; 251 if (hasRenderToTexture()) res ~= " render-to-texture"; 252 if (isVsyncEnabled()) res ~= " vsync"; 253 res ~= "]\n"; 254 res ~= format("max. texture: %sx%s", _info.max_texture_width, _info.max_texture_height); 255 return res; 256 } 257 } 258 259 private 260 { 261 Logger _logger; 262 int _index; 263 SDL_RendererInfo _info; 264 } 265 }