QGVAPMetalUtil.m 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190
  1. // QGVAPMetalUtil.m
  2. // Tencent is pleased to support the open source community by making vap available.
  3. //
  4. // Copyright (C) 2020 THL A29 Limited, a Tencent company. All rights reserved.
  5. //
  6. // Licensed under the MIT License (the "License"); you may not use this file except in
  7. // compliance with the License. You may obtain a copy of the License at
  8. //
  9. // http://opensource.org/licenses/MIT
  10. //
  11. // Unless required by applicable law or agreed to in writing, software distributed under the License is
  12. // distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
  13. // either express or implied. See the License for the specific language governing permissions and
  14. // limitations under the License.
  15. #import "QGVAPMetalUtil.h"
  16. #import <AVFoundation/AVFoundation.h>
  17. #import "QGVAPLogger.h"
  18. #import <UIKit/UIKit.h>
  19. NSString *const kVAPAttachmentVertexFunctionName = @"vapAttachment_vertexShader";
  20. NSString *const kVAPAttachmentFragmentFunctionName = @"vapAttachment_FragmentShader";
  21. NSString *const kVAPVertexFunctionName = @"vap_vertexShader";
  22. NSString *const kVAPYUVFragmentFunctionName = @"vap_yuvFragmentShader";
  23. NSString *const kVAPMaskFragmentFunctionName = @"vap_maskFragmentShader";
  24. NSString *const kVAPMaskBlurFragmentFunctionName = @"vap_maskBlurFragmentShader";
  25. float const kVAPMTLVerticesIdentity[16] = {-1.0, -1.0, 0.0, 1.0, -1.0, 1.0, 0.0, 1.0, 1.0, -1.0, 0.0, 1.0, 1.0, 1.0, 0.0, 1.0};
  26. float const kVAPMTLTextureCoordinatesIdentity[8] = {0.0, 1.0, 0.0, 0.0, 1.0, 1.0, 1.0, 0.0};
  27. float const kVAPMTLTextureCoordinatesFor90[8] = {0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 1.0, 1.0};
  28. void replaceArrayElements(float arr0[], float arr1[], int size) {
  29. if ((arr0 == NULL || arr1 == NULL) && size > 0) {
  30. assert(0);
  31. }
  32. if (size < 0) {
  33. assert(0);
  34. }
  35. for (int i = 0; i < size; i++) {
  36. arr0[i] = arr1[i];
  37. }
  38. }
  39. //倒N形
  40. void genMTLVertices(CGRect rect, CGSize containerSize, float vertices[16], BOOL reverse) {
  41. if (vertices == NULL) {
  42. VAP_Error(kQGVAPModuleCommon, @"generateMTLVertices params illegal.");
  43. assert(0);
  44. return ;
  45. }
  46. if (containerSize.width <= 0 || containerSize.height <= 0) {
  47. VAP_Error(kQGVAPModuleCommon, @"generateMTLVertices params containerSize illegal.");
  48. assert(0);
  49. return ;
  50. }
  51. float originX, originY, width, height;
  52. originX = -1+2*rect.origin.x/containerSize.width;
  53. originY = 1-2*rect.origin.y/containerSize.height;
  54. width = 2*rect.size.width/containerSize.width;
  55. height = 2*rect.size.height/containerSize.height;
  56. if (reverse) {
  57. float tempVertices[] = {originX, originY-height, 0.0, 1.0, originX, originY, 0.0, 1.0, originX+width, originY-height, 0.0, 1.0, originX+width, originY, 0.0, 1.0};
  58. replaceArrayElements(vertices, tempVertices, 16);
  59. return ;
  60. }
  61. float tempVertices[] = {originX, originY, 0.0, 1.0, originX, originY-height, 0.0, 1.0, originX+width, originY, 0.0, 1.0 , originX+width, originY-height, 0.0, 1.0};
  62. replaceArrayElements(vertices, tempVertices, 16);
  63. }
  64. //N形
  65. void genMTLTextureCoordinates(CGRect rect, CGSize containerSize, float coordinates[8], BOOL reverse, NSInteger degree) {
  66. //degree预留字段,支持旋转纹理
  67. if (coordinates == NULL) {
  68. VAP_Error(kQGVAPModuleCommon, @"generateMTLTextureCoordinates params coordinates illegal.");
  69. assert(0);
  70. return ;
  71. }
  72. if (containerSize.width <= 0 || containerSize.height <= 0) {
  73. VAP_Error(kQGVAPModuleCommon, @"generateMTLTextureCoordinates params containerSize illegal.");
  74. assert(0);
  75. return ;
  76. }
  77. float originX, originY, width, height;
  78. originX = rect.origin.x/containerSize.width;
  79. originY = rect.origin.y/containerSize.height;
  80. width = rect.size.width/containerSize.width;
  81. height = rect.size.height/containerSize.height;
  82. if (reverse) {
  83. float tempCoordintes[] = {originX, originY, originX, originY+height , originX+width, originY,originX+width, originY+height};
  84. replaceArrayElements(coordinates, tempCoordintes, 8);
  85. return ;
  86. }
  87. float tempCoordintes[] = {originX, originY+height, originX, originY, originX+width, originY+height, originX+width, originY};
  88. replaceArrayElements(coordinates, tempCoordintes, 8);
  89. }
  90. CGSize vapSourceSizeForCenterFull(CGSize sourceSize, CGSize renderSize) {
  91. //source大小完全包含render大小,直接返回中间部分
  92. if (sourceSize.width >= renderSize.width && sourceSize.height >= renderSize.height) {
  93. return sourceSize;
  94. }
  95. CGRect rectForAspectFill = vapRectWithContentModeInsideRect(CGRectMake(0, 0, renderSize.width, renderSize.height), sourceSize, UIViewContentModeScaleAspectFill);
  96. return rectForAspectFill.size;
  97. }
  98. CGRect vapRectForCenterFull(CGSize sourceSize, CGSize renderSize) {
  99. //source大小完全包含render大小,直接返回中间部分
  100. if (sourceSize.width >= renderSize.width && sourceSize.height >= renderSize.height) {
  101. return CGRectMake((sourceSize.width-renderSize.width)/2.0, (sourceSize.height-renderSize.height)/2.0, renderSize.width, renderSize.height);
  102. }
  103. CGRect rectForAspectFill = vapRectWithContentModeInsideRect(CGRectMake(0, 0, renderSize.width, renderSize.height), sourceSize, UIViewContentModeScaleAspectFill);
  104. CGRect intersection = CGRectMake(-rectForAspectFill.origin.x, -rectForAspectFill.origin.y, renderSize.width, renderSize.height);
  105. return intersection;
  106. }
  107. CGRect vapRectWithContentModeInsideRect(CGRect boundingRect, CGSize aspectRatio, UIViewContentMode contentMode) {
  108. if (aspectRatio.width <= 0 || aspectRatio.height <= 0) {
  109. return boundingRect;
  110. }
  111. CGRect desRect = CGRectZero;
  112. switch (contentMode) {
  113. case UIViewContentModeScaleToFill: {
  114. desRect = boundingRect;
  115. }
  116. break;
  117. case UIViewContentModeScaleAspectFit: {
  118. desRect = AVMakeRectWithAspectRatioInsideRect(aspectRatio, boundingRect);
  119. }
  120. break;
  121. case UIViewContentModeScaleAspectFill: {
  122. CGFloat ratio = MAX(CGRectGetWidth(boundingRect)/aspectRatio.width, CGRectGetHeight(boundingRect)/aspectRatio.height);
  123. CGSize contentSize = CGSizeMake(aspectRatio.width*ratio, aspectRatio.height*ratio);
  124. desRect = CGRectMake(boundingRect.origin.x+(CGRectGetWidth(boundingRect)-contentSize.width)/2.0, boundingRect.origin.y+(CGRectGetHeight(boundingRect)-contentSize.height)/2.0, contentSize.width, contentSize.height);
  125. }
  126. break;
  127. case UIViewContentModeCenter: {
  128. desRect = CGRectMake(boundingRect.origin.x+(CGRectGetWidth(boundingRect)-aspectRatio.width)/2.0, boundingRect.origin.y+(CGRectGetHeight(boundingRect)-aspectRatio.height)/2.0, aspectRatio.width, aspectRatio.height);
  129. }
  130. break;
  131. case UIViewContentModeTop: {
  132. desRect = CGRectMake(boundingRect.origin.x+(CGRectGetWidth(boundingRect)-aspectRatio.width)/2.0, boundingRect.origin.y, aspectRatio.width, aspectRatio.height);
  133. }
  134. break;
  135. case UIViewContentModeBottom: {
  136. desRect = CGRectMake(boundingRect.origin.x+(CGRectGetWidth(boundingRect)-aspectRatio.width)/2.0, boundingRect.origin.y+CGRectGetHeight(boundingRect)-aspectRatio.height, aspectRatio.width, aspectRatio.height);
  137. }
  138. break;
  139. case UIViewContentModeLeft: {
  140. desRect = CGRectMake(boundingRect.origin.x, boundingRect.origin.y+(CGRectGetHeight(boundingRect)-aspectRatio.height)/2.0, aspectRatio.width, aspectRatio.height);
  141. }
  142. break;
  143. case UIViewContentModeRight: {
  144. desRect = CGRectMake(boundingRect.origin.x+CGRectGetWidth(boundingRect)-aspectRatio.width, boundingRect.origin.y+(CGRectGetHeight(boundingRect)-aspectRatio.height)/2.0, aspectRatio.width, aspectRatio.height);
  145. }
  146. break;
  147. case UIViewContentModeTopLeft: {
  148. desRect = CGRectMake(boundingRect.origin.x, boundingRect.origin.y, aspectRatio.width, aspectRatio.height);
  149. }
  150. break;
  151. case UIViewContentModeTopRight: {
  152. desRect = CGRectMake(boundingRect.origin.x+CGRectGetWidth(boundingRect)-aspectRatio.width, boundingRect.origin.y, aspectRatio.width, aspectRatio.height);
  153. }
  154. break;
  155. case UIViewContentModeBottomLeft: {
  156. desRect = CGRectMake(boundingRect.origin.x, boundingRect.origin.y+CGRectGetHeight(boundingRect)-aspectRatio.height, aspectRatio.width, aspectRatio.height);
  157. }
  158. break;
  159. case UIViewContentModeBottomRight: {
  160. desRect = CGRectMake(boundingRect.origin.x+CGRectGetWidth(boundingRect)-aspectRatio.width, boundingRect.origin.y+CGRectGetHeight(boundingRect)-aspectRatio.height, aspectRatio.width, aspectRatio.height);
  161. }
  162. break;
  163. default:
  164. break;
  165. }
  166. return desRect;
  167. }
  168. @implementation QGVAPMetalUtil
  169. @end