mediaMachineAPI.cpp 54 KB

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