You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

OSXPixelBuffer.cxx 3.2KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114
  1. /* Copyright 2011-2014 Pierre Ossman for Cendio AB
  2. *
  3. * This 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. *
  8. * This software is distributed in the hope that it will be useful,
  9. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. * GNU General Public License for more details.
  12. *
  13. * You should have received a copy of the GNU General Public License
  14. * along with this software; if not, write to the Free Software
  15. * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
  16. * USA.
  17. */
  18. #ifdef HAVE_CONFIG_H
  19. #include <config.h>
  20. #endif
  21. #include <ApplicationServices/ApplicationServices.h>
  22. #include <FL/Fl_Window.H>
  23. #include <FL/x.H>
  24. #include <rfb/LogWriter.h>
  25. #include <rfb/Exception.h>
  26. #include "i18n.h"
  27. #include "OSXPixelBuffer.h"
  28. using namespace rfb;
  29. static rfb::LogWriter vlog("OSXPixelBuffer");
  30. OSXPixelBuffer::OSXPixelBuffer(int width, int height) :
  31. PlatformPixelBuffer(rfb::PixelFormat(32, 24, false, true,
  32. 255, 255, 255, 16, 8, 0),
  33. width, height, NULL, width),
  34. image(NULL)
  35. {
  36. CGColorSpaceRef lut;
  37. CGDataProviderRef provider;
  38. data = new rdr::U8[width * height * format.bpp/8];
  39. if (data == NULL)
  40. throw rfb::Exception(_("Not enough memory for framebuffer"));
  41. lut = CGDisplayCopyColorSpace(kCGDirectMainDisplay);
  42. if (!lut) {
  43. vlog.error(_("Could not get screen color space. Using slower fallback."));
  44. lut = CGColorSpaceCreateDeviceRGB();
  45. if (!lut)
  46. throw rfb::Exception("CGColorSpaceCreateDeviceRGB");
  47. }
  48. provider = CGDataProviderCreateWithData(NULL, data,
  49. width * height * 4, NULL);
  50. if (!provider)
  51. throw rfb::Exception("CGDataProviderCreateWithData");
  52. image = CGImageCreate(width, height, 8, 32, width * 4, lut,
  53. kCGImageAlphaNoneSkipFirst | kCGBitmapByteOrder32Little,
  54. provider, NULL, false, kCGRenderingIntentDefault);
  55. CGColorSpaceRelease(lut);
  56. CGDataProviderRelease(provider);
  57. if (!image)
  58. throw rfb::Exception("CGImageCreate");
  59. }
  60. OSXPixelBuffer::~OSXPixelBuffer()
  61. {
  62. CGImageRelease(image);
  63. delete [] data;
  64. }
  65. void OSXPixelBuffer::draw(int src_x, int src_y, int x, int y, int w, int h)
  66. {
  67. CGContextRef gc;
  68. CGRect rect;
  69. gc = fl_gc;
  70. CGContextSaveGState(gc);
  71. // macOS Coordinates are from bottom left, not top left
  72. src_y = height() - (src_y + h);
  73. y = Fl_Window::current()->h() - (y + h);
  74. // Reset the transformation matrix back to the default identity
  75. // matrix as otherwise we get a massive performance hit
  76. CGContextConcatCTM(gc, CGAffineTransformInvert(CGContextGetCTM(gc)));
  77. // We have to use clipping to partially display an image
  78. rect.origin.x = x;
  79. rect.origin.y = y;
  80. rect.size.width = w;
  81. rect.size.height = h;
  82. CGContextClipToRect(gc, rect);
  83. rect.origin.x = x - src_x;
  84. rect.origin.y = y - src_y;
  85. rect.size.width = width();
  86. rect.size.height = height();
  87. CGContextDrawImage(gc, rect, image);
  88. CGContextRestoreGState(gc);
  89. }