1 /** 2 * ae.ui.video.renderer 3 * 4 * License: 5 * This Source Code Form is subject to the terms of 6 * the Mozilla Public License, v. 2.0. If a copy of 7 * the MPL was not distributed with this file, You 8 * can obtain one at http://mozilla.org/MPL/2.0/. 9 * 10 * Authors: 11 * Vladimir Panteleev <ae@cy.md> 12 */ 13 14 module ae.ui.video.renderer; 15 16 public import ae.utils.graphics.color; 17 public import ae.utils.graphics.image; 18 public import ae.utils.graphics.view; 19 20 import ae.utils.meta : enumLength; 21 22 /// Abstract class for a video renderer. 23 class Renderer 24 { 25 alias COLOR = BGRX; /// The color type we use for all rendering. 26 27 /// BGRX/BGRA-only. 28 struct Bitmap 29 { 30 static assert(COLOR.sizeof == uint.sizeof); 31 /// `ae.utils.graphics.view` implementation. 32 alias StorageType = PlainStorageUnit!COLOR; 33 34 StorageType* pixels; /// ditto 35 /// ditto 36 xy_t w, h, stride; 37 38 inout(StorageType)[] scanline(xy_t y) inout 39 { 40 assert(y>=0 && y<h); 41 return pixels[stride*y..stride*(y+1)]; 42 } /// ditto 43 44 mixin DirectView; 45 } 46 47 /// True when this renderer can lock quickly (usually when it's rendering in software). 48 /*immutable*/ bool canFastLock; 49 50 /// Lock a 32-bit, BGRX/BGRA surface 51 abstract Bitmap fastLock(); 52 53 /// ditto 54 abstract Bitmap lock(); 55 56 /// Unlock what was previously locked 57 abstract void unlock(); 58 59 /// Finalize rendering and present it to the user (flip buffers etc.) 60 abstract void present(); 61 62 /// Destroy any bound resources 63 abstract void shutdown(); 64 65 // ********************************************************************** 66 67 /// Get geometry. 68 abstract @property uint width(); 69 abstract @property uint height(); /// ditto 70 71 /// Set a single pixel. 72 abstract void putPixel(int x, int y, COLOR color); 73 74 /// Set some pixels. 75 struct Pixel { int x, /***/ y; /***/ COLOR color; /***/ } 76 void putPixels(Pixel[] pixels) 77 { 78 foreach (ref pixel; pixels) 79 putPixel(pixel.tupleof); 80 } /// ditto 81 82 /// Draw a straight line. 83 abstract void line(float x0, float y0, float x1, float y1, COLOR color); 84 /// Draw a vertical line. 85 void vline(int x, int y0, int y1, COLOR color) { line(x, y0, x, y1, color); } 86 /// Draw a horizontal line. 87 void hline(int x0, int x1, int y, COLOR color) { line(x0, y, x1, y, color); } 88 89 /// Draw a filled rectangle. 90 abstract void fillRect(int x0, int y0, int x1, int y1, COLOR color); 91 abstract void fillRect(float x0, float y0, float x1, float y1, COLOR color); /// ditto 92 93 /// Clear the entire surface. 94 abstract void clear(); 95 96 /// Draw a texture. 97 abstract void draw(int x, int y, TextureSource source, int u0, int v0, int u1, int v1); 98 99 /// Draw a texture with scaling. 100 abstract void draw(float x0, float y0, float x1, float y1, TextureSource source, int u0, int v0, int u1, int v1); 101 } 102 103 /// Uniquely identify private data owned by different renderers 104 enum Renderers 105 { 106 SDLSoftware, /// 107 SDLOpenGL, /// 108 SDL2, /// 109 } 110 111 /// Base class for all renderer-specific texture data 112 class TextureRenderData 113 { 114 /// If `true`, the `TextureSource` has been destroyed, 115 /// and so should this instance (in the render thread)> 116 bool destroyed; 117 118 /// Uploaded version number of the texture. 119 /// If it does not match `TextureSource.textureVersion`, 120 /// it needs to be updated. 121 uint textureVersion = 0; 122 123 /// Set to `true` when any `TextureRenderData` 124 /// needs to be destroyed. 125 static shared bool cleanupNeeded; 126 } 127 128 /// Base class for logical textures 129 class TextureSource 130 { 131 // TODO: make this extensible for external renderer implementations. 132 /// Renderer-specific texture data. 133 TextureRenderData[enumLength!Renderers] renderData; 134 135 /// Source version number of the texture. 136 uint textureVersion = 1; 137 138 /// Common type used by `drawTo` / `getPixels` 139 alias ImageRef!(Renderer.COLOR) TextureCanvas; 140 141 /// Request the contents of this `TextureSource`. 142 /// Used when the target pixel memory is already allocated 143 abstract void drawTo(TextureCanvas dest); 144 145 /// Request the contents of this `TextureSource`. 146 /// Used when a pointer is needed to existing pixel memory 147 abstract TextureCanvas getPixels(); 148 149 ~this() @nogc 150 { 151 foreach (r; renderData) 152 if (r) 153 r.destroyed = true; 154 TextureRenderData.cleanupNeeded = true; 155 } 156 } 157 158 /// Implementation of `TextureSource` 159 /// using an `ae.utils.graphics.image.Image`. 160 class ImageTextureSource : TextureSource 161 { 162 Image!(Renderer.COLOR) image; /// The image. 163 164 override void drawTo(TextureCanvas dest) 165 { 166 image.blitTo(dest); 167 } /// 168 169 override TextureCanvas getPixels() 170 { 171 return image.toRef(); 172 } /// 173 } 174 175 /// Base class for `TextureSource` implementations 176 /// where pixel data is calculated on request. 177 class ProceduralTextureSource : TextureSource 178 { 179 private Image!(Renderer.COLOR) cachedImage; 180 181 /// Query the size of the procedural texture 182 abstract void getSize(out int width, out int height); 183 184 /// Implementation of `getPixels` using 185 /// `drawTo` and a cached copy. 186 override TextureCanvas getPixels() 187 { 188 if (!cachedImage.w) 189 { 190 int w, h; 191 getSize(w, h); 192 cachedImage.size(w, h); 193 drawTo(cachedImage.toRef()); 194 } 195 return cachedImage.toRef(); 196 } 197 }