CVTextureCache.mm 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167
  1. #include "CVTextureCache.h"
  2. #include "DisplayManager.h"
  3. #include <OpenGLES/ES2/glext.h>
  4. #include <OpenGLES/ES3/gl.h>
  5. #include <OpenGLES/ES3/glext.h>
  6. #include <CoreVideo/CVOpenGLESTextureCache.h>
  7. #include "UnityMetalSupport.h"
  8. #if UNITY_CAN_USE_METAL
  9. #include <CoreVideo/CVMetalTextureCache.h>
  10. #else
  11. typedef void* CVMetalTextureCacheRef;
  12. typedef void* CVMetalTextureRef;
  13. const CFStringRef kCVPixelBufferMetalCompatibilityKey = CFSTR("MetalCompatibility");
  14. inline CVReturn CVMetalTextureCacheCreate(CFAllocatorRef, CFDictionaryRef, MTLDeviceRef, CFDictionaryRef, CVMetalTextureCacheRef*) { return 0; }
  15. inline CVReturn CVMetalTextureCacheCreateTextureFromImage(CFAllocatorRef, CVMetalTextureCacheRef, CVImageBufferRef, CFDictionaryRef, MTLPixelFormat, size_t, size_t, size_t, CVMetalTextureRef*) { return 0; }
  16. inline void CVMetalTextureCacheFlush(CVMetalTextureCacheRef, uint64_t options) {}
  17. inline MTLTextureRef CVMetalTextureGetTexture(CVMetalTextureRef) { return nil; }
  18. inline Boolean CVMetalTextureIsFlipped(CVMetalTextureRef) { return 0; }
  19. #endif
  20. void* CreateCVTextureCache()
  21. {
  22. void* ret = 0;
  23. CVReturn err = 0;
  24. if (UnitySelectedRenderingAPI() == apiMetal)
  25. err = CVMetalTextureCacheCreate(kCFAllocatorDefault, 0, UnityGetMetalDevice(), 0, (CVMetalTextureCacheRef*)&ret);
  26. else
  27. err = CVOpenGLESTextureCacheCreate(kCFAllocatorDefault, 0, UnityGetMainScreenContextGLES(), 0, (CVOpenGLESTextureCacheRef*)&ret);
  28. if (err)
  29. {
  30. ::printf("Error at CVOpenGLESTextureCacheCreate: %d", err);
  31. ret = 0;
  32. }
  33. return ret;
  34. }
  35. void FlushCVTextureCache(void* cache)
  36. {
  37. if (UnitySelectedRenderingAPI() == apiMetal)
  38. CVMetalTextureCacheFlush((CVMetalTextureCacheRef)cache, 0);
  39. else
  40. CVOpenGLESTextureCacheFlush((CVOpenGLESTextureCacheRef)cache, 0);
  41. }
  42. void* CreateBGRA32TextureFromCVTextureCache(void* cache, void* image, size_t w, size_t h)
  43. {
  44. void* texture = 0;
  45. CVReturn err = 0;
  46. if (UnitySelectedRenderingAPI() == apiMetal)
  47. {
  48. err = CVMetalTextureCacheCreateTextureFromImage(
  49. kCFAllocatorDefault, (CVMetalTextureCacheRef)cache, (CVImageBufferRef)image, 0,
  50. (MTLPixelFormat)((UnityDisplaySurfaceMTL*)GetMainDisplaySurface())->colorFormat, w, h, 0, (CVMetalTextureRef*)&texture
  51. );
  52. }
  53. else
  54. {
  55. err = CVOpenGLESTextureCacheCreateTextureFromImage(
  56. kCFAllocatorDefault, (CVOpenGLESTextureCacheRef)cache, (CVImageBufferRef)image, 0,
  57. GL_TEXTURE_2D, GL_RGBA, (GLsizei)w, (GLsizei)h, GL_BGRA_EXT, GL_UNSIGNED_BYTE,
  58. 0, (CVOpenGLESTextureRef*)&texture
  59. );
  60. }
  61. if (err)
  62. {
  63. ::printf("Error at CVOpenGLESTextureCacheCreateTextureFromImage: %d\n", err);
  64. texture = 0;
  65. }
  66. return texture;
  67. }
  68. void* CreateHalfFloatTextureFromCVTextureCache(void* cache, void* image, size_t w, size_t h)
  69. {
  70. void* texture = 0;
  71. CVReturn err = 0;
  72. if (UnitySelectedRenderingAPI() == apiMetal)
  73. {
  74. err = CVMetalTextureCacheCreateTextureFromImage(
  75. kCFAllocatorDefault, (CVMetalTextureCacheRef)cache, (CVImageBufferRef)image, 0,
  76. MTLPixelFormatR16Float, w, h, 0, (CVMetalTextureRef*)&texture
  77. );
  78. }
  79. else if (UnitySelectedRenderingAPI() == apiOpenGLES3)
  80. {
  81. err = CVOpenGLESTextureCacheCreateTextureFromImage(
  82. kCFAllocatorDefault, (CVOpenGLESTextureCacheRef)cache, (CVImageBufferRef)image, 0,
  83. GL_TEXTURE_2D, GL_R16F, (GLsizei)w, (GLsizei)h, GL_RED, GL_HALF_FLOAT,
  84. 0, (CVOpenGLESTextureRef*)&texture
  85. );
  86. }
  87. else // OpenGLES2
  88. {
  89. err = CVOpenGLESTextureCacheCreateTextureFromImage(
  90. kCFAllocatorDefault, (CVOpenGLESTextureCacheRef)cache, (CVImageBufferRef)image, 0,
  91. GL_TEXTURE_2D, GL_RED_EXT, (GLsizei)w, (GLsizei)h, GL_RED_EXT, GL_HALF_FLOAT_OES,
  92. 0, (CVOpenGLESTextureRef*)&texture
  93. );
  94. }
  95. if (err)
  96. {
  97. ::printf("Error at CVOpenGLESTextureCacheCreateTextureFromImage: %d\n", err);
  98. texture = 0;
  99. }
  100. return texture;
  101. }
  102. unsigned GetGLTextureFromCVTextureCache(void* texture)
  103. {
  104. assert(UnitySelectedRenderingAPI() != apiMetal);
  105. return CVOpenGLESTextureGetName((CVOpenGLESTextureRef)texture);
  106. }
  107. id<MTLTexture> GetMetalTextureFromCVTextureCache(void* texture)
  108. {
  109. assert(UnitySelectedRenderingAPI() == apiMetal);
  110. return CVMetalTextureGetTexture((CVMetalTextureRef)texture);
  111. }
  112. uintptr_t GetTextureFromCVTextureCache(void* texture)
  113. {
  114. if (UnitySelectedRenderingAPI() == apiMetal)
  115. return (uintptr_t)(__bridge void*)GetMetalTextureFromCVTextureCache(texture);
  116. else
  117. return (uintptr_t)GetGLTextureFromCVTextureCache(texture);
  118. }
  119. void* CreatePixelBufferForCVTextureCache(size_t w, size_t h)
  120. {
  121. NSString* apiKey = UnitySelectedRenderingAPI() == apiMetal ? (__bridge NSString*)kCVPixelBufferMetalCompatibilityKey
  122. : (__bridge NSString*)kCVPixelBufferOpenGLESCompatibilityKey;
  123. CVPixelBufferRef pb = 0;
  124. NSDictionary* options = @{ (__bridge NSString*)kCVPixelBufferPixelFormatTypeKey: @(kCVPixelFormatType_32BGRA),
  125. (__bridge NSString*)kCVPixelBufferWidthKey: @(w),
  126. (__bridge NSString*)kCVPixelBufferHeightKey: @(h),
  127. apiKey: @(YES),
  128. (__bridge NSString*)kCVPixelBufferIOSurfacePropertiesKey: @{}};
  129. CVPixelBufferCreate(kCFAllocatorDefault, w, h, kCVPixelFormatType_32BGRA, (__bridge CFDictionaryRef)options, &pb);
  130. return pb;
  131. }
  132. void* CreateReadableRTFromCVTextureCache(void* cache, size_t w, size_t h, void** pb)
  133. {
  134. *pb = CreatePixelBufferForCVTextureCache(w, h);
  135. return CreateBGRA32TextureFromCVTextureCache(cache, *pb, w, h);
  136. }
  137. int IsCVTextureFlipped(void* texture)
  138. {
  139. if (UnitySelectedRenderingAPI() == apiMetal)
  140. return CVMetalTextureIsFlipped((CVMetalTextureRef)texture);
  141. else
  142. return CVOpenGLESTextureIsFlipped((CVOpenGLESTextureRef)texture);
  143. }