FramebufferCache.swift 2.7 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768
  1. #if os(Linux)
  2. #if GLES
  3. import COpenGLES.gles2
  4. #else
  5. import COpenGL
  6. #endif
  7. #else
  8. #if GLES
  9. import OpenGLES
  10. #else
  11. import OpenGL.GL3
  12. #endif
  13. #endif
  14. // TODO: Add mechanism to purge framebuffers on low memory
  15. public class FramebufferCache {
  16. var framebufferCache = [Int64: [Framebuffer]]()
  17. let context: OpenGLContext
  18. init(context: OpenGLContext) {
  19. self.context = context
  20. }
  21. public func requestFramebufferWithProperties(orientation: ImageOrientation, size: GLSize, textureOnly: Bool = false, minFilter: Int32 = GL_LINEAR, magFilter: Int32 = GL_LINEAR, wrapS: Int32 = GL_CLAMP_TO_EDGE, wrapT: Int32 = GL_CLAMP_TO_EDGE, internalFormat: Int32 = GL_RGBA, format: Int32 = GL_BGRA, type: Int32 = GL_UNSIGNED_BYTE, stencil: Bool = false) -> Framebuffer {
  22. let hash = hashForFramebufferWithProperties(orientation: orientation, size: size, textureOnly: textureOnly, minFilter: minFilter, magFilter: magFilter, wrapS: wrapS, wrapT: wrapT, internalFormat: internalFormat, format: format, type: type, stencil: stencil)
  23. let framebuffer: Framebuffer
  24. if framebufferCache.count > 20 {
  25. debugPrint("WARNING: Runaway framebuffer cache with size: \(framebufferCache.count)")
  26. }
  27. if (framebufferCache[hash]?.count ?? -1) > 0 {
  28. // debugPrint("Restoring previous framebuffer")
  29. framebuffer = framebufferCache[hash]!.removeLast()
  30. framebuffer.orientation = orientation
  31. } else {
  32. do {
  33. // debugPrint("Generating new framebuffer at size: \(size)")
  34. framebuffer = try Framebuffer(context: context, orientation: orientation, size: size, textureOnly: textureOnly, minFilter: minFilter, magFilter: magFilter, wrapS: wrapS, wrapT: wrapT, internalFormat: internalFormat, format: format, type: type, stencil: stencil)
  35. framebuffer.cache = self
  36. } catch {
  37. fatalError("Could not create a framebuffer of the size (\(size.width), \(size.height)), error: \(error)")
  38. }
  39. }
  40. return framebuffer
  41. }
  42. public func purgeAllUnassignedFramebuffers() {
  43. framebufferCache.removeAll()
  44. #if os(iOS)
  45. CVOpenGLESTextureCacheFlush(sharedImageProcessingContext.coreVideoTextureCache, 0);
  46. print("release buffer")
  47. #endif
  48. }
  49. func returnToCache(_ framebuffer: Framebuffer) {
  50. // sprint("Returning to cache: \(framebuffer)")
  51. context.runOperationSynchronously {
  52. if self.framebufferCache[framebuffer.hash] != nil {
  53. self.framebufferCache[framebuffer.hash]!.append(framebuffer)
  54. } else {
  55. self.framebufferCache[framebuffer.hash] = [framebuffer]
  56. }
  57. }
  58. }
  59. }