libobs+Extensions.swift 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486
  1. /******************************************************************************
  2. Copyright (C) 2024 by Patrick Heyer <[email protected]>
  3. This program is free software: you can redistribute it and/or modify
  4. it under the terms of the GNU General Public License as published by
  5. the Free Software Foundation, either version 2 of the License, or
  6. (at your option) any later version.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. GNU General Public License for more details.
  11. You should have received a copy of the GNU General Public License
  12. along with this program. If not, see <http://www.gnu.org/licenses/>.
  13. ******************************************************************************/
  14. import Foundation
  15. import Metal
  16. import simd
  17. public enum OBSLogLevel: Int32 {
  18. case error = 100
  19. case warning = 200
  20. case info = 300
  21. case debug = 400
  22. }
  23. extension strref {
  24. mutating func getString() -> String {
  25. let buffer = UnsafeRawBufferPointer(start: self.array, count: self.len)
  26. let string = String(decoding: buffer, as: UTF8.self)
  27. return string
  28. }
  29. mutating func isEqualTo(_ comparison: String) -> Bool {
  30. return strref_cmp(&self, comparison.cString(using: .utf8)) == 0
  31. }
  32. mutating func isEqualToCString(_ comparison: UnsafeMutablePointer<CChar>?) -> Bool {
  33. if let comparison {
  34. let result = withUnsafeMutablePointer(to: &self) {
  35. strref_cmp($0, comparison) == 0
  36. }
  37. return result
  38. }
  39. return false
  40. }
  41. }
  42. extension cf_parser {
  43. mutating func advanceToken() -> Bool {
  44. let result = withUnsafeMutablePointer(to: &self) {
  45. cf_next_token($0)
  46. }
  47. return result
  48. }
  49. mutating func hasNextToken() -> Bool {
  50. let result = withUnsafeMutablePointer(to: &self) {
  51. var nextToken: UnsafeMutablePointer<cf_token>?
  52. switch $0.pointee.cur_token.pointee.type {
  53. case CFTOKEN_SPACETAB, CFTOKEN_NEWLINE, CFTOKEN_NONE:
  54. nextToken = $0.pointee.cur_token
  55. default:
  56. nextToken = $0.pointee.cur_token.advanced(by: 1)
  57. }
  58. if var nextToken {
  59. while nextToken.pointee.type == CFTOKEN_SPACETAB || nextToken.pointee.type == CFTOKEN_NEWLINE {
  60. nextToken = nextToken.successor()
  61. }
  62. return nextToken.pointee.type != CFTOKEN_NONE
  63. } else {
  64. return false
  65. }
  66. }
  67. return result
  68. }
  69. mutating func tokenIsEqualTo(_ comparison: String) -> Bool {
  70. let result = withUnsafeMutablePointer(to: &self) {
  71. cf_token_is($0, comparison.cString(using: .utf8))
  72. }
  73. return result
  74. }
  75. }
  76. extension gs_shader_param_type {
  77. var size: Int {
  78. switch self {
  79. case GS_SHADER_PARAM_BOOL, GS_SHADER_PARAM_INT, GS_SHADER_PARAM_FLOAT:
  80. return MemoryLayout<Float32>.size
  81. case GS_SHADER_PARAM_INT2, GS_SHADER_PARAM_VEC2:
  82. return MemoryLayout<Float32>.size * 2
  83. case GS_SHADER_PARAM_INT3, GS_SHADER_PARAM_VEC3:
  84. return MemoryLayout<Float32>.size * 3
  85. case GS_SHADER_PARAM_INT4, GS_SHADER_PARAM_VEC4:
  86. return MemoryLayout<Float32>.size * 4
  87. case GS_SHADER_PARAM_MATRIX4X4:
  88. return MemoryLayout<Float32>.size * 4 * 4
  89. case GS_SHADER_PARAM_TEXTURE:
  90. return MemoryLayout<gs_shader_texture>.size
  91. case GS_SHADER_PARAM_STRING, GS_SHADER_PARAM_UNKNOWN:
  92. return 0
  93. default:
  94. return 0
  95. }
  96. }
  97. var mtlSize: Int {
  98. switch self {
  99. case GS_SHADER_PARAM_BOOL, GS_SHADER_PARAM_INT, GS_SHADER_PARAM_FLOAT:
  100. return MemoryLayout<simd_float1>.size
  101. case GS_SHADER_PARAM_INT2, GS_SHADER_PARAM_VEC2:
  102. return MemoryLayout<simd_float2>.size
  103. case GS_SHADER_PARAM_INT3, GS_SHADER_PARAM_VEC3:
  104. return MemoryLayout<simd_float3>.size
  105. case GS_SHADER_PARAM_INT4, GS_SHADER_PARAM_VEC4:
  106. return MemoryLayout<simd_float4>.size
  107. case GS_SHADER_PARAM_MATRIX4X4:
  108. return MemoryLayout<simd_float4x4>.size
  109. case GS_SHADER_PARAM_TEXTURE:
  110. return MemoryLayout<gs_shader_texture>.size
  111. case GS_SHADER_PARAM_STRING, GS_SHADER_PARAM_UNKNOWN:
  112. return 0
  113. default:
  114. return 0
  115. }
  116. }
  117. var mtlAlignment: Int {
  118. switch self {
  119. case GS_SHADER_PARAM_BOOL, GS_SHADER_PARAM_INT, GS_SHADER_PARAM_FLOAT:
  120. return MemoryLayout<simd_float1>.alignment
  121. case GS_SHADER_PARAM_INT2, GS_SHADER_PARAM_VEC2:
  122. return MemoryLayout<simd_float2>.alignment
  123. case GS_SHADER_PARAM_INT3, GS_SHADER_PARAM_VEC3:
  124. return MemoryLayout<simd_float3>.alignment
  125. case GS_SHADER_PARAM_INT4, GS_SHADER_PARAM_VEC4:
  126. return MemoryLayout<simd_float4>.alignment
  127. case GS_SHADER_PARAM_MATRIX4X4:
  128. return MemoryLayout<simd_float4x4>.alignment
  129. case GS_SHADER_PARAM_TEXTURE:
  130. return 0
  131. case GS_SHADER_PARAM_STRING, GS_SHADER_PARAM_UNKNOWN:
  132. return 0
  133. default:
  134. return 0
  135. }
  136. }
  137. }
  138. extension gs_color_format {
  139. var sRGBVariant: MTLPixelFormat? {
  140. switch self {
  141. case GS_RGBA:
  142. return .rgba8Unorm_srgb
  143. case GS_BGRX, GS_BGRA:
  144. return .bgra8Unorm_srgb
  145. default:
  146. return nil
  147. }
  148. }
  149. var mtlFormat: MTLPixelFormat {
  150. switch self {
  151. case GS_A8:
  152. return .a8Unorm
  153. case GS_R8:
  154. return .r8Unorm
  155. case GS_R8G8:
  156. return .rg8Unorm
  157. case GS_R16:
  158. return .r16Unorm
  159. case GS_R16F:
  160. return .r16Float
  161. case GS_RG16:
  162. return .rg16Unorm
  163. case GS_RG16F:
  164. return .rg16Float
  165. case GS_R32F:
  166. return .r32Float
  167. case GS_RG32F:
  168. return .rg32Float
  169. case GS_RGBA:
  170. return .rgba8Unorm
  171. case GS_BGRX, GS_BGRA:
  172. return .bgra8Unorm
  173. case GS_R10G10B10A2:
  174. return .rgb10a2Unorm
  175. case GS_RGBA16:
  176. return .rgba16Unorm
  177. case GS_RGBA16F:
  178. return .rgba16Float
  179. case GS_RGBA32F:
  180. return .rgba32Float
  181. case GS_DXT1:
  182. return .bc1_rgba
  183. case GS_DXT3:
  184. return .bc2_rgba
  185. case GS_DXT5:
  186. return .bc3_rgba
  187. default:
  188. return .invalid
  189. }
  190. }
  191. }
  192. extension gs_color_space {
  193. var colorFormat: gs_color_format {
  194. switch self {
  195. case GS_CS_SRGB_16F, GS_CS_709_SCRGB:
  196. return GS_RGBA16F
  197. default:
  198. return GS_RGBA
  199. }
  200. }
  201. var pixelFormat: MTLPixelFormat? {
  202. switch self {
  203. case GS_CS_SRGB:
  204. .bgra8Unorm_srgb
  205. case GS_CS_709_SCRGB:
  206. nil
  207. case GS_CS_709_EXTENDED:
  208. .bgra10_xr_srgb
  209. case GS_CS_SRGB_16F:
  210. nil
  211. default:
  212. nil
  213. }
  214. }
  215. }
  216. extension gs_depth_test {
  217. var mtlFunction: MTLCompareFunction {
  218. switch self {
  219. case GS_NEVER:
  220. return .never
  221. case GS_LESS:
  222. return .less
  223. case GS_LEQUAL:
  224. return .lessEqual
  225. case GS_EQUAL:
  226. return .equal
  227. case GS_GEQUAL:
  228. return .greaterEqual
  229. case GS_GREATER:
  230. return .greater
  231. case GS_NOTEQUAL:
  232. return .notEqual
  233. case GS_ALWAYS:
  234. return .always
  235. default:
  236. return .never
  237. }
  238. }
  239. }
  240. extension gs_stencil_op_type {
  241. var mtlOperation: MTLStencilOperation {
  242. switch self {
  243. case GS_KEEP:
  244. return .keep
  245. case GS_ZERO:
  246. return .zero
  247. case GS_REPLACE:
  248. return .replace
  249. case GS_INCR:
  250. return .incrementWrap
  251. case GS_DECR:
  252. return .decrementWrap
  253. case GS_INVERT:
  254. return .invert
  255. default:
  256. return .keep
  257. }
  258. }
  259. }
  260. extension gs_blend_type {
  261. var blendFactor: MTLBlendFactor? {
  262. switch self {
  263. case GS_BLEND_ZERO:
  264. return .zero
  265. case GS_BLEND_ONE:
  266. return .one
  267. case GS_BLEND_SRCCOLOR:
  268. return .sourceColor
  269. case GS_BLEND_INVSRCCOLOR:
  270. return .oneMinusSourceColor
  271. case GS_BLEND_SRCALPHA:
  272. return .sourceAlpha
  273. case GS_BLEND_INVSRCALPHA:
  274. return .oneMinusSourceAlpha
  275. case GS_BLEND_DSTCOLOR:
  276. return .destinationColor
  277. case GS_BLEND_INVDSTCOLOR:
  278. return .oneMinusDestinationColor
  279. case GS_BLEND_DSTALPHA:
  280. return .destinationAlpha
  281. case GS_BLEND_INVDSTALPHA:
  282. return .oneMinusDestinationAlpha
  283. case GS_BLEND_SRCALPHASAT:
  284. return .sourceAlphaSaturated
  285. default:
  286. return nil
  287. }
  288. }
  289. }
  290. extension gs_blend_op_type {
  291. var mtlOperation: MTLBlendOperation? {
  292. switch self {
  293. case GS_BLEND_OP_ADD:
  294. return .add
  295. case GS_BLEND_OP_MAX:
  296. return .max
  297. case GS_BLEND_OP_MIN:
  298. return .min
  299. case GS_BLEND_OP_SUBTRACT:
  300. return .subtract
  301. case GS_BLEND_OP_REVERSE_SUBTRACT:
  302. return .reverseSubtract
  303. default:
  304. return nil
  305. }
  306. }
  307. }
  308. extension gs_cull_mode {
  309. var mtlMode: MTLCullMode {
  310. switch self {
  311. case GS_BACK:
  312. return .back
  313. case GS_FRONT:
  314. return .front
  315. default:
  316. return .none
  317. }
  318. }
  319. }
  320. extension gs_draw_mode {
  321. var mtlPrimitive: MTLPrimitiveType? {
  322. switch self {
  323. case GS_POINTS:
  324. return .point
  325. case GS_LINES:
  326. return .line
  327. case GS_LINESTRIP:
  328. return .lineStrip
  329. case GS_TRIS:
  330. return .triangle
  331. case GS_TRISTRIP:
  332. return .triangleStrip
  333. default:
  334. return nil
  335. }
  336. }
  337. }
  338. extension gs_rect {
  339. var mtlViewPort: MTLViewport {
  340. MTLViewport(
  341. originX: Double(self.x),
  342. originY: Double(self.y),
  343. width: Double(self.cx),
  344. height: Double(self.cy),
  345. znear: 0.0,
  346. zfar: 1.0)
  347. }
  348. var mtlScissorRect: MTLScissorRect {
  349. MTLScissorRect(
  350. x: Int(self.x),
  351. y: Int(self.y),
  352. width: Int(self.cx),
  353. height: Int(self.cy))
  354. }
  355. }
  356. extension gs_zstencil_format {
  357. var mtlFormat: MTLPixelFormat {
  358. switch self {
  359. case GS_ZS_NONE:
  360. return .invalid
  361. case GS_Z16:
  362. return .depth16Unorm
  363. case GS_Z24_S8:
  364. return .depth24Unorm_stencil8
  365. case GS_Z32F:
  366. return .depth32Float
  367. case GS_Z32F_S8X24:
  368. return .depth32Float_stencil8
  369. default:
  370. return .invalid
  371. }
  372. }
  373. }
  374. extension gs_index_type {
  375. var mtlType: MTLIndexType? {
  376. switch self {
  377. case GS_UNSIGNED_LONG:
  378. return .uint16
  379. case GS_UNSIGNED_SHORT:
  380. return .uint32
  381. default:
  382. return nil
  383. }
  384. }
  385. var byteSize: Int {
  386. guard let indexType = self.mtlType else {
  387. return 0
  388. }
  389. let byteSize =
  390. if indexType == .uint16 {
  391. 2
  392. } else {
  393. 4
  394. }
  395. return byteSize
  396. }
  397. }
  398. extension gs_address_mode {
  399. var mtlMode: MTLSamplerAddressMode? {
  400. switch self {
  401. case GS_ADDRESS_WRAP:
  402. return .repeat
  403. case GS_ADDRESS_CLAMP:
  404. return .clampToEdge
  405. case GS_ADDRESS_MIRROR:
  406. return .mirrorRepeat
  407. case GS_ADDRESS_BORDER:
  408. return .clampToBorderColor
  409. case GS_ADDRESS_MIRRORONCE:
  410. return .mirrorClampToEdge
  411. default:
  412. return nil
  413. }
  414. }
  415. }
  416. extension gs_sample_filter {
  417. var minMagFilter: MTLSamplerMinMagFilter? {
  418. switch self {
  419. case GS_FILTER_POINT, GS_FILTER_MIN_MAG_POINT_MIP_LINEAR, GS_FILTER_MIN_POINT_MAG_LINEAR_MIP_POINT,
  420. GS_FILTER_MIN_POINT_MAG_MIP_LINEAR:
  421. return .nearest
  422. case GS_FILTER_LINEAR, GS_FILTER_MIN_LINEAR_MAG_MIP_POINT, GS_FILTER_MIN_LINEAR_MAG_POINT_MIP_LINEAR,
  423. GS_FILTER_MIN_MAG_LINEAR_MIP_POINT, GS_FILTER_ANISOTROPIC:
  424. return .linear
  425. default:
  426. return nil
  427. }
  428. }
  429. var mipFilter: MTLSamplerMipFilter? {
  430. switch self {
  431. case GS_FILTER_POINT, GS_FILTER_MIN_MAG_POINT_MIP_LINEAR, GS_FILTER_MIN_POINT_MAG_LINEAR_MIP_POINT,
  432. GS_FILTER_MIN_POINT_MAG_MIP_LINEAR:
  433. return .nearest
  434. case GS_FILTER_LINEAR, GS_FILTER_MIN_LINEAR_MAG_MIP_POINT, GS_FILTER_MIN_LINEAR_MAG_POINT_MIP_LINEAR,
  435. GS_FILTER_MIN_MAG_LINEAR_MIP_POINT, GS_FILTER_ANISOTROPIC:
  436. return .linear
  437. default:
  438. return nil
  439. }
  440. }
  441. }