test-desktop.m 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173
  1. #include <stdlib.h>
  2. #include "test-desktop.h"
  3. #import <Cocoa/Cocoa.h>
  4. #import <AppKit/AppKit.h>
  5. #import <OpenGL/OpenGL.h>
  6. #import <OpenGL/CGLIOSurface.h>
  7. #import <OpenGL/CGLMacro.h>
  8. #import <CoreGraphics/CGDisplayStream.h>
  9. #include <pthread.h>
  10. const char *osx_desktop_test_getname(const char *locale)
  11. {
  12. return "OSX Monitor Capture";
  13. }
  14. static IOSurfaceRef current = NULL,
  15. prev = NULL;
  16. static texture_t tex = NULL;
  17. static pthread_mutex_t c_mutex;
  18. struct desktop_tex *osx_desktop_test_create(const char *settings,
  19. obs_source_t source)
  20. {
  21. struct desktop_tex *rt = bzalloc(sizeof(struct desktop_tex));
  22. char *effect_file;
  23. gs_entercontext(obs_graphics());
  24. struct gs_sampler_info info = {
  25. .filter = GS_FILTER_LINEAR,
  26. .address_u = GS_ADDRESS_CLAMP,
  27. .address_v = GS_ADDRESS_CLAMP,
  28. .address_w = GS_ADDRESS_CLAMP,
  29. .max_anisotropy = 1,
  30. };
  31. rt->sampler = gs_create_samplerstate(&info);
  32. effect_file = obs_find_plugin_file("test-input/draw_rect.effect");
  33. rt->whatever = gs_create_effect_from_file(effect_file, NULL);
  34. bfree(effect_file);
  35. if (!rt->whatever) {
  36. osx_desktop_test_destroy(rt);
  37. return NULL;
  38. }
  39. if ([[NSScreen screens] count] < 1) {
  40. osx_desktop_test_destroy(rt);
  41. return NULL;
  42. }
  43. NSScreen *screen = [NSScreen screens][0];
  44. NSRect frame = [screen convertRectToBacking:[screen frame]];
  45. rt->width = frame.size.width;
  46. rt->height = frame.size.height;
  47. pthread_mutex_init(&rt->mutex, NULL);
  48. NSDictionary *dict = @{
  49. (__bridge NSString*)kCGDisplayStreamSourceRect:
  50. (__bridge NSDictionary*)CGRectCreateDictionaryRepresentation(
  51. CGRectMake(0, 0, rt->width, rt->height)),
  52. (__bridge NSString*)kCGDisplayStreamQueueDepth: @5
  53. };
  54. rt->disp = CGDisplayStreamCreateWithDispatchQueue(CGMainDisplayID(),
  55. rt->width, rt->height, 'BGRA',
  56. (__bridge CFDictionaryRef)dict,
  57. dispatch_queue_create(NULL, NULL),
  58. ^(CGDisplayStreamFrameStatus status, uint64_t
  59. displayTime, IOSurfaceRef frameSurface,
  60. CGDisplayStreamUpdateRef updateRef)
  61. {
  62. if (!frameSurface ||
  63. pthread_mutex_trylock(&rt->mutex))
  64. return;
  65. if (rt->current) {
  66. IOSurfaceDecrementUseCount(rt->current);
  67. CFRelease(rt->current);
  68. rt->current = NULL;
  69. }
  70. rt->current = frameSurface;
  71. CFRetain(rt->current);
  72. IOSurfaceIncrementUseCount(rt->current);
  73. pthread_mutex_unlock(&rt->mutex);
  74. }
  75. );
  76. gs_leavecontext();
  77. if (CGDisplayStreamStart(rt->disp)) {
  78. osx_desktop_test_destroy(rt);
  79. return NULL;
  80. }
  81. return rt;
  82. }
  83. void osx_desktop_test_destroy(struct desktop_tex *rt)
  84. {
  85. if (rt) {
  86. pthread_mutex_lock(&rt->mutex);
  87. gs_entercontext(obs_graphics());
  88. if (current) {
  89. IOSurfaceDecrementUseCount(rt->current);
  90. CFRelease(rt->current);
  91. }
  92. if (rt->sampler)
  93. samplerstate_destroy(rt->sampler);
  94. if (tex)
  95. texture_destroy(rt->tex);
  96. CGDisplayStreamStop(rt->disp);
  97. effect_destroy(rt->whatever);
  98. bfree(rt);
  99. gs_leavecontext();
  100. pthread_mutex_unlock(&rt->mutex);
  101. }
  102. }
  103. uint32_t osx_desktop_test_get_output_flags(struct desktop_tex *rt)
  104. {
  105. return SOURCE_VIDEO;
  106. }
  107. void osx_desktop_test_video_render(struct desktop_tex *rt,
  108. obs_source_t filter_target)
  109. {
  110. pthread_mutex_lock(&rt->mutex);
  111. if (rt->prev != rt->current) {
  112. if (tex)
  113. texture_rebind_iosurface(rt->tex, rt->current);
  114. else
  115. rt->tex = gs_create_texture_from_iosurface(
  116. rt->current);
  117. rt->prev = rt->current;
  118. }
  119. if (!rt->tex) goto fail;
  120. gs_load_samplerstate(rt->sampler, 0);
  121. technique_t tech = effect_gettechnique(rt->whatever, "Default");
  122. effect_settexture(rt->whatever, effect_getparambyidx(rt->whatever, 1),
  123. rt->tex);
  124. technique_begin(tech);
  125. technique_beginpass(tech, 0);
  126. gs_draw_sprite(rt->tex, 0, 0, 0);
  127. technique_endpass(tech);
  128. technique_end(tech);
  129. fail:
  130. pthread_mutex_unlock(&rt->mutex);
  131. }
  132. uint32_t osx_desktop_test_getwidth(struct desktop_tex *rt)
  133. {
  134. return rt->width;
  135. }
  136. uint32_t osx_desktop_test_getheight(struct desktop_tex *rt)
  137. {
  138. return rt->height;
  139. }