1 module gfm.sdl2.renderer; 2 3 import std.string; 4 5 import derelict.sdl2.sdl; 6 7 import std.experimental.logger; 8 9 import gfm.sdl2.sdl, 10 gfm.sdl2.window, 11 gfm.sdl2.texture, 12 gfm.sdl2.surface; 13 14 /// SDL Renderer wrapper. 15 final class SDL2Renderer 16 { 17 public 18 { 19 /// Creates a SDL renderer which targets a window. 20 /// See_also: $(LINK http://wiki.libsdl.org/SDL_CreateRenderer) 21 /// Throws: $(D SDL2Exception) on error. 22 this(SDL2Window window, int flags = 0) 23 { 24 _sdl2 = window._sdl2; 25 _renderer = SDL_CreateRenderer(window._window, -1, flags); 26 if (_renderer is null) 27 _sdl2.throwSDL2Exception("SDL_CreateRenderer"); 28 29 readCapabilities(); 30 } 31 32 /// Create a software renderer which targets a surface. 33 /// See_also: $(LINK http://wiki.libsdl.org/SDL_CreateSoftwareRenderer) 34 /// Throws: $(D SDL2Exception) on error. 35 this(SDL2Surface surface) 36 { 37 _sdl2 = surface._sdl2; 38 _renderer = SDL_CreateSoftwareRenderer(surface._surface); 39 if (_renderer is null) 40 _sdl2.throwSDL2Exception("SDL_CreateSoftwareRenderer"); 41 42 readCapabilities(); 43 } 44 45 /// Releases the SDL ressource. 46 /// See_also: $(LINK http://wiki.libsdl.org/SDL_DestroyRenderer) 47 ~this() 48 { 49 if (_renderer !is null) 50 { 51 debug ensureNotInGC("SDL2Renderer"); 52 SDL_DestroyRenderer(_renderer); 53 _renderer = null; 54 } 55 } 56 57 /// Clear the current rendering target with the drawing color. 58 /// See_also: $(LINK http://wiki.libsdl.org/SDL_RenderClear) 59 /// Throws: $(D SDL2Exception) on error. 60 void clear() 61 { 62 if (0 != SDL_RenderClear(_renderer)) 63 _sdl2.throwSDL2Exception("SDL_RenderClear"); 64 } 65 66 /// Update the screen with rendering performed. 67 /// See_also: $(LINK http://wiki.libsdl.org/SDL_RenderPresent) 68 void present() 69 { 70 SDL_RenderPresent(_renderer); 71 } 72 73 /// Sets the color used for drawing operations. 74 /// See_also: $(LINK http://wiki.libsdl.org/SDL_SetRenderDrawColor) 75 /// Throws: $(D SDL2Exception) on error. 76 void setColor(int r, int g, int b, int a = 255) 77 { 78 if (0 != SDL_SetRenderDrawColor(_renderer, cast(ubyte)r, cast(ubyte)g, cast(ubyte)b, cast(ubyte)a)) 79 _sdl2.throwSDL2Exception("SDL_SetRenderDrawColor"); 80 } 81 82 /// Sets the window drawing area. 83 /// See_also: $(LINK http://wiki.libsdl.org/SDL_RenderSetViewport) 84 /// Throws: $(D SDL2Exception) on error. 85 void setViewport(int x, int y, int w, int h) 86 { 87 SDL_Rect r = SDL_Rect(x, y, w, h); 88 if (0 != SDL_RenderSetViewport(_renderer, &r)) 89 _sdl2.throwSDL2Exception("SDL_RenderSetViewport"); 90 } 91 92 /// Sets the whole window as drawing area. 93 /// See_also: $(LINK http://wiki.libsdl.org/SDL_RenderSetViewport) 94 /// Throws: $(D SDL2Exception) on error. 95 void setViewportFull() 96 { 97 if (0 != SDL_RenderSetViewport(_renderer, null)) 98 _sdl2.throwSDL2Exception("SDL_RenderSetViewport"); 99 } 100 101 /// Sets the scale of the renderer. 102 /// See_also: $(LINK http://wiki.libsdl.org/SDL_RenderSetScale) 103 /// Throws: $(D SDL2Exception) on error. 104 void setScale(float x, float y) 105 { 106 if (0 != SDL_RenderSetScale(_renderer, x, y)) 107 _sdl2.throwSDL2Exception("SDL_RenderSetScale"); 108 } 109 110 /// Sets a device independent resolution of the renderer. 111 /// See_also: $(LINK http://wiki.libsdl.org/SDL_RenderSetLogicalSize) 112 /// Throws: $(D SDL2Exception) on error. 113 void setLogicalSize(int w, int h) 114 { 115 if (0 != SDL_RenderSetLogicalSize(_renderer, w, h)) 116 _sdl2.throwSDL2Exception("SDL_RenderSetLogicalSize"); 117 } 118 119 /// Sets SDL blend mode. 120 /// See_also: $(LINK http://wiki.libsdl.org/SDL_SetRenderDrawBlendMode) 121 /// Throws: $(D SDL2Exception) on error. 122 void setBlend(int blendMode) 123 { 124 if (0 != SDL_SetRenderDrawBlendMode(_renderer, blendMode)) 125 _sdl2.throwSDL2Exception("SDL_SetRenderDrawBlendMode"); 126 } 127 128 /// Draw a line. 129 /// See_also: $(LINK http://wiki.libsdl.org/SDL_RenderDrawLine) 130 /// Throws: $(D SDL2Exception) on error. 131 void drawLine(int x1, int y1, int x2, int y2) 132 { 133 if (0 != SDL_RenderDrawLine(_renderer, x1, y1, x2, y2)) 134 _sdl2.throwSDL2Exception("SDL_RenderDrawLine"); 135 136 } 137 138 /// Draw several lines at once. 139 /// See_also: $(LINK http://wiki.libsdl.org/SDL_RenderDrawLines) 140 /// Throws: $(D SDL2Exception) on error. 141 void drawLines(SDL_Point[] points) 142 { 143 if (0 != SDL_RenderDrawLines(_renderer, points.ptr, cast(int)(points.length))) 144 _sdl2.throwSDL2Exception("SDL_RenderDrawLines"); 145 } 146 147 /// Draw a point. 148 /// See_also: $(LINK http://wiki.libsdl.org/SDL_RenderDrawPoint) 149 /// Throws: $(D SDL2Exception) on error. 150 void drawPoint(int x, int y) 151 { 152 if (0 != SDL_RenderDrawPoint(_renderer, x, y)) 153 _sdl2.throwSDL2Exception("SDL_RenderDrawPoint"); 154 } 155 156 /// Draw several point at once. 157 /// See_also: $(LINK http://wiki.libsdl.org/SDL_RenderDrawPoints) 158 /// Throws: $(D SDL2Exception) on error. 159 void drawPoints(SDL_Point[] points) 160 { 161 if (0 != SDL_RenderDrawPoints(_renderer, points.ptr, cast(int)(points.length))) 162 _sdl2.throwSDL2Exception("SDL_RenderDrawPoints"); 163 } 164 165 /// Draw a rectangle outline. 166 /// See_also: $(LINK http://wiki.libsdl.org/SDL_RenderDrawRect) 167 /// Throws: $(D SDL2Exception) on error. 168 void drawRect(int x, int y, int width, int height) 169 { 170 SDL_Rect r = SDL_Rect(x, y, width, height); 171 if (0 != SDL_RenderDrawRect(_renderer, &r)) 172 _sdl2.throwSDL2Exception("SDL_RenderDrawRect"); 173 } 174 175 /// Draw a filled rectangle. 176 /// See_also: $(LINK http://wiki.libsdl.org/SDL_RenderFillRect) 177 /// Throws: $(D SDL2Exception) on error. 178 void fillRect(int x, int y, int width, int height) 179 { 180 SDL_Rect r = SDL_Rect(x, y, width, height); 181 if (0 != SDL_RenderFillRect(_renderer, &r)) 182 _sdl2.throwSDL2Exception("SDL_RenderFillRect"); 183 } 184 185 /// Blit a rectangle from a texture. 186 /// See_also: $(LINK http://wiki.libsdl.org/SDL_RenderCopy) 187 /// Throws: $(D SDL2Exception) on error. 188 void copy(SDL2Texture texture, SDL_Rect srcRect, SDL_Rect dstRect) 189 { 190 if (0 != SDL_RenderCopy(_renderer, texture._handle, &srcRect, &dstRect)) 191 _sdl2.throwSDL2Exception("SDL_RenderCopy"); 192 } 193 194 /// Draws a whole texture. 195 /// See_also: $(LINK http://wiki.libsdl.org/SDL_RenderCopy) 196 /// Throws: $(D SDL2Exception) on error. 197 void copy(SDL2Texture texture, int x, int y) 198 { 199 int w = texture.width(); 200 int h = texture.height(); 201 SDL_Rect source = SDL_Rect(0, 0, w, h); 202 SDL_Rect dest = SDL_Rect(x, y, w, h); 203 copy(texture, source, dest); 204 } 205 206 /// Blits a rectangle from a texture and apply rotation/reflection. 207 /// See_also: $(LINK http://wiki.libsdl.org/SDL_RenderCopyEx) 208 /// Throws: $(D SDL2Exception) on error. 209 void copyEx(SDL2Texture texture, SDL_Rect srcRect, SDL_Rect dstRect, double rotangle, SDL_Point* rotcenter, SDL_RendererFlip flip) 210 { 211 if (0 != SDL_RenderCopyEx(_renderer, texture._handle, &srcRect, &dstRect, rotangle, rotcenter, flip)) 212 _sdl2.throwSDL2Exception("SDL_RenderCopyEx"); 213 } 214 215 /// Set a texture as the current rendering target. 216 /// See_also: $(LINK http://wiki.libsdl.org/SDL_SetRenderTarget) 217 /// Throws: $(D SDL2Exception) on error. 218 void setRenderTarget(SDL2Texture texture) 219 { 220 if (0 != SDL_SetRenderTarget(_renderer, texture is null ? cast(SDL_Texture*)0 : texture._handle)) 221 _sdl2.throwSDL2Exception("SDL_SetRenderTarget"); 222 } 223 224 /// Returns: Renderer information. 225 /// See_also: $(LINK http://wiki.libsdl.org/SDL_GetRendererInfo) 226 /// Throws: $(D SDL2Exception) on error. 227 SDL2RendererInfo info() 228 { 229 return _info; 230 } 231 232 /// Returns: SDL handle. 233 SDL_Renderer* handle() 234 { 235 return _renderer; 236 } 237 } 238 239 package 240 { 241 SDL2 _sdl2; 242 SDL_Renderer* _renderer; 243 SDL2RendererInfo _info; 244 } 245 246 private 247 { 248 void readCapabilities() 249 { 250 SDL_RendererInfo info; 251 int res = SDL_GetRendererInfo(_renderer, &info); 252 if (res != 0) 253 _sdl2.throwSDL2Exception("SDL_GetRendererInfo"); 254 _info = new SDL2RendererInfo(info); 255 } 256 } 257 } 258 259 /// SDL Renderer information. 260 final class SDL2RendererInfo 261 { 262 public 263 { 264 this(SDL_RendererInfo info) 265 { 266 _info = info; 267 } 268 269 /// Returns: Renderer name. 270 const(char)[] name() 271 { 272 return fromStringz(_info.name); 273 } 274 275 /// Returns: true if this renderer is software. 276 bool isSoftware() 277 { 278 return (_info.flags & SDL_RENDERER_SOFTWARE) != 0; 279 } 280 281 /// Returns: true if this renderer is accelerated. 282 bool isAccelerated() 283 { 284 return (_info.flags & SDL_RENDERER_ACCELERATED) != 0; 285 } 286 287 /// Returns: true if this renderer can render to a texture. 288 bool hasRenderToTexture() 289 { 290 return (_info.flags & SDL_RENDERER_TARGETTEXTURE) != 0; 291 } 292 293 /// Returns: true if this renderer support vertical synchronization. 294 bool isVsyncEnabled() 295 { 296 return (_info.flags & SDL_RENDERER_PRESENTVSYNC) != 0; 297 } 298 299 /// Returns: the maximum supported texture width 300 int maxTextureWidth() 301 { 302 return _info.max_texture_width; 303 } 304 305 /// Returns: the maximum supported texture height 306 int maxTextureHeight() 307 { 308 return _info.max_texture_height; 309 } 310 311 /// Returns: Pretty string describing the renderer. 312 override string toString() 313 { 314 string res = format("renderer: %s [flags:", name()); 315 if (isSoftware()) res ~= " software"; 316 if (isAccelerated()) res ~= " accelerated"; 317 if (hasRenderToTexture()) res ~= " render-to-texture"; 318 if (isVsyncEnabled()) res ~= " vsync"; 319 res ~= "]\n"; 320 res ~= format("max. supported texture size: %sx%s", maxTextureWidth(), maxTextureHeight()); 321 return res; 322 } 323 } 324 325 private 326 { 327 SDL_RendererInfo _info; 328 } 329 }