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