mediaMachineAPI.cpp 54 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212
  1. // zlib open source license
  2. //
  3. // Copyright (c) 2019 David Forsgren Piuva
  4. //
  5. // This software is provided 'as-is', without any express or implied
  6. // warranty. In no event will the authors be held liable for any damages
  7. // arising from 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
  14. // claim that you wrote the original software. If you use this software
  15. // in a product, an acknowledgment in the product documentation would be
  16. // appreciated but is 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
  22. // distribution.
  23. #define DFPSR_INTERNAL_ACCESS
  24. #include "mediaMachineAPI.h"
  25. #include "../machine/VirtualMachine.h"
  26. #include "../machine/mediaFilters.h"
  27. #include "../api/imageAPI.h"
  28. namespace dsr {
  29. // Media Machine specification
  30. // Enumerating types
  31. static const DataType DataType_ImageU8 = 1;
  32. static const DataType DataType_ImageRgbaU8 = 2;
  33. static ReadableString getMediaTypeName(DataType type) {
  34. switch(type) {
  35. case DataType_FixedPoint: return U"FixedPoint";
  36. case DataType_ImageU8: return U"ImageU8";
  37. case DataType_ImageRgbaU8: return U"ImageRgbaU8";
  38. default: return U"?";
  39. }
  40. }
  41. class MediaMemory : public PlanarMemory {
  42. public:
  43. MemoryPlane<FixedPoint> FixedPointMemory;
  44. MemoryPlane<AlignedImageU8> AlignedImageU8Memory;
  45. MemoryPlane<OrderedImageRgbaU8> OrderedImageRgbaU8Memory;
  46. MediaMemory() : FixedPointMemory(1024), AlignedImageU8Memory(1024), OrderedImageRgbaU8Memory(512) {}
  47. void store(int targetStackIndex, const VMA& sourceArg, int sourceFramePointer, DataType type) override {
  48. switch(type) {
  49. case DataType_FixedPoint:
  50. if (sourceArg.argType == ArgumentType::Immediate) {
  51. #ifdef VIRTUAL_MACHINE_DEBUG_PRINT
  52. printText(U"Storing: FixedPoint[", targetStackIndex, U"] <- immediate ", sourceArg.value, U".\n");
  53. #endif
  54. this->FixedPointMemory.accessByStackIndex(targetStackIndex) = sourceArg.value;
  55. } else {
  56. int globalIndex = sourceArg.value.getMantissa();
  57. FixedPoint value = this->FixedPointMemory.accessByGlobalIndex(globalIndex, sourceFramePointer);
  58. #ifdef VIRTUAL_MACHINE_DEBUG_PRINT
  59. if (globalIndex < 0) {
  60. printText(U"Storing: FixedPoint[", targetStackIndex, U"] <- FixedPoint[", -(globalIndex + 1), U"] = ", value, U".\n");
  61. } else {
  62. printText(U"Storing: FixedPoint[", targetStackIndex, U"] <- FixedPoint[fp(", sourceFramePointer, U") + ", globalIndex, U"] = ", value, U".\n");
  63. }
  64. #endif
  65. this->FixedPointMemory.accessByStackIndex(targetStackIndex) = value;
  66. }
  67. break;
  68. case DataType_ImageU8:
  69. this->AlignedImageU8Memory.accessByStackIndex(targetStackIndex) = this->AlignedImageU8Memory.accessByGlobalIndex(sourceArg.value.getMantissa(), sourceFramePointer);
  70. break;
  71. case DataType_ImageRgbaU8:
  72. this->OrderedImageRgbaU8Memory.accessByStackIndex(targetStackIndex) = this->OrderedImageRgbaU8Memory.accessByGlobalIndex(sourceArg.value.getMantissa(), sourceFramePointer);
  73. break;
  74. default:
  75. throwError("Storing element of unhandled type!\n");
  76. break;
  77. }
  78. }
  79. void load(int sourceStackIndex, const VMA& targetArg, int targetFramePointer, DataType type) override {
  80. int globalIndex = targetArg.value.getMantissa();
  81. switch(type) {
  82. case DataType_FixedPoint:
  83. this->FixedPointMemory.accessByGlobalIndex(globalIndex, targetFramePointer) = this->FixedPointMemory.accessByStackIndex(sourceStackIndex);
  84. break;
  85. case DataType_ImageU8:
  86. this->AlignedImageU8Memory.accessByGlobalIndex(globalIndex, targetFramePointer) = this->AlignedImageU8Memory.accessByStackIndex(sourceStackIndex);
  87. break;
  88. case DataType_ImageRgbaU8:
  89. this->OrderedImageRgbaU8Memory.accessByGlobalIndex(globalIndex, targetFramePointer) = this->OrderedImageRgbaU8Memory.accessByStackIndex(sourceStackIndex);
  90. break;
  91. default:
  92. throwError("Loading element of unhandled type!\n");
  93. break;
  94. }
  95. }
  96. };
  97. #define MEDIA_MEMORY ((MediaMemory&)memory)
  98. // Type definitions
  99. static const VMTypeDef mediaMachineTypes[] = {
  100. VMTypeDef(U"FixedPoint", DataType_FixedPoint, true,
  101. [](VirtualMachine& machine, int globalIndex, const ReadableString& defaultValueText){
  102. FixedPoint defaultValue = string_length(defaultValueText) > 0 ? FixedPoint::fromText(defaultValueText) : FixedPoint();
  103. List<VMA> args;
  104. args.pushConstruct(DataType_FixedPoint, globalIndex);
  105. args.pushConstruct(defaultValue);
  106. machine.interpretCommand(U"Load", args);
  107. },
  108. [](PlanarMemory& memory, Variable& variable, int globalIndex, int32_t* framePointer, bool fullContent) {
  109. FixedPoint value = MEDIA_MEMORY.FixedPointMemory.accessByGlobalIndex(globalIndex, framePointer[DataType_FixedPoint]);
  110. printText(variable.name, "(", value, ")");
  111. }),
  112. VMTypeDef(U"ImageU8", DataType_ImageU8, false,
  113. [](VirtualMachine& machine, int globalIndex, const ReadableString& defaultValueText){
  114. List<VMA> args;
  115. args.pushConstruct(DataType_ImageU8, globalIndex);
  116. machine.interpretCommand(U"Reset", args);
  117. },
  118. [](PlanarMemory& memory, Variable& variable, int globalIndex, int32_t* framePointer, bool fullContent) {
  119. AlignedImageU8 value = MEDIA_MEMORY.AlignedImageU8Memory.accessByGlobalIndex(globalIndex, framePointer[DataType_ImageU8]);
  120. printText(variable.name, " ImageU8");
  121. if (image_exists(value)) {
  122. if (fullContent) {
  123. printText(":\n", image_toAscii(value, U" .:*ixXM"));
  124. } else {
  125. printText("(", image_getWidth(value), "x", image_getHeight(value), ")");
  126. }
  127. } else {
  128. printText("(nothing)");
  129. }
  130. }),
  131. VMTypeDef(U"ImageRgbaU8", DataType_ImageRgbaU8, false,
  132. [](VirtualMachine& machine, int globalIndex, const ReadableString& defaultValueText){
  133. List<VMA> args;
  134. args.pushConstruct(DataType_ImageRgbaU8, globalIndex);
  135. machine.interpretCommand(U"Reset", args);
  136. },
  137. [](PlanarMemory& memory, Variable& variable, int globalIndex, int32_t* framePointer, bool fullContent) {
  138. OrderedImageRgbaU8 value = MEDIA_MEMORY.OrderedImageRgbaU8Memory.accessByGlobalIndex(globalIndex, framePointer[DataType_ImageRgbaU8]);
  139. printText(variable.name, " ImageRgbaU8");
  140. if (image_exists(value)) {
  141. // TODO: image_toAscii for multi-channel images
  142. printText("(", image_getWidth(value), "x", image_getHeight(value), ")");
  143. } else {
  144. printText("(nothing)");
  145. }
  146. })
  147. };
  148. inline FixedPoint getFixedPointValue(MediaMemory& memory, const VMA& arg) {
  149. if (arg.argType == ArgumentType::Immediate) {
  150. return arg.value;
  151. } else {
  152. return memory.FixedPointMemory.getRef(arg, memory.current.framePointer[DataType_FixedPoint]);
  153. }
  154. }
  155. #define SCALAR_VALUE(ARG_INDEX) getFixedPointValue(MEDIA_MEMORY, args[ARG_INDEX])
  156. #define INT_VALUE(ARG_INDEX) fixedPoint_round(SCALAR_VALUE(ARG_INDEX))
  157. #define SCALAR_REF(ARG_INDEX) (MEDIA_MEMORY.FixedPointMemory.getRef(args[ARG_INDEX], memory.current.framePointer[DataType_FixedPoint]))
  158. #define IMAGE_U8_REF(ARG_INDEX) (MEDIA_MEMORY.AlignedImageU8Memory.getRef(args[ARG_INDEX], memory.current.framePointer[DataType_ImageU8]))
  159. #define IMAGE_RGBAU8_REF(ARG_INDEX) (MEDIA_MEMORY.OrderedImageRgbaU8Memory.getRef(args[ARG_INDEX], memory.current.framePointer[DataType_ImageRgbaU8]))
  160. #define NEXT_INSTRUCTION memory.current.programCounter++;
  161. static const InsSig mediaMachineInstructions[] = {
  162. InsSig::create(U"LOAD", 1,
  163. [](VirtualMachine& machine, PlanarMemory& memory, const List<VMA>& args) {
  164. SCALAR_REF(0) = SCALAR_VALUE(1);
  165. NEXT_INSTRUCTION
  166. },
  167. ArgSig(U"Target", false, DataType_FixedPoint),
  168. ArgSig(U"Source", true, DataType_FixedPoint)
  169. ),
  170. InsSig::create(U"RESET", 1,
  171. [](VirtualMachine& machine, PlanarMemory& memory, const List<VMA>& args) {
  172. IMAGE_U8_REF(0) = AlignedImageU8();
  173. NEXT_INSTRUCTION
  174. },
  175. ArgSig(U"Target", false, DataType_ImageU8)
  176. ),
  177. InsSig::create(U"RESET", 1,
  178. [](VirtualMachine& machine, PlanarMemory& memory, const List<VMA>& args) {
  179. IMAGE_RGBAU8_REF(0) = OrderedImageRgbaU8();
  180. NEXT_INSTRUCTION
  181. },
  182. ArgSig(U"Target", false, DataType_ImageRgbaU8)
  183. ),
  184. InsSig::create(U"ROUND", 1,
  185. [](VirtualMachine& machine, PlanarMemory& memory, const List<VMA>& args) {
  186. SCALAR_REF(0) = FixedPoint::fromWhole(fixedPoint_round(SCALAR_VALUE(1)));
  187. NEXT_INSTRUCTION
  188. },
  189. ArgSig(U"Target", false, DataType_FixedPoint), // Aliasing is accepted
  190. ArgSig(U"Source", true, DataType_FixedPoint)
  191. ),
  192. InsSig::create(U"MIN", 1,
  193. [](VirtualMachine& machine, PlanarMemory& memory, const List<VMA>& args) {
  194. SCALAR_REF(0) = fixedPoint_min(SCALAR_VALUE(1), SCALAR_VALUE(2));
  195. NEXT_INSTRUCTION
  196. },
  197. ArgSig(U"Target", false, DataType_FixedPoint), // Aliasing is accepted
  198. ArgSig(U"LeftSource", true, DataType_FixedPoint),
  199. ArgSig(U"RightSource", true, DataType_FixedPoint)
  200. ),
  201. InsSig::create(U"MAX", 1,
  202. [](VirtualMachine& machine, PlanarMemory& memory, const List<VMA>& args) {
  203. SCALAR_REF(0) = fixedPoint_max(SCALAR_VALUE(1), SCALAR_VALUE(2));
  204. NEXT_INSTRUCTION
  205. },
  206. ArgSig(U"Target", false, DataType_FixedPoint), // Aliasing is accepted
  207. ArgSig(U"LeftSource", true, DataType_FixedPoint),
  208. ArgSig(U"RightSource", true, DataType_FixedPoint)
  209. ),
  210. InsSig::create(U"ADD", 1,
  211. [](VirtualMachine& machine, PlanarMemory& memory, const List<VMA>& args) {
  212. SCALAR_REF(0) = SCALAR_VALUE(1) + SCALAR_VALUE(2);
  213. NEXT_INSTRUCTION
  214. },
  215. ArgSig(U"Target", false, DataType_FixedPoint), // Aliasing is accepted
  216. ArgSig(U"LeftSource", true, DataType_FixedPoint),
  217. ArgSig(U"RightSource", true, DataType_FixedPoint)
  218. ),
  219. InsSig::create(U"ADD", 1,
  220. [](VirtualMachine& machine, PlanarMemory& memory, const List<VMA>& args) {
  221. media_filter_add(IMAGE_U8_REF(0), IMAGE_U8_REF(1), IMAGE_U8_REF(2));
  222. NEXT_INSTRUCTION
  223. },
  224. ArgSig(U"Target", false, DataType_ImageU8), // Aliasing is accepted
  225. ArgSig(U"LeftSource", true, DataType_ImageU8),
  226. ArgSig(U"RightSource", true, DataType_ImageU8)
  227. ),
  228. InsSig::create(U"ADD", 1,
  229. [](VirtualMachine& machine, PlanarMemory& memory, const List<VMA>& args) {
  230. media_filter_add(IMAGE_U8_REF(0), IMAGE_U8_REF(1), SCALAR_VALUE(2));
  231. NEXT_INSTRUCTION
  232. },
  233. ArgSig(U"Target", false, DataType_ImageU8), // Aliasing is accepted
  234. ArgSig(U"LeftSource", true, DataType_ImageU8),
  235. ArgSig(U"RightSource", true, DataType_FixedPoint)
  236. ),
  237. InsSig::create(U"ADD", 1,
  238. [](VirtualMachine& machine, PlanarMemory& memory, const List<VMA>& args) {
  239. media_filter_add(IMAGE_U8_REF(0), IMAGE_U8_REF(2), SCALAR_VALUE(1));
  240. NEXT_INSTRUCTION
  241. },
  242. ArgSig(U"Target", false, DataType_ImageU8), // Aliasing is accepted
  243. ArgSig(U"LeftSource", true, DataType_FixedPoint),
  244. ArgSig(U"RightSource", true, DataType_ImageU8)
  245. ),
  246. InsSig::create(U"SUB", 1,
  247. [](VirtualMachine& machine, PlanarMemory& memory, const List<VMA>& args) {
  248. SCALAR_REF(0) = SCALAR_VALUE(1) - SCALAR_VALUE(2);
  249. NEXT_INSTRUCTION
  250. },
  251. ArgSig(U"Target", false, DataType_FixedPoint), // Aliasing is accepted
  252. ArgSig(U"PositiveSource", true, DataType_FixedPoint),
  253. ArgSig(U"NegativeSource", true, DataType_FixedPoint)
  254. ),
  255. InsSig::create(U"SUB", 1,
  256. [](VirtualMachine& machine, PlanarMemory& memory, const List<VMA>& args) {
  257. media_filter_sub(IMAGE_U8_REF(0), IMAGE_U8_REF(1), IMAGE_U8_REF(2));
  258. NEXT_INSTRUCTION
  259. },
  260. ArgSig(U"Target", false, DataType_ImageU8), // Aliasing is accepted
  261. ArgSig(U"PositiveSource", true, DataType_ImageU8),
  262. ArgSig(U"NegativeSource", true, DataType_ImageU8)
  263. ),
  264. InsSig::create(U"SUB", 1,
  265. [](VirtualMachine& machine, PlanarMemory& memory, const List<VMA>& args) {
  266. media_filter_sub(IMAGE_U8_REF(0), IMAGE_U8_REF(1), SCALAR_VALUE(2));
  267. NEXT_INSTRUCTION
  268. },
  269. ArgSig(U"Target", false, DataType_ImageU8), // Aliasing is accepted
  270. ArgSig(U"PositiveSource", true, DataType_ImageU8),
  271. ArgSig(U"NegativeSource", true, DataType_FixedPoint)
  272. ),
  273. InsSig::create(U"SUB", 1,
  274. [](VirtualMachine& machine, PlanarMemory& memory, const List<VMA>& args) {
  275. media_filter_sub(IMAGE_U8_REF(0), SCALAR_VALUE(2), IMAGE_U8_REF(1));
  276. NEXT_INSTRUCTION
  277. },
  278. ArgSig(U"Target", false, DataType_ImageU8), // Aliasing is accepted
  279. ArgSig(U"PositiveSource", true, DataType_FixedPoint),
  280. ArgSig(U"NegativeSource", true, DataType_ImageU8)
  281. ),
  282. InsSig::create(U"MUL", 1,
  283. [](VirtualMachine& machine, PlanarMemory& memory, const List<VMA>& args) {
  284. SCALAR_REF(0) = SCALAR_VALUE(1) * SCALAR_VALUE(2);
  285. NEXT_INSTRUCTION
  286. },
  287. ArgSig(U"Target", false, DataType_FixedPoint), // Aliasing is accepted
  288. ArgSig(U"LeftSource", true, DataType_FixedPoint),
  289. ArgSig(U"RightSource", true, DataType_FixedPoint)
  290. ),
  291. InsSig::create(U"MUL", 1,
  292. [](VirtualMachine& machine, PlanarMemory& memory, const List<VMA>& args) {
  293. media_filter_mul(IMAGE_U8_REF(0), IMAGE_U8_REF(1), SCALAR_VALUE(2));
  294. NEXT_INSTRUCTION
  295. },
  296. ArgSig(U"Target", false, DataType_ImageU8), // Aliasing is accepted
  297. ArgSig(U"LeftSource", true, DataType_ImageU8),
  298. ArgSig(U"RightSource", true, DataType_FixedPoint)
  299. ),
  300. InsSig::create(U"MUL", 1,
  301. [](VirtualMachine& machine, PlanarMemory& memory, const List<VMA>& args) {
  302. media_filter_mul(IMAGE_U8_REF(0), IMAGE_U8_REF(1), IMAGE_U8_REF(2), SCALAR_VALUE(3));
  303. NEXT_INSTRUCTION
  304. },
  305. ArgSig(U"Target", false, DataType_ImageU8), // Aliasing is accepted
  306. ArgSig(U"FirstSource", true, DataType_ImageU8),
  307. ArgSig(U"SecondSource", true, DataType_ImageU8),
  308. ArgSig(U"Scalar", true, DataType_FixedPoint) // Use 1/255 for normalized multiplication
  309. ),
  310. InsSig::create(U"CREATE", 1,
  311. [](VirtualMachine& machine, PlanarMemory& memory, const List<VMA>& args) {
  312. int width = INT_VALUE(1);
  313. int height = INT_VALUE(2);
  314. if (width < 1 || height < 1) {
  315. throwError("Images must allocate at least one pixel to be created.");
  316. }
  317. IMAGE_U8_REF(0) = image_create_U8(width, height);
  318. NEXT_INSTRUCTION
  319. },
  320. ArgSig(U"Target", false, DataType_ImageU8),
  321. ArgSig(U"Width", true, DataType_FixedPoint),
  322. ArgSig(U"Height", true, DataType_FixedPoint)
  323. ),
  324. InsSig::create(U"CREATE", 1,
  325. [](VirtualMachine& machine, PlanarMemory& memory, const List<VMA>& args) {
  326. int width = INT_VALUE(1);
  327. int height = INT_VALUE(2);
  328. if (width < 1 || height < 1) {
  329. throwError("Images must allocate at least one pixel to be created.");
  330. }
  331. IMAGE_RGBAU8_REF(0) = image_create_RgbaU8(width, height);
  332. NEXT_INSTRUCTION
  333. },
  334. ArgSig(U"Target", false, DataType_ImageRgbaU8),
  335. ArgSig(U"Width", true, DataType_FixedPoint),
  336. ArgSig(U"Height", true, DataType_FixedPoint)
  337. ),
  338. InsSig::create(U"EXISTS", 1,
  339. [](VirtualMachine& machine, PlanarMemory& memory, const List<VMA>& args) {
  340. SCALAR_REF(0) = FixedPoint::fromWhole(image_exists(IMAGE_U8_REF(1)) ? 1 : 0);
  341. NEXT_INSTRUCTION
  342. },
  343. ArgSig(U"Truth", false, DataType_FixedPoint), // 1 for existing, 0 for null
  344. ArgSig(U"Source", true, DataType_ImageU8)
  345. ),
  346. InsSig::create(U"EXISTS", 1,
  347. [](VirtualMachine& machine, PlanarMemory& memory, const List<VMA>& args) {
  348. SCALAR_REF(0) = FixedPoint::fromWhole(image_exists(IMAGE_RGBAU8_REF(1)) ? 1 : 0);
  349. NEXT_INSTRUCTION
  350. },
  351. ArgSig(U"Truth", false, DataType_FixedPoint), // 1 for existing, 0 for null
  352. ArgSig(U"Source", true, DataType_ImageRgbaU8)
  353. ),
  354. InsSig::create(U"GET_WIDTH", 1,
  355. [](VirtualMachine& machine, PlanarMemory& memory, const List<VMA>& args) {
  356. SCALAR_REF(0) = FixedPoint::fromWhole(image_getWidth(IMAGE_U8_REF(1)));
  357. NEXT_INSTRUCTION
  358. },
  359. ArgSig(U"Width", false, DataType_FixedPoint),
  360. ArgSig(U"Source", true, DataType_ImageU8)
  361. ),
  362. InsSig::create(U"GET_WIDTH", 1,
  363. [](VirtualMachine& machine, PlanarMemory& memory, const List<VMA>& args) {
  364. SCALAR_REF(0) = FixedPoint::fromWhole(image_getWidth(IMAGE_RGBAU8_REF(1)));
  365. NEXT_INSTRUCTION
  366. },
  367. ArgSig(U"Width", false, DataType_FixedPoint),
  368. ArgSig(U"Source", true, DataType_ImageRgbaU8)
  369. ),
  370. InsSig::create(U"GET_HEIGHT", 1,
  371. [](VirtualMachine& machine, PlanarMemory& memory, const List<VMA>& args) {
  372. SCALAR_REF(0) = FixedPoint::fromWhole(image_getHeight(IMAGE_U8_REF(1)));
  373. NEXT_INSTRUCTION
  374. },
  375. ArgSig(U"Height", false, DataType_FixedPoint),
  376. ArgSig(U"Source", true, DataType_ImageU8)
  377. ),
  378. InsSig::create(U"GET_HEIGHT", 1,
  379. [](VirtualMachine& machine, PlanarMemory& memory, const List<VMA>& args) {
  380. SCALAR_REF(0) = FixedPoint::fromWhole(image_getHeight(IMAGE_RGBAU8_REF(1)));
  381. NEXT_INSTRUCTION
  382. },
  383. ArgSig(U"Height", false, DataType_FixedPoint),
  384. ArgSig(U"Source", true, DataType_ImageRgbaU8)
  385. ),
  386. InsSig::create(U"FILL", 1,
  387. [](VirtualMachine& machine, PlanarMemory& memory, const List<VMA>& args) {
  388. image_fill(IMAGE_U8_REF(0), INT_VALUE(1));
  389. NEXT_INSTRUCTION
  390. },
  391. ArgSig(U"Target", false, DataType_ImageU8),
  392. ArgSig(U"Luma", true, DataType_FixedPoint)
  393. ),
  394. InsSig::create(U"FILL", 1,
  395. [](VirtualMachine& machine, PlanarMemory& memory, const List<VMA>& args) {
  396. image_fill(
  397. IMAGE_RGBAU8_REF(0),
  398. ColorRgbaI32(INT_VALUE(1), INT_VALUE(2), INT_VALUE(3), INT_VALUE(4))
  399. );
  400. NEXT_INSTRUCTION
  401. },
  402. ArgSig(U"Target", false, DataType_ImageRgbaU8),
  403. ArgSig(U"Red", true, DataType_FixedPoint),
  404. ArgSig(U"Green", true, DataType_FixedPoint),
  405. ArgSig(U"Blue", true, DataType_FixedPoint),
  406. ArgSig(U"Alpha", true, DataType_FixedPoint)
  407. ),
  408. InsSig::create(U"RECTANGLE", 1,
  409. [](VirtualMachine& machine, PlanarMemory& memory, const List<VMA>& args) {
  410. draw_rectangle(
  411. IMAGE_U8_REF(0),
  412. IRect(INT_VALUE(1), INT_VALUE(2), INT_VALUE(3), INT_VALUE(4)),
  413. INT_VALUE(5)
  414. );
  415. NEXT_INSTRUCTION
  416. },
  417. ArgSig(U"Target", false, DataType_ImageU8),
  418. ArgSig(U"Left", true, DataType_FixedPoint),
  419. ArgSig(U"Top", true, DataType_FixedPoint),
  420. ArgSig(U"Width", true, DataType_FixedPoint),
  421. ArgSig(U"Height", true, DataType_FixedPoint),
  422. ArgSig(U"Luma", true, DataType_FixedPoint)
  423. ),
  424. InsSig::create(U"RECTANGLE", 1,
  425. [](VirtualMachine& machine, PlanarMemory& memory, const List<VMA>& args) {
  426. draw_rectangle(
  427. IMAGE_RGBAU8_REF(0),
  428. IRect(INT_VALUE(1), INT_VALUE(2), INT_VALUE(3), INT_VALUE(4)),
  429. ColorRgbaI32(INT_VALUE(5), INT_VALUE(6), INT_VALUE(7), INT_VALUE(8))
  430. );
  431. NEXT_INSTRUCTION
  432. },
  433. ArgSig(U"Target", false, DataType_ImageRgbaU8),
  434. ArgSig(U"Left", true, DataType_FixedPoint),
  435. ArgSig(U"Top", true, DataType_FixedPoint),
  436. ArgSig(U"Width", true, DataType_FixedPoint),
  437. ArgSig(U"Height", true, DataType_FixedPoint),
  438. ArgSig(U"Red", true, DataType_FixedPoint),
  439. ArgSig(U"Green", true, DataType_FixedPoint),
  440. ArgSig(U"Blue", true, DataType_FixedPoint),
  441. ArgSig(U"Alpha", true, DataType_FixedPoint)
  442. ),
  443. InsSig::create(U"COPY", 1,
  444. [](VirtualMachine& machine, PlanarMemory& memory, const List<VMA>& args) {
  445. draw_copy(IMAGE_U8_REF(0), IMAGE_U8_REF(3), INT_VALUE(1), INT_VALUE(2));
  446. NEXT_INSTRUCTION
  447. },
  448. ArgSig(U"Target", false, DataType_ImageU8),
  449. ArgSig(U"TargetLeft", true, DataType_FixedPoint),
  450. ArgSig(U"TargetTop", true, DataType_FixedPoint),
  451. ArgSig(U"Source", true, DataType_ImageU8)
  452. ),
  453. InsSig::create(U"COPY", 1,
  454. [](VirtualMachine& machine, PlanarMemory& memory, const List<VMA>& args) {
  455. draw_copy(IMAGE_RGBAU8_REF(0), IMAGE_RGBAU8_REF(3), INT_VALUE(1), INT_VALUE(2));
  456. NEXT_INSTRUCTION
  457. },
  458. ArgSig(U"Target", false, DataType_ImageRgbaU8),
  459. ArgSig(U"TargetLeft", true, DataType_FixedPoint),
  460. ArgSig(U"TargetTop", true, DataType_FixedPoint),
  461. ArgSig(U"Source", true, DataType_ImageRgbaU8)
  462. ),
  463. InsSig::create(U"COPY", 1,
  464. [](VirtualMachine& machine, PlanarMemory& memory, const List<VMA>& args) {
  465. draw_copy(
  466. IMAGE_U8_REF(0),
  467. image_getSubImage(IMAGE_U8_REF(3), IRect(INT_VALUE(4), INT_VALUE(5), INT_VALUE(6), INT_VALUE(7))),
  468. INT_VALUE(1), INT_VALUE(2)
  469. );
  470. NEXT_INSTRUCTION
  471. },
  472. // TODO: Prevent aliasing between IMAGE_U8_REF(0) and IMAGE_U8_REF(3) in compile-time
  473. // This will be added as another lambda running safety checks on suggested inputs
  474. // The result will either accept, pass on to the next overload or abort compilation
  475. // Passing to another overload can be used to fall back on a run-time checked operation
  476. ArgSig(U"Target", false, DataType_ImageU8),
  477. ArgSig(U"TargetLeft", true, DataType_FixedPoint),
  478. ArgSig(U"TargetTop", true, DataType_FixedPoint),
  479. ArgSig(U"Source", true, DataType_ImageU8),
  480. ArgSig(U"SourceLeft", true, DataType_FixedPoint),
  481. ArgSig(U"SourceTop", true, DataType_FixedPoint),
  482. ArgSig(U"SourceWidth", true, DataType_FixedPoint),
  483. ArgSig(U"SourceHeight", true, DataType_FixedPoint)
  484. ),
  485. InsSig::create(U"COPY", 1,
  486. [](VirtualMachine& machine, PlanarMemory& memory, const List<VMA>& args) {
  487. draw_copy(
  488. IMAGE_RGBAU8_REF(0),
  489. image_getSubImage(IMAGE_RGBAU8_REF(3), IRect(INT_VALUE(4), INT_VALUE(5), INT_VALUE(6), INT_VALUE(7))),
  490. INT_VALUE(1), INT_VALUE(2)
  491. );
  492. NEXT_INSTRUCTION
  493. },
  494. // TODO: Prevent aliasing
  495. ArgSig(U"Target", false, DataType_ImageRgbaU8),
  496. ArgSig(U"TargetLeft", true, DataType_FixedPoint),
  497. ArgSig(U"TargetTop", true, DataType_FixedPoint),
  498. ArgSig(U"Source", true, DataType_ImageRgbaU8),
  499. ArgSig(U"SourceLeft", true, DataType_FixedPoint),
  500. ArgSig(U"SourceTop", true, DataType_FixedPoint),
  501. ArgSig(U"SourceWidth", true, DataType_FixedPoint),
  502. ArgSig(U"SourceHeight", true, DataType_FixedPoint)
  503. ),
  504. InsSig::create(U"RESIZE_BILINEAR", 1,
  505. [](VirtualMachine& machine, PlanarMemory& memory, const List<VMA>& args) {
  506. int width = INT_VALUE(1); if (width < 1) width = 1;
  507. int height = INT_VALUE(2); if (height < 1) height = 1;
  508. IMAGE_U8_REF(0) = filter_resize(IMAGE_U8_REF(3), Sampler::Linear, width, height);
  509. NEXT_INSTRUCTION
  510. },
  511. ArgSig(U"Target", false, DataType_ImageU8),
  512. ArgSig(U"NewWidth", true, DataType_FixedPoint),
  513. ArgSig(U"NewHeight", true, DataType_FixedPoint),
  514. ArgSig(U"Source", true, DataType_ImageU8)
  515. ),
  516. InsSig::create(U"RESIZE_BILINEAR", 1,
  517. [](VirtualMachine& machine, PlanarMemory& memory, const List<VMA>& args) {
  518. int width = INT_VALUE(1); if (width < 1) width = 1;
  519. int height = INT_VALUE(2); if (height < 1) height = 1;
  520. IMAGE_RGBAU8_REF(0) = filter_resize(IMAGE_RGBAU8_REF(3), Sampler::Linear, width, height);
  521. NEXT_INSTRUCTION
  522. },
  523. ArgSig(U"Target", false, DataType_ImageRgbaU8),
  524. ArgSig(U"NewWidth", true, DataType_FixedPoint),
  525. ArgSig(U"NewHeight", true, DataType_FixedPoint),
  526. ArgSig(U"Source", true, DataType_ImageRgbaU8)
  527. ),
  528. InsSig::create(U"RESIZE_BILINEAR", 1,
  529. [](VirtualMachine& machine, PlanarMemory& memory, const List<VMA>& args) {
  530. int width = INT_VALUE(1); if (width < 1) width = 1;
  531. int height = INT_VALUE(2); if (height < 1) height = 1;
  532. IMAGE_U8_REF(0) = filter_resize(image_getSubImage(IMAGE_U8_REF(3), IRect(INT_VALUE(4), INT_VALUE(5), INT_VALUE(6), INT_VALUE(7))), Sampler::Linear, width, height);
  533. NEXT_INSTRUCTION
  534. },
  535. // TODO: Prevent aliasing
  536. ArgSig(U"Target", false, DataType_ImageU8),
  537. ArgSig(U"NewWidth", true, DataType_FixedPoint),
  538. ArgSig(U"NewHeight", true, DataType_FixedPoint),
  539. ArgSig(U"Source", true, DataType_ImageU8),
  540. ArgSig(U"SourceLeft", true, DataType_FixedPoint),
  541. ArgSig(U"SourceTop", true, DataType_FixedPoint),
  542. ArgSig(U"SourceWidth", true, DataType_FixedPoint),
  543. ArgSig(U"SourceHeight", true, DataType_FixedPoint)
  544. ),
  545. InsSig::create(U"RESIZE_BILINEAR", 1,
  546. [](VirtualMachine& machine, PlanarMemory& memory, const List<VMA>& args) {
  547. int width = INT_VALUE(1); if (width < 1) width = 1;
  548. int height = INT_VALUE(2); if (height < 1) height = 1;
  549. IMAGE_RGBAU8_REF(0) = filter_resize(image_getSubImage(IMAGE_RGBAU8_REF(3), IRect(INT_VALUE(4), INT_VALUE(5), INT_VALUE(6), INT_VALUE(7))), Sampler::Linear, width, height);
  550. NEXT_INSTRUCTION
  551. },
  552. // TODO: Prevent aliasing
  553. ArgSig(U"Target", false, DataType_ImageRgbaU8),
  554. ArgSig(U"NewWidth", true, DataType_FixedPoint),
  555. ArgSig(U"NewHeight", true, DataType_FixedPoint),
  556. ArgSig(U"Source", true, DataType_ImageRgbaU8),
  557. ArgSig(U"SourceLeft", true, DataType_FixedPoint),
  558. ArgSig(U"SourceTop", true, DataType_FixedPoint),
  559. ArgSig(U"SourceWidth", true, DataType_FixedPoint),
  560. ArgSig(U"SourceHeight", true, DataType_FixedPoint)
  561. ),
  562. InsSig::create(U"GET_RED", 1,
  563. // Getting red channel of an image.
  564. [](VirtualMachine& machine, PlanarMemory& memory, const List<VMA>& args) {
  565. IMAGE_U8_REF(0) = image_get_red(IMAGE_RGBAU8_REF(1));
  566. NEXT_INSTRUCTION
  567. },
  568. ArgSig(U"Target", false, DataType_ImageU8),
  569. ArgSig(U"Source", true, DataType_ImageRgbaU8)
  570. ),
  571. InsSig::create(U"GET_RED", 1,
  572. // Getting red channel of a source region in the image.
  573. [](VirtualMachine& machine, PlanarMemory& memory, const List<VMA>& args) {
  574. IMAGE_U8_REF(0) = image_get_red(image_getSubImage(IMAGE_RGBAU8_REF(1), IRect(INT_VALUE(2), INT_VALUE(3), INT_VALUE(4), INT_VALUE(5))));
  575. NEXT_INSTRUCTION
  576. },
  577. ArgSig(U"Target", false, DataType_ImageU8),
  578. ArgSig(U"Source", true, DataType_ImageRgbaU8),
  579. ArgSig(U"SourceLeft", true, DataType_FixedPoint),
  580. ArgSig(U"SourceTop", true, DataType_FixedPoint),
  581. ArgSig(U"SourceWidth", true, DataType_FixedPoint),
  582. ArgSig(U"SourceHeight", true, DataType_FixedPoint)
  583. ),
  584. InsSig::create(U"GET_GREEN", 1,
  585. // Getting green channel of an image.
  586. [](VirtualMachine& machine, PlanarMemory& memory, const List<VMA>& args) {
  587. IMAGE_U8_REF(0) = image_get_green(IMAGE_RGBAU8_REF(1));
  588. NEXT_INSTRUCTION
  589. },
  590. ArgSig(U"Target", false, DataType_ImageU8),
  591. ArgSig(U"Source", true, DataType_ImageRgbaU8)
  592. ),
  593. InsSig::create(U"GET_GREEN", 1,
  594. // Getting green channel of a source region in the image.
  595. [](VirtualMachine& machine, PlanarMemory& memory, const List<VMA>& args) {
  596. IMAGE_U8_REF(0) = image_get_green(image_getSubImage(IMAGE_RGBAU8_REF(1), IRect(INT_VALUE(2), INT_VALUE(3), INT_VALUE(4), INT_VALUE(5))));
  597. NEXT_INSTRUCTION
  598. },
  599. ArgSig(U"Target", false, DataType_ImageU8),
  600. ArgSig(U"Source", true, DataType_ImageRgbaU8),
  601. ArgSig(U"SourceLeft", true, DataType_FixedPoint),
  602. ArgSig(U"SourceTop", true, DataType_FixedPoint),
  603. ArgSig(U"SourceWidth", true, DataType_FixedPoint),
  604. ArgSig(U"SourceHeight", true, DataType_FixedPoint)
  605. ),
  606. InsSig::create(U"GET_BLUE", 1,
  607. // Getting blue channel of an image.
  608. [](VirtualMachine& machine, PlanarMemory& memory, const List<VMA>& args) {
  609. IMAGE_U8_REF(0) = image_get_blue(IMAGE_RGBAU8_REF(1));
  610. NEXT_INSTRUCTION
  611. },
  612. ArgSig(U"Target", false, DataType_ImageU8),
  613. ArgSig(U"Source", true, DataType_ImageRgbaU8)
  614. ),
  615. InsSig::create(U"GET_BLUE", 1,
  616. // Getting blue channel of a source region in the image.
  617. [](VirtualMachine& machine, PlanarMemory& memory, const List<VMA>& args) {
  618. IMAGE_U8_REF(0) = image_get_blue(image_getSubImage(IMAGE_RGBAU8_REF(1), IRect(INT_VALUE(2), INT_VALUE(3), INT_VALUE(4), INT_VALUE(5))));
  619. NEXT_INSTRUCTION
  620. },
  621. ArgSig(U"Target", false, DataType_ImageU8),
  622. ArgSig(U"Source", true, DataType_ImageRgbaU8),
  623. ArgSig(U"SourceLeft", true, DataType_FixedPoint),
  624. ArgSig(U"SourceTop", true, DataType_FixedPoint),
  625. ArgSig(U"SourceWidth", true, DataType_FixedPoint),
  626. ArgSig(U"SourceHeight", true, DataType_FixedPoint)
  627. ),
  628. InsSig::create(U"GET_ALPHA", 1,
  629. // Getting alpha channel of an image.
  630. [](VirtualMachine& machine, PlanarMemory& memory, const List<VMA>& args) {
  631. IMAGE_U8_REF(0) = image_get_alpha(IMAGE_RGBAU8_REF(1));
  632. NEXT_INSTRUCTION
  633. },
  634. ArgSig(U"Target", false, DataType_ImageU8),
  635. ArgSig(U"Source", true, DataType_ImageRgbaU8)
  636. ),
  637. InsSig::create(U"GET_ALPHA", 1,
  638. // Getting alpha channel of a source region in the image.
  639. [](VirtualMachine& machine, PlanarMemory& memory, const List<VMA>& args) {
  640. IMAGE_U8_REF(0) = image_get_alpha(image_getSubImage(IMAGE_RGBAU8_REF(1), IRect(INT_VALUE(2), INT_VALUE(3), INT_VALUE(4), INT_VALUE(5))));
  641. NEXT_INSTRUCTION
  642. },
  643. ArgSig(U"Target", false, DataType_ImageU8),
  644. ArgSig(U"Source", true, DataType_ImageRgbaU8),
  645. ArgSig(U"SourceLeft", true, DataType_FixedPoint),
  646. ArgSig(U"SourceTop", true, DataType_FixedPoint),
  647. ArgSig(U"SourceWidth", true, DataType_FixedPoint),
  648. ArgSig(U"SourceHeight", true, DataType_FixedPoint)
  649. ),
  650. InsSig::create(U"PACK_RGBA", 1,
  651. [](VirtualMachine& machine, PlanarMemory& memory, const List<VMA>& args) {
  652. IMAGE_RGBAU8_REF(0) = image_pack(IMAGE_U8_REF(1), INT_VALUE(2), INT_VALUE(3), INT_VALUE(4));
  653. NEXT_INSTRUCTION
  654. },
  655. ArgSig(U"Target", false, DataType_ImageRgbaU8),
  656. ArgSig(U"Red", true, DataType_ImageU8),
  657. ArgSig(U"Green", true, DataType_FixedPoint),
  658. ArgSig(U"Blue", true, DataType_FixedPoint),
  659. ArgSig(U"Alpha", true, DataType_FixedPoint)
  660. ),
  661. InsSig::create(U"PACK_RGBA", 1,
  662. [](VirtualMachine& machine, PlanarMemory& memory, const List<VMA>& args) {
  663. IMAGE_RGBAU8_REF(0) = image_pack(INT_VALUE(1), IMAGE_U8_REF(2), INT_VALUE(3), INT_VALUE(4));
  664. NEXT_INSTRUCTION
  665. },
  666. ArgSig(U"Target", false, DataType_ImageRgbaU8),
  667. ArgSig(U"Red", true, DataType_FixedPoint),
  668. ArgSig(U"Green", true, DataType_ImageU8),
  669. ArgSig(U"Blue", true, DataType_FixedPoint),
  670. ArgSig(U"Alpha", true, DataType_FixedPoint)
  671. ),
  672. InsSig::create(U"PACK_RGBA", 1,
  673. [](VirtualMachine& machine, PlanarMemory& memory, const List<VMA>& args) {
  674. IMAGE_RGBAU8_REF(0) = image_pack(INT_VALUE(1), INT_VALUE(2), IMAGE_U8_REF(3), INT_VALUE(4));
  675. NEXT_INSTRUCTION
  676. },
  677. ArgSig(U"Target", false, DataType_ImageRgbaU8),
  678. ArgSig(U"Red", true, DataType_FixedPoint),
  679. ArgSig(U"Green", true, DataType_FixedPoint),
  680. ArgSig(U"Blue", true, DataType_ImageU8),
  681. ArgSig(U"Alpha", true, DataType_FixedPoint)
  682. ),
  683. InsSig::create(U"PACK_RGBA", 1,
  684. [](VirtualMachine& machine, PlanarMemory& memory, const List<VMA>& args) {
  685. IMAGE_RGBAU8_REF(0) = image_pack(INT_VALUE(1), INT_VALUE(2), INT_VALUE(3), IMAGE_U8_REF(4));
  686. NEXT_INSTRUCTION
  687. },
  688. ArgSig(U"Target", false, DataType_ImageRgbaU8),
  689. ArgSig(U"Red", true, DataType_FixedPoint),
  690. ArgSig(U"Green", true, DataType_FixedPoint),
  691. ArgSig(U"Blue", true, DataType_FixedPoint),
  692. ArgSig(U"Alpha", true, DataType_ImageU8)
  693. ),
  694. InsSig::create(U"PACK_RGBA", 1,
  695. [](VirtualMachine& machine, PlanarMemory& memory, const List<VMA>& args) {
  696. IMAGE_RGBAU8_REF(0) = image_pack(IMAGE_U8_REF(1), IMAGE_U8_REF(2), INT_VALUE(3), INT_VALUE(4));
  697. NEXT_INSTRUCTION
  698. },
  699. ArgSig(U"Target", false, DataType_ImageRgbaU8),
  700. ArgSig(U"Red", true, DataType_ImageU8),
  701. ArgSig(U"Green", true, DataType_ImageU8),
  702. ArgSig(U"Blue", true, DataType_FixedPoint),
  703. ArgSig(U"Alpha", true, DataType_FixedPoint)
  704. ),
  705. InsSig::create(U"PACK_RGBA", 1,
  706. [](VirtualMachine& machine, PlanarMemory& memory, const List<VMA>& args) {
  707. IMAGE_RGBAU8_REF(0) = image_pack(IMAGE_U8_REF(1), INT_VALUE(2), IMAGE_U8_REF(3), INT_VALUE(4));
  708. NEXT_INSTRUCTION
  709. },
  710. ArgSig(U"Target", false, DataType_ImageRgbaU8),
  711. ArgSig(U"Red", true, DataType_ImageU8),
  712. ArgSig(U"Green", true, DataType_FixedPoint),
  713. ArgSig(U"Blue", true, DataType_ImageU8),
  714. ArgSig(U"Alpha", true, DataType_FixedPoint)
  715. ),
  716. InsSig::create(U"PACK_RGBA", 1,
  717. [](VirtualMachine& machine, PlanarMemory& memory, const List<VMA>& args) {
  718. IMAGE_RGBAU8_REF(0) = image_pack(IMAGE_U8_REF(1), INT_VALUE(2), INT_VALUE(3), IMAGE_U8_REF(4));
  719. NEXT_INSTRUCTION
  720. },
  721. ArgSig(U"Target", false, DataType_ImageRgbaU8),
  722. ArgSig(U"Red", true, DataType_ImageU8),
  723. ArgSig(U"Green", true, DataType_FixedPoint),
  724. ArgSig(U"Blue", true, DataType_FixedPoint),
  725. ArgSig(U"Alpha", true, DataType_ImageU8)
  726. ),
  727. InsSig::create(U"PACK_RGBA", 1,
  728. [](VirtualMachine& machine, PlanarMemory& memory, const List<VMA>& args) {
  729. IMAGE_RGBAU8_REF(0) = image_pack(INT_VALUE(1), IMAGE_U8_REF(2), IMAGE_U8_REF(3), INT_VALUE(4));
  730. NEXT_INSTRUCTION
  731. },
  732. ArgSig(U"Target", false, DataType_ImageRgbaU8),
  733. ArgSig(U"Red", true, DataType_FixedPoint),
  734. ArgSig(U"Green", true, DataType_ImageU8),
  735. ArgSig(U"Blue", true, DataType_ImageU8),
  736. ArgSig(U"Alpha", true, DataType_FixedPoint)
  737. ),
  738. InsSig::create(U"PACK_RGBA", 1,
  739. [](VirtualMachine& machine, PlanarMemory& memory, const List<VMA>& args) {
  740. IMAGE_RGBAU8_REF(0) = image_pack(INT_VALUE(1), IMAGE_U8_REF(2), INT_VALUE(3), IMAGE_U8_REF(4));
  741. NEXT_INSTRUCTION
  742. },
  743. ArgSig(U"Target", false, DataType_ImageRgbaU8),
  744. ArgSig(U"Red", true, DataType_FixedPoint),
  745. ArgSig(U"Green", true, DataType_ImageU8),
  746. ArgSig(U"Blue", true, DataType_FixedPoint),
  747. ArgSig(U"Alpha", true, DataType_ImageU8)
  748. ),
  749. InsSig::create(U"PACK_RGBA", 1,
  750. [](VirtualMachine& machine, PlanarMemory& memory, const List<VMA>& args) {
  751. IMAGE_RGBAU8_REF(0) = image_pack(INT_VALUE(1), INT_VALUE(2), IMAGE_U8_REF(3), IMAGE_U8_REF(4));
  752. NEXT_INSTRUCTION
  753. },
  754. ArgSig(U"Target", false, DataType_ImageRgbaU8),
  755. ArgSig(U"Red", true, DataType_FixedPoint),
  756. ArgSig(U"Green", true, DataType_FixedPoint),
  757. ArgSig(U"Blue", true, DataType_ImageU8),
  758. ArgSig(U"Alpha", true, DataType_ImageU8)
  759. ),
  760. InsSig::create(U"PACK_RGBA", 1,
  761. [](VirtualMachine& machine, PlanarMemory& memory, const List<VMA>& args) {
  762. IMAGE_RGBAU8_REF(0) = image_pack(INT_VALUE(1), IMAGE_U8_REF(2), IMAGE_U8_REF(3), IMAGE_U8_REF(4));
  763. NEXT_INSTRUCTION
  764. },
  765. ArgSig(U"Target", false, DataType_ImageRgbaU8),
  766. ArgSig(U"Red", true, DataType_FixedPoint),
  767. ArgSig(U"Green", true, DataType_ImageU8),
  768. ArgSig(U"Blue", true, DataType_ImageU8),
  769. ArgSig(U"Alpha", true, DataType_ImageU8)
  770. ),
  771. InsSig::create(U"PACK_RGBA", 1,
  772. [](VirtualMachine& machine, PlanarMemory& memory, const List<VMA>& args) {
  773. IMAGE_RGBAU8_REF(0) = image_pack(IMAGE_U8_REF(1), INT_VALUE(2), IMAGE_U8_REF(3), IMAGE_U8_REF(4));
  774. NEXT_INSTRUCTION
  775. },
  776. ArgSig(U"Target", false, DataType_ImageRgbaU8),
  777. ArgSig(U"Red", true, DataType_ImageU8),
  778. ArgSig(U"Green", true, DataType_FixedPoint),
  779. ArgSig(U"Blue", true, DataType_ImageU8),
  780. ArgSig(U"Alpha", true, DataType_ImageU8)
  781. ),
  782. InsSig::create(U"PACK_RGBA", 1,
  783. [](VirtualMachine& machine, PlanarMemory& memory, const List<VMA>& args) {
  784. IMAGE_RGBAU8_REF(0) = image_pack(IMAGE_U8_REF(1), IMAGE_U8_REF(2), INT_VALUE(3), IMAGE_U8_REF(4));
  785. NEXT_INSTRUCTION
  786. },
  787. ArgSig(U"Target", false, DataType_ImageRgbaU8),
  788. ArgSig(U"Red", true, DataType_ImageU8),
  789. ArgSig(U"Green", true, DataType_ImageU8),
  790. ArgSig(U"Blue", true, DataType_FixedPoint),
  791. ArgSig(U"Alpha", true, DataType_ImageU8)
  792. ),
  793. InsSig::create(U"PACK_RGBA", 1,
  794. [](VirtualMachine& machine, PlanarMemory& memory, const List<VMA>& args) {
  795. IMAGE_RGBAU8_REF(0) = image_pack(IMAGE_U8_REF(1), IMAGE_U8_REF(2), IMAGE_U8_REF(3), INT_VALUE(4));
  796. NEXT_INSTRUCTION
  797. },
  798. ArgSig(U"Target", false, DataType_ImageRgbaU8),
  799. ArgSig(U"Red", true, DataType_ImageU8),
  800. ArgSig(U"Green", true, DataType_ImageU8),
  801. ArgSig(U"Blue", true, DataType_ImageU8),
  802. ArgSig(U"Alpha", true, DataType_FixedPoint)
  803. ),
  804. InsSig::create(U"PACK_RGBA", 1,
  805. [](VirtualMachine& machine, PlanarMemory& memory, const List<VMA>& args) {
  806. IMAGE_RGBAU8_REF(0) = image_pack(IMAGE_U8_REF(1), IMAGE_U8_REF(2), IMAGE_U8_REF(3), IMAGE_U8_REF(4));
  807. NEXT_INSTRUCTION
  808. },
  809. ArgSig(U"Target", false, DataType_ImageRgbaU8),
  810. ArgSig(U"Red", true, DataType_ImageU8),
  811. ArgSig(U"Green", true, DataType_ImageU8),
  812. ArgSig(U"Blue", true, DataType_ImageU8),
  813. ArgSig(U"Alpha", true, DataType_ImageU8)
  814. ),
  815. InsSig::create(U"LINE", 1,
  816. [](VirtualMachine& machine, PlanarMemory& memory, const List<VMA>& args) {
  817. draw_line(IMAGE_U8_REF(0), INT_VALUE(1), INT_VALUE(2), INT_VALUE(3), INT_VALUE(4), INT_VALUE(5));
  818. NEXT_INSTRUCTION
  819. },
  820. ArgSig(U"Target", false, DataType_ImageU8),
  821. ArgSig(U"X1", true, DataType_FixedPoint),
  822. ArgSig(U"Y1", true, DataType_FixedPoint),
  823. ArgSig(U"X2", true, DataType_FixedPoint),
  824. ArgSig(U"Y2", true, DataType_FixedPoint),
  825. ArgSig(U"Luma", true, DataType_FixedPoint)
  826. ),
  827. InsSig::create(U"LINE", 1,
  828. [](VirtualMachine& machine, PlanarMemory& memory, const List<VMA>& args) {
  829. draw_line(
  830. IMAGE_RGBAU8_REF(0),
  831. INT_VALUE(1), INT_VALUE(2), INT_VALUE(3), INT_VALUE(4),
  832. ColorRgbaI32(INT_VALUE(5), INT_VALUE(6), INT_VALUE(7), INT_VALUE(8))
  833. );
  834. NEXT_INSTRUCTION
  835. },
  836. ArgSig(U"Target", false, DataType_ImageRgbaU8),
  837. ArgSig(U"X1", true, DataType_FixedPoint),
  838. ArgSig(U"Y1", true, DataType_FixedPoint),
  839. ArgSig(U"X2", true, DataType_FixedPoint),
  840. ArgSig(U"Y2", true, DataType_FixedPoint),
  841. ArgSig(U"Red", true, DataType_FixedPoint),
  842. ArgSig(U"Green", true, DataType_FixedPoint),
  843. ArgSig(U"Blue", true, DataType_FixedPoint),
  844. ArgSig(U"Alpha", true, DataType_FixedPoint)
  845. ),
  846. InsSig::create(U"FADE_LINEAR", 1,
  847. [](VirtualMachine& machine, PlanarMemory& memory, const List<VMA>& args) {
  848. media_fade_linear(IMAGE_U8_REF(0), SCALAR_VALUE(1), SCALAR_VALUE(2), SCALAR_VALUE(3), SCALAR_VALUE(4), SCALAR_VALUE(5), SCALAR_VALUE(6));
  849. NEXT_INSTRUCTION
  850. },
  851. ArgSig(U"Target", false, DataType_ImageU8),
  852. ArgSig(U"X1", true, DataType_FixedPoint),
  853. ArgSig(U"Y1", true, DataType_FixedPoint),
  854. ArgSig(U"Luma1", true, DataType_FixedPoint), // At x1, y1
  855. ArgSig(U"X2", true, DataType_FixedPoint),
  856. ArgSig(U"Y2", true, DataType_FixedPoint),
  857. ArgSig(U"Luma2", true, DataType_FixedPoint) // At x2, y2
  858. ),
  859. InsSig::create(U"FADE_REGION_LINEAR", 1,
  860. [](VirtualMachine& machine, PlanarMemory& memory, const List<VMA>& args) {
  861. media_fade_region_linear(IMAGE_U8_REF(0), IRect(INT_VALUE(1), INT_VALUE(2), INT_VALUE(3), INT_VALUE(4)), SCALAR_VALUE(5), SCALAR_VALUE(6), SCALAR_VALUE(7), SCALAR_VALUE(8), SCALAR_VALUE(9), SCALAR_VALUE(10));
  862. NEXT_INSTRUCTION
  863. },
  864. ArgSig(U"Target", false, DataType_ImageU8),
  865. ArgSig(U"Left", true, DataType_FixedPoint),
  866. ArgSig(U"Top", true, DataType_FixedPoint),
  867. ArgSig(U"Width", true, DataType_FixedPoint),
  868. ArgSig(U"Height", true, DataType_FixedPoint),
  869. ArgSig(U"X1", true, DataType_FixedPoint), // Relative to Left
  870. ArgSig(U"Y1", true, DataType_FixedPoint), // Relative to Top
  871. ArgSig(U"Luma1", true, DataType_FixedPoint), // At Left + X1, Top + Y1
  872. ArgSig(U"X2", true, DataType_FixedPoint), // Relative to Left
  873. ArgSig(U"Y2", true, DataType_FixedPoint), // Relative to Top
  874. ArgSig(U"Luma2", true, DataType_FixedPoint) // At Left + X2, Top + Y2
  875. ),
  876. //void media_fade_radial(ImageU8& targetImage, FixedPoint centerX, FixedPoint centerY, FixedPoint innerRadius, FixedPoint innerLuma, FixedPoint outerRadius, FixedPoint outerLuma);
  877. InsSig::create(U"FADE_RADIAL", 1,
  878. [](VirtualMachine& machine, PlanarMemory& memory, const List<VMA>& args) {
  879. media_fade_radial(IMAGE_U8_REF(0), SCALAR_VALUE(1), SCALAR_VALUE(2), SCALAR_VALUE(3), SCALAR_VALUE(4), SCALAR_VALUE(5), SCALAR_VALUE(6));
  880. NEXT_INSTRUCTION
  881. },
  882. ArgSig(U"Target", false, DataType_ImageU8),
  883. ArgSig(U"CenterX", true, DataType_FixedPoint),
  884. ArgSig(U"CenterY", true, DataType_FixedPoint),
  885. ArgSig(U"InnerRadius", true, DataType_FixedPoint),
  886. ArgSig(U"InnerLuma", true, DataType_FixedPoint),
  887. ArgSig(U"OuterRadius", true, DataType_FixedPoint),
  888. ArgSig(U"OuterLuma", true, DataType_FixedPoint)
  889. ),
  890. // void media_fade_region_radial(ImageU8& targetImage, const IRect& viewport, FixedPoint centerX, FixedPoint centerY, FixedPoint innerRadius, FixedPoint innerLuma, FixedPoint outerRadius, FixedPoint outerLuma);
  891. InsSig::create(U"FADE_REGION_RADIAL", 1,
  892. [](VirtualMachine& machine, PlanarMemory& memory, const List<VMA>& args) {
  893. media_fade_region_radial(IMAGE_U8_REF(0), IRect(INT_VALUE(1), INT_VALUE(2), INT_VALUE(3), INT_VALUE(4)), SCALAR_VALUE(5), SCALAR_VALUE(6), SCALAR_VALUE(7), SCALAR_VALUE(8), SCALAR_VALUE(9), SCALAR_VALUE(10));
  894. NEXT_INSTRUCTION
  895. },
  896. ArgSig(U"Target", false, DataType_ImageU8),
  897. ArgSig(U"Left", true, DataType_FixedPoint),
  898. ArgSig(U"Top", true, DataType_FixedPoint),
  899. ArgSig(U"Width", true, DataType_FixedPoint),
  900. ArgSig(U"Height", true, DataType_FixedPoint),
  901. ArgSig(U"CenterX", true, DataType_FixedPoint),
  902. ArgSig(U"CenterY", true, DataType_FixedPoint),
  903. ArgSig(U"InnerRadius", true, DataType_FixedPoint),
  904. ArgSig(U"InnerLuma", true, DataType_FixedPoint),
  905. ArgSig(U"OuterRadius", true, DataType_FixedPoint),
  906. ArgSig(U"OuterLuma", true, DataType_FixedPoint)
  907. ),
  908. InsSig::create(U"WRITE_PIXEL", 1,
  909. [](VirtualMachine& machine, PlanarMemory& memory, const List<VMA>& args) {
  910. image_writePixel(IMAGE_U8_REF(0), INT_VALUE(1), INT_VALUE(2), INT_VALUE(3));
  911. NEXT_INSTRUCTION
  912. },
  913. ArgSig(U"Target", false, DataType_ImageU8),
  914. ArgSig(U"X", true, DataType_FixedPoint),
  915. ArgSig(U"Y", true, DataType_FixedPoint),
  916. ArgSig(U"Luma", true, DataType_FixedPoint)
  917. ),
  918. InsSig::create(U"WRITE_PIXEL", 1,
  919. [](VirtualMachine& machine, PlanarMemory& memory, const List<VMA>& args) {
  920. image_writePixel(
  921. IMAGE_RGBAU8_REF(0),
  922. INT_VALUE(1), INT_VALUE(2),
  923. ColorRgbaI32(INT_VALUE(3), INT_VALUE(4), INT_VALUE(5), INT_VALUE(6))
  924. );
  925. NEXT_INSTRUCTION
  926. },
  927. ArgSig(U"Target", false, DataType_ImageRgbaU8),
  928. ArgSig(U"X", true, DataType_FixedPoint),
  929. ArgSig(U"Y", true, DataType_FixedPoint),
  930. ArgSig(U"Red", true, DataType_FixedPoint),
  931. ArgSig(U"Green", true, DataType_FixedPoint),
  932. ArgSig(U"Blue", true, DataType_FixedPoint),
  933. ArgSig(U"Alpha", true, DataType_FixedPoint)
  934. ),
  935. InsSig::create(U"READ_PIXEL_BORDER", 1,
  936. [](VirtualMachine& machine, PlanarMemory& memory, const List<VMA>& args) {
  937. SCALAR_REF(0) = FixedPoint::fromWhole(image_readPixel_border(IMAGE_U8_REF(1), INT_VALUE(2), INT_VALUE(3), INT_VALUE(4)));
  938. NEXT_INSTRUCTION
  939. },
  940. ArgSig(U"LumaOutput", false, DataType_FixedPoint),
  941. ArgSig(U"Source", true, DataType_ImageU8),
  942. ArgSig(U"X", true, DataType_FixedPoint),
  943. ArgSig(U"Y", true, DataType_FixedPoint),
  944. ArgSig(U"LumaBorder", true, DataType_FixedPoint)
  945. ),
  946. InsSig::create(U"READ_PIXEL_BORDER", 4,
  947. [](VirtualMachine& machine, PlanarMemory& memory, const List<VMA>& args) {
  948. ColorRgbaI32 result = image_readPixel_border(
  949. IMAGE_RGBAU8_REF(4),
  950. INT_VALUE(5), INT_VALUE(6),
  951. ColorRgbaI32(INT_VALUE(7), INT_VALUE(8), INT_VALUE(9), INT_VALUE(10))
  952. );
  953. SCALAR_REF(0) = FixedPoint::fromWhole(result.red);
  954. SCALAR_REF(1) = FixedPoint::fromWhole(result.green);
  955. SCALAR_REF(2) = FixedPoint::fromWhole(result.blue);
  956. SCALAR_REF(3) = FixedPoint::fromWhole(result.alpha);
  957. NEXT_INSTRUCTION
  958. },
  959. ArgSig(U"RedOutput", false, DataType_FixedPoint),
  960. ArgSig(U"GreenOutput", false, DataType_FixedPoint),
  961. ArgSig(U"BlueOutput", false, DataType_FixedPoint),
  962. ArgSig(U"AlphaOutput", false, DataType_FixedPoint),
  963. ArgSig(U"Source", true, DataType_ImageRgbaU8),
  964. ArgSig(U"X", true, DataType_FixedPoint),
  965. ArgSig(U"Y", true, DataType_FixedPoint),
  966. ArgSig(U"RedBorder", true, DataType_FixedPoint),
  967. ArgSig(U"GreenBorder", true, DataType_FixedPoint),
  968. ArgSig(U"BlueBorder", true, DataType_FixedPoint),
  969. ArgSig(U"AlphaBorder", true, DataType_FixedPoint)
  970. ),
  971. InsSig::create(U"READ_PIXEL_CLAMP", 1,
  972. [](VirtualMachine& machine, PlanarMemory& memory, const List<VMA>& args) {
  973. SCALAR_REF(0) = FixedPoint::fromWhole(image_readPixel_clamp(IMAGE_U8_REF(1), INT_VALUE(2), INT_VALUE(3)));
  974. NEXT_INSTRUCTION
  975. },
  976. ArgSig(U"LumaOutput", false, DataType_FixedPoint),
  977. ArgSig(U"Source", true, DataType_ImageU8),
  978. ArgSig(U"X", true, DataType_FixedPoint),
  979. ArgSig(U"Y", true, DataType_FixedPoint)
  980. ),
  981. InsSig::create(U"READ_PIXEL_CLAMP", 4,
  982. [](VirtualMachine& machine, PlanarMemory& memory, const List<VMA>& args) {
  983. ColorRgbaI32 result = image_readPixel_clamp(
  984. IMAGE_RGBAU8_REF(4),
  985. INT_VALUE(5), INT_VALUE(6)
  986. );
  987. SCALAR_REF(0) = FixedPoint::fromWhole(result.red);
  988. SCALAR_REF(1) = FixedPoint::fromWhole(result.green);
  989. SCALAR_REF(2) = FixedPoint::fromWhole(result.blue);
  990. SCALAR_REF(3) = FixedPoint::fromWhole(result.alpha);
  991. NEXT_INSTRUCTION
  992. },
  993. ArgSig(U"RedOutput", false, DataType_FixedPoint),
  994. ArgSig(U"GreenOutput", false, DataType_FixedPoint),
  995. ArgSig(U"BlueOutput", false, DataType_FixedPoint),
  996. ArgSig(U"AlphaOutput", false, DataType_FixedPoint),
  997. ArgSig(U"Source", true, DataType_ImageRgbaU8),
  998. ArgSig(U"X", true, DataType_FixedPoint),
  999. ArgSig(U"Y", true, DataType_FixedPoint)
  1000. ),
  1001. InsSig::create(U"READ_PIXEL_TILE", 1,
  1002. [](VirtualMachine& machine, PlanarMemory& memory, const List<VMA>& args) {
  1003. SCALAR_REF(0) = FixedPoint::fromWhole(image_readPixel_tile(IMAGE_U8_REF(1), INT_VALUE(2), INT_VALUE(3)));
  1004. NEXT_INSTRUCTION
  1005. },
  1006. ArgSig(U"LumaOutput", false, DataType_FixedPoint),
  1007. ArgSig(U"Source", true, DataType_ImageU8),
  1008. ArgSig(U"X", true, DataType_FixedPoint),
  1009. ArgSig(U"Y", true, DataType_FixedPoint)
  1010. ),
  1011. InsSig::create(U"READ_PIXEL_TILE", 4,
  1012. [](VirtualMachine& machine, PlanarMemory& memory, const List<VMA>& args) {
  1013. ColorRgbaI32 result = image_readPixel_tile(
  1014. IMAGE_RGBAU8_REF(4),
  1015. INT_VALUE(5), INT_VALUE(6)
  1016. );
  1017. SCALAR_REF(0) = FixedPoint::fromWhole(result.red);
  1018. SCALAR_REF(1) = FixedPoint::fromWhole(result.green);
  1019. SCALAR_REF(2) = FixedPoint::fromWhole(result.blue);
  1020. SCALAR_REF(3) = FixedPoint::fromWhole(result.alpha);
  1021. NEXT_INSTRUCTION
  1022. },
  1023. ArgSig(U"RedOutput", false, DataType_FixedPoint),
  1024. ArgSig(U"GreenOutput", false, DataType_FixedPoint),
  1025. ArgSig(U"BlueOutput", false, DataType_FixedPoint),
  1026. ArgSig(U"AlphaOutput", false, DataType_FixedPoint),
  1027. ArgSig(U"Source", true, DataType_ImageRgbaU8),
  1028. ArgSig(U"X", true, DataType_FixedPoint),
  1029. ArgSig(U"Y", true, DataType_FixedPoint)
  1030. )
  1031. };
  1032. // API implementation
  1033. static void checkMachine(const MediaMachine& machine) {
  1034. if (machine.get() == nullptr) {
  1035. throwError("The given media machine does not exist!");
  1036. }
  1037. }
  1038. static void checkMethodIndex(const MediaMachine& machine, int methodIndex) {
  1039. checkMachine(machine);
  1040. if (methodIndex < 0 || methodIndex >= machine->methods.length()) {
  1041. throwError("Invalid method index ", methodIndex, " of 0..", (machine->methods.length() - 1), "!");
  1042. }
  1043. }
  1044. MediaMachine machine_create(const ReadableString& code) {
  1045. std::shared_ptr<PlanarMemory> memory = std::make_shared<MediaMemory>();
  1046. static const int mediaMachineInstructionCount = sizeof(mediaMachineInstructions) / sizeof(InsSig);
  1047. static const int mediaMachineTypeCount = sizeof(mediaMachineTypes) / sizeof(VMTypeDef);
  1048. return MediaMachine(std::make_shared<VirtualMachine>(code, memory, mediaMachineInstructions, mediaMachineInstructionCount, mediaMachineTypes, mediaMachineTypeCount));
  1049. }
  1050. void machine_executeMethod(MediaMachine& machine, int methodIndex) {
  1051. checkMethodIndex(machine, methodIndex);
  1052. machine->executeMethod(methodIndex);
  1053. }
  1054. template <typename T>
  1055. static void setInputByIndex(MemoryPlane<T>& stack, int framePointer, Method& method, DataType givenType, int inputIndex, const T& value) {
  1056. if (inputIndex < 0 || inputIndex >= method.inputCount) {
  1057. throwError("Invalid input index ", inputIndex, " of 0..", (method.inputCount - 1), ".");
  1058. }
  1059. Variable* variable = &method.locals[inputIndex];
  1060. DataType expected = variable->typeDescription->dataType;
  1061. if (givenType != expected) {
  1062. throwError("Cannot assign ", getMediaTypeName(givenType), " to ", variable->name, " of ", getMediaTypeName(expected), ".");
  1063. }
  1064. stack.accessByStackIndex(framePointer + variable->typeLocalIndex) = value;
  1065. }
  1066. template <typename T>
  1067. static T& accessOutputByIndex(MemoryPlane<T>& stack, int framePointer, Method& method, DataType wantedType, int outputIndex) {
  1068. if (outputIndex < 0 || outputIndex >= method.outputCount) {
  1069. throwError("Invalid output index ", outputIndex, " of 0..", (method.outputCount - 1), ".");
  1070. }
  1071. Variable* variable = &method.locals[method.inputCount + outputIndex];
  1072. DataType foundType = variable->typeDescription->dataType;
  1073. if (wantedType != foundType) {
  1074. throwError("Cannot get ", variable->name, " of ", getMediaTypeName(wantedType), " as ", getMediaTypeName(wantedType), ".");
  1075. }
  1076. return stack.accessByStackIndex(framePointer + variable->typeLocalIndex);
  1077. }
  1078. // Set input by argument index
  1079. // Indexed arguments are confirmed to be inputs during compilation of the script
  1080. void machine_setInputByIndex(MediaMachine& machine, int methodIndex, int inputIndex, int32_t input) {
  1081. #ifdef VIRTUAL_MACHINE_DEBUG_PRINT
  1082. printText("Input ", inputIndex, " of ", machine->methods[methodIndex].inputCount, " (", machine->methods[methodIndex].locals[inputIndex].name, ") to ", machine->methods[methodIndex].name, " = ", input, "\n");
  1083. #endif
  1084. checkMethodIndex(machine, methodIndex);
  1085. setInputByIndex(((MediaMemory*)machine->memory.get())->FixedPointMemory, machine->memory->current.framePointer[DataType_FixedPoint], machine->methods[methodIndex], DataType_FixedPoint, inputIndex, FixedPoint::fromWhole(input));
  1086. }
  1087. void machine_setInputByIndex(MediaMachine& machine, int methodIndex, int inputIndex, const FixedPoint& input) {
  1088. #ifdef VIRTUAL_MACHINE_DEBUG_PRINT
  1089. printText("Input ", inputIndex, " of ", machine->methods[methodIndex].inputCount, " (", machine->methods[methodIndex].locals[inputIndex].name, ") to ", machine->methods[methodIndex].name, " = ", input, "\n");
  1090. #endif
  1091. checkMethodIndex(machine, methodIndex);
  1092. setInputByIndex(((MediaMemory*)machine->memory.get())->FixedPointMemory, machine->memory->current.framePointer[DataType_FixedPoint], machine->methods[methodIndex], DataType_FixedPoint, inputIndex, input);
  1093. }
  1094. void machine_setInputByIndex(MediaMachine& machine, int methodIndex, int inputIndex, const AlignedImageU8& input) {
  1095. #ifdef VIRTUAL_MACHINE_DEBUG_PRINT
  1096. printText("Input ", inputIndex, " of ", machine->methods[methodIndex].inputCount, " (", machine->methods[methodIndex].locals[inputIndex].name, ") to ", machine->methods[methodIndex].name, " = monochrome image of ", image_getWidth(input), "x", image_getHeight(input), " pixels\n");
  1097. #endif
  1098. checkMethodIndex(machine, methodIndex);
  1099. setInputByIndex(((MediaMemory*)machine->memory.get())->AlignedImageU8Memory, machine->memory->current.framePointer[DataType_ImageU8], machine->methods[methodIndex], DataType_ImageU8, inputIndex, input);
  1100. }
  1101. void machine_setInputByIndex(MediaMachine& machine, int methodIndex, int inputIndex, const OrderedImageRgbaU8& input) {
  1102. #ifdef VIRTUAL_MACHINE_DEBUG_PRINT
  1103. printText("Input ", inputIndex, " of ", machine->methods[methodIndex].inputCount, " (", machine->methods[methodIndex].locals[inputIndex].name, ") to ", machine->methods[methodIndex].name, " = rgba image of ", image_getWidth(input), "x", image_getHeight(input), " pixels\n");
  1104. #endif
  1105. checkMethodIndex(machine, methodIndex);
  1106. setInputByIndex(((MediaMemory*)machine->memory.get())->OrderedImageRgbaU8Memory, machine->memory->current.framePointer[DataType_ImageRgbaU8], machine->methods[methodIndex], DataType_ImageRgbaU8, inputIndex, input);
  1107. }
  1108. // Get output by index
  1109. FixedPoint machine_getFixedPointOutputByIndex(const MediaMachine& machine, int methodIndex, int outputIndex) {
  1110. checkMethodIndex(machine, methodIndex);
  1111. return accessOutputByIndex<FixedPoint>(((MediaMemory*)machine->memory.get())->FixedPointMemory, machine->memory->current.framePointer[DataType_FixedPoint], machine->methods[methodIndex], DataType_FixedPoint, outputIndex);
  1112. }
  1113. AlignedImageU8 machine_getImageU8OutputByIndex(const MediaMachine& machine, int methodIndex, int outputIndex) {
  1114. checkMethodIndex(machine, methodIndex);
  1115. return accessOutputByIndex<AlignedImageU8>(((MediaMemory*)machine->memory.get())->AlignedImageU8Memory, machine->memory->current.framePointer[DataType_ImageU8], machine->methods[methodIndex], DataType_ImageU8, outputIndex);
  1116. }
  1117. OrderedImageRgbaU8 machine_getImageRgbaU8OutputByIndex(const MediaMachine& machine, int methodIndex, int outputIndex) {
  1118. checkMethodIndex(machine, methodIndex);
  1119. return accessOutputByIndex<OrderedImageRgbaU8>(((MediaMemory*)machine->memory.get())->OrderedImageRgbaU8Memory, machine->memory->current.framePointer[DataType_ImageRgbaU8], machine->methods[methodIndex], DataType_ImageRgbaU8, outputIndex);
  1120. }
  1121. bool machine_exists(const MediaMachine& machine) {
  1122. return machine.get() != nullptr;
  1123. }
  1124. int machine_findMethod(const MediaMachine& machine, const ReadableString& methodName) {
  1125. if (!machine_exists(machine)) {
  1126. throwError(U"Can not look for ", methodName, U" in a media machine that does not exist!\n");
  1127. return -1;
  1128. } else {
  1129. return machine->findMethod(methodName);
  1130. }
  1131. }
  1132. MediaMethod machine_getMethod(MediaMachine& machine, const ReadableString& methodName, int contextIndex, bool mustExist) {
  1133. int methodIndex = machine_findMethod(machine, methodName);
  1134. if (mustExist && methodIndex == -1) {
  1135. throwError(U"The method name ", methodName, U" could not be found in the media machine!\n");
  1136. }
  1137. return MediaMethod(machine, methodIndex, contextIndex);
  1138. }
  1139. String machine_getMethodName(const MediaMachine& machine, int methodIndex) {
  1140. checkMethodIndex(machine, methodIndex);
  1141. return machine->methods[methodIndex].name;
  1142. }
  1143. int machine_getMethodCount(const MediaMachine& machine) {
  1144. checkMachine(machine);
  1145. return machine->methods.length();
  1146. }
  1147. int machine_getInputCount(const MediaMachine& machine, int methodIndex) {
  1148. checkMethodIndex(machine, methodIndex);
  1149. return machine->methods[methodIndex].inputCount;
  1150. }
  1151. int machine_getOutputCount(const MediaMachine& machine, int methodIndex) {
  1152. checkMethodIndex(machine, methodIndex);
  1153. return machine->methods[methodIndex].outputCount;
  1154. }
  1155. String machine_getInputName(const MediaMachine& machine, int methodIndex, int inputIndex) {
  1156. checkMethodIndex(machine, methodIndex);
  1157. Method *method = &(machine->methods[methodIndex]);
  1158. if (inputIndex < 0 || inputIndex >= method->inputCount) {
  1159. throwError(U"Input index ", inputIndex, U" is out of bound 0..", method->inputCount - 1, U" for method ", machine_getMethodName(machine, methodIndex), U"!\n");
  1160. }
  1161. return method->locals[inputIndex].name;
  1162. }
  1163. String machine_getOutputName(const MediaMachine& machine, int methodIndex, int outputIndex) {
  1164. checkMethodIndex(machine, methodIndex);
  1165. Method *method = &(machine->methods[methodIndex]);
  1166. if (outputIndex < 0 || outputIndex >= method->outputCount) {
  1167. throwError(U"Input index ", outputIndex, U" is out of bound 0..", method->outputCount - 1, U" for method ", machine_getMethodName(machine, methodIndex), U"!\n");
  1168. }
  1169. return method->locals[method->inputCount + outputIndex].name;
  1170. }
  1171. MediaResult MediaMethod::callUsingKeywords(std::function<void(MediaMachine &machine, int methodIndex, int inputIndex, const ReadableString &argumentName)> setInputAction) {
  1172. if (this->methodIndex < 0 || this->methodIndex >= this->machine->methods.length()) {
  1173. throwError(U"Method index ", this->methodIndex, U" is out of bound 0..", this->machine->methods.length() - 1, U"\n");
  1174. }
  1175. Method *method = &(this->machine->methods[this->methodIndex]);
  1176. int inputCount = method->inputCount;
  1177. // TODO: Make sure that input arguments are assigned default arguments before assigning inputs as keywords.
  1178. for (int i = 0; i < inputCount; i++) {
  1179. setInputAction(this->machine, this->methodIndex, i, method->locals[i].name);
  1180. }
  1181. machine_executeMethod(this->machine, this->methodIndex);
  1182. return MediaResult(this->machine, this->methodIndex);
  1183. }
  1184. }