gfx/2d/MacIOSurface.cpp

branch
TOR_BUG_9701
changeset 15
b8a032363ba2
equal deleted inserted replaced
-1:000000000000 0:8c5c8df169de
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 // vim:set ts=2 sts=2 sw=2 et cin:
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6
7 #include "MacIOSurface.h"
8 #include <OpenGL/gl.h>
9 #include <QuartzCore/QuartzCore.h>
10 #include <dlfcn.h>
11 #include "mozilla/RefPtr.h"
12 #include "mozilla/Assertions.h"
13
14 using namespace mozilla;
15 // IOSurface signatures
16 #define IOSURFACE_FRAMEWORK_PATH \
17 "/System/Library/Frameworks/IOSurface.framework/IOSurface"
18 #define OPENGL_FRAMEWORK_PATH \
19 "/System/Library/Frameworks/OpenGL.framework/OpenGL"
20 #define COREGRAPHICS_FRAMEWORK_PATH \
21 "/System/Library/Frameworks/ApplicationServices.framework/Frameworks/CoreGraphics.framework/CoreGraphics"
22
23
24
25 #define GET_CONST(const_name) \
26 ((CFStringRef*) dlsym(sIOSurfaceFramework, const_name))
27 #define GET_IOSYM(dest,sym_name) \
28 (typeof(dest)) dlsym(sIOSurfaceFramework, sym_name)
29 #define GET_CGLSYM(dest,sym_name) \
30 (typeof(dest)) dlsym(sOpenGLFramework, sym_name)
31 #define GET_CGSYM(dest,sym_name) \
32 (typeof(dest)) dlsym(sCoreGraphicsFramework, sym_name)
33
34 MacIOSurfaceLib::LibraryUnloader MacIOSurfaceLib::sLibraryUnloader;
35 bool MacIOSurfaceLib::isLoaded = false;
36 void* MacIOSurfaceLib::sIOSurfaceFramework;
37 void* MacIOSurfaceLib::sOpenGLFramework;
38 void* MacIOSurfaceLib::sCoreGraphicsFramework;
39 IOSurfaceCreateFunc MacIOSurfaceLib::sCreate;
40 IOSurfaceGetIDFunc MacIOSurfaceLib::sGetID;
41 IOSurfaceLookupFunc MacIOSurfaceLib::sLookup;
42 IOSurfaceGetBaseAddressFunc MacIOSurfaceLib::sGetBaseAddress;
43 IOSurfaceGetWidthFunc MacIOSurfaceLib::sWidth;
44 IOSurfaceGetHeightFunc MacIOSurfaceLib::sHeight;
45 IOSurfaceGetBytesPerRowFunc MacIOSurfaceLib::sBytesPerRow;
46 IOSurfaceLockFunc MacIOSurfaceLib::sLock;
47 IOSurfaceUnlockFunc MacIOSurfaceLib::sUnlock;
48 CGLTexImageIOSurface2DFunc MacIOSurfaceLib::sTexImage;
49 IOSurfaceContextCreateFunc MacIOSurfaceLib::sIOSurfaceContextCreate;
50 IOSurfaceContextCreateImageFunc MacIOSurfaceLib::sIOSurfaceContextCreateImage;
51 IOSurfaceContextGetSurfaceFunc MacIOSurfaceLib::sIOSurfaceContextGetSurface;
52 unsigned int (*MacIOSurfaceLib::sCGContextGetTypePtr) (CGContextRef) = nullptr;
53
54 CFStringRef MacIOSurfaceLib::kPropWidth;
55 CFStringRef MacIOSurfaceLib::kPropHeight;
56 CFStringRef MacIOSurfaceLib::kPropBytesPerElem;
57 CFStringRef MacIOSurfaceLib::kPropBytesPerRow;
58 CFStringRef MacIOSurfaceLib::kPropIsGlobal;
59
60 bool MacIOSurfaceLib::isInit() {
61 // Guard against trying to reload the library
62 // if it is not available.
63 if (!isLoaded)
64 LoadLibrary();
65 MOZ_ASSERT(sIOSurfaceFramework);
66 return sIOSurfaceFramework;
67 }
68
69 IOSurfacePtr MacIOSurfaceLib::IOSurfaceCreate(CFDictionaryRef properties) {
70 return sCreate(properties);
71 }
72
73 IOSurfacePtr MacIOSurfaceLib::IOSurfaceLookup(IOSurfaceID aIOSurfaceID) {
74 return sLookup(aIOSurfaceID);
75 }
76
77 IOSurfaceID MacIOSurfaceLib::IOSurfaceGetID(IOSurfacePtr aIOSurfacePtr) {
78 return sGetID(aIOSurfacePtr);
79 }
80
81 void* MacIOSurfaceLib::IOSurfaceGetBaseAddress(IOSurfacePtr aIOSurfacePtr) {
82 return sGetBaseAddress(aIOSurfacePtr);
83 }
84
85 size_t MacIOSurfaceLib::IOSurfaceGetWidth(IOSurfacePtr aIOSurfacePtr) {
86 return sWidth(aIOSurfacePtr);
87 }
88
89 size_t MacIOSurfaceLib::IOSurfaceGetHeight(IOSurfacePtr aIOSurfacePtr) {
90 return sHeight(aIOSurfacePtr);
91 }
92
93 size_t MacIOSurfaceLib::IOSurfaceGetBytesPerRow(IOSurfacePtr aIOSurfacePtr) {
94 return sBytesPerRow(aIOSurfacePtr);
95 }
96
97 IOReturn MacIOSurfaceLib::IOSurfaceLock(IOSurfacePtr aIOSurfacePtr,
98 uint32_t options, uint32_t *seed) {
99 return sLock(aIOSurfacePtr, options, seed);
100 }
101
102 IOReturn MacIOSurfaceLib::IOSurfaceUnlock(IOSurfacePtr aIOSurfacePtr,
103 uint32_t options, uint32_t *seed) {
104 return sUnlock(aIOSurfacePtr, options, seed);
105 }
106
107 CGLError MacIOSurfaceLib::CGLTexImageIOSurface2D(CGLContextObj ctxt,
108 GLenum target, GLenum internalFormat,
109 GLsizei width, GLsizei height,
110 GLenum format, GLenum type,
111 IOSurfacePtr ioSurface, GLuint plane) {
112 return sTexImage(ctxt, target, internalFormat, width, height,
113 format, type, ioSurface, plane);
114 }
115
116 CGContextRef MacIOSurfaceLib::IOSurfaceContextCreate(IOSurfacePtr aIOSurfacePtr,
117 unsigned aWidth, unsigned aHeight,
118 unsigned aBitsPerComponent, unsigned aBytes,
119 CGColorSpaceRef aColorSpace, CGBitmapInfo bitmapInfo) {
120 if (!sIOSurfaceContextCreate)
121 return nullptr;
122 return sIOSurfaceContextCreate(aIOSurfacePtr, aWidth, aHeight, aBitsPerComponent, aBytes, aColorSpace, bitmapInfo);
123 }
124
125 CGImageRef MacIOSurfaceLib::IOSurfaceContextCreateImage(CGContextRef aContext) {
126 if (!sIOSurfaceContextCreateImage)
127 return nullptr;
128 return sIOSurfaceContextCreateImage(aContext);
129 }
130
131 IOSurfacePtr MacIOSurfaceLib::IOSurfaceContextGetSurface(CGContextRef aContext) {
132 if (!sIOSurfaceContextGetSurface)
133 return nullptr;
134 return sIOSurfaceContextGetSurface(aContext);
135 }
136
137 CFStringRef MacIOSurfaceLib::GetIOConst(const char* symbole) {
138 CFStringRef *address = (CFStringRef*)dlsym(sIOSurfaceFramework, symbole);
139 if (!address)
140 return nullptr;
141
142 return *address;
143 }
144
145 void MacIOSurfaceLib::LoadLibrary() {
146 if (isLoaded) {
147 return;
148 }
149 isLoaded = true;
150 sIOSurfaceFramework = dlopen(IOSURFACE_FRAMEWORK_PATH,
151 RTLD_LAZY | RTLD_LOCAL);
152 sOpenGLFramework = dlopen(OPENGL_FRAMEWORK_PATH,
153 RTLD_LAZY | RTLD_LOCAL);
154
155 sCoreGraphicsFramework = dlopen(COREGRAPHICS_FRAMEWORK_PATH,
156 RTLD_LAZY | RTLD_LOCAL);
157 if (!sIOSurfaceFramework || !sOpenGLFramework || !sCoreGraphicsFramework) {
158 if (sIOSurfaceFramework)
159 dlclose(sIOSurfaceFramework);
160 if (sOpenGLFramework)
161 dlclose(sOpenGLFramework);
162 if (sCoreGraphicsFramework)
163 dlclose(sCoreGraphicsFramework);
164 sIOSurfaceFramework = nullptr;
165 sOpenGLFramework = nullptr;
166 sCoreGraphicsFramework = nullptr;
167 return;
168 }
169
170 kPropWidth = GetIOConst("kIOSurfaceWidth");
171 kPropHeight = GetIOConst("kIOSurfaceHeight");
172 kPropBytesPerElem = GetIOConst("kIOSurfaceBytesPerElement");
173 kPropBytesPerRow = GetIOConst("kIOSurfaceBytesPerRow");
174 kPropIsGlobal = GetIOConst("kIOSurfaceIsGlobal");
175 sCreate = GET_IOSYM(sCreate, "IOSurfaceCreate");
176 sGetID = GET_IOSYM(sGetID, "IOSurfaceGetID");
177 sWidth = GET_IOSYM(sWidth, "IOSurfaceGetWidth");
178 sHeight = GET_IOSYM(sHeight, "IOSurfaceGetHeight");
179 sBytesPerRow = GET_IOSYM(sBytesPerRow, "IOSurfaceGetBytesPerRow");
180 sLookup = GET_IOSYM(sLookup, "IOSurfaceLookup");
181 sLock = GET_IOSYM(sLock, "IOSurfaceLock");
182 sUnlock = GET_IOSYM(sUnlock, "IOSurfaceUnlock");
183 sGetBaseAddress = GET_IOSYM(sGetBaseAddress, "IOSurfaceGetBaseAddress");
184 sTexImage = GET_CGLSYM(sTexImage, "CGLTexImageIOSurface2D");
185 sCGContextGetTypePtr = (unsigned int (*)(CGContext*))dlsym(RTLD_DEFAULT, "CGContextGetType");
186
187 // Optional symbols
188 sIOSurfaceContextCreate = GET_CGSYM(sIOSurfaceContextCreate, "CGIOSurfaceContextCreate");
189 sIOSurfaceContextCreateImage = GET_CGSYM(sIOSurfaceContextCreateImage, "CGIOSurfaceContextCreateImage");
190 sIOSurfaceContextGetSurface = GET_CGSYM(sIOSurfaceContextGetSurface, "CGIOSurfaceContextGetSurface");
191
192 if (!sCreate || !sGetID || !sLookup || !sTexImage || !sGetBaseAddress ||
193 !kPropWidth || !kPropHeight || !kPropBytesPerElem || !kPropIsGlobal ||
194 !sLock || !sUnlock || !sWidth || !sHeight || !kPropBytesPerRow ||
195 !sBytesPerRow) {
196 CloseLibrary();
197 }
198 }
199
200 void MacIOSurfaceLib::CloseLibrary() {
201 if (sIOSurfaceFramework) {
202 dlclose(sIOSurfaceFramework);
203 }
204 if (sOpenGLFramework) {
205 dlclose(sOpenGLFramework);
206 }
207 sIOSurfaceFramework = nullptr;
208 sOpenGLFramework = nullptr;
209 }
210
211 MacIOSurface::~MacIOSurface() {
212 CFRelease(mIOSurfacePtr);
213 }
214
215 TemporaryRef<MacIOSurface> MacIOSurface::CreateIOSurface(int aWidth, int aHeight,
216 double aContentsScaleFactor,
217 bool aHasAlpha) {
218 if (!MacIOSurfaceLib::isInit() || aContentsScaleFactor <= 0)
219 return nullptr;
220
221 CFMutableDictionaryRef props = ::CFDictionaryCreateMutable(
222 kCFAllocatorDefault, 4,
223 &kCFTypeDictionaryKeyCallBacks,
224 &kCFTypeDictionaryValueCallBacks);
225 if (!props)
226 return nullptr;
227
228 int32_t bytesPerElem = 4;
229 size_t intScaleFactor = ceil(aContentsScaleFactor);
230 aWidth *= intScaleFactor;
231 aHeight *= intScaleFactor;
232 CFNumberRef cfWidth = ::CFNumberCreate(nullptr, kCFNumberSInt32Type, &aWidth);
233 CFNumberRef cfHeight = ::CFNumberCreate(nullptr, kCFNumberSInt32Type, &aHeight);
234 CFNumberRef cfBytesPerElem = ::CFNumberCreate(nullptr, kCFNumberSInt32Type, &bytesPerElem);
235 ::CFDictionaryAddValue(props, MacIOSurfaceLib::kPropWidth,
236 cfWidth);
237 ::CFRelease(cfWidth);
238 ::CFDictionaryAddValue(props, MacIOSurfaceLib::kPropHeight,
239 cfHeight);
240 ::CFRelease(cfHeight);
241 ::CFDictionaryAddValue(props, MacIOSurfaceLib::kPropBytesPerElem,
242 cfBytesPerElem);
243 ::CFRelease(cfBytesPerElem);
244 ::CFDictionaryAddValue(props, MacIOSurfaceLib::kPropIsGlobal,
245 kCFBooleanTrue);
246
247 IOSurfacePtr surfaceRef = MacIOSurfaceLib::IOSurfaceCreate(props);
248 ::CFRelease(props);
249
250 if (!surfaceRef)
251 return nullptr;
252
253 RefPtr<MacIOSurface> ioSurface = new MacIOSurface(surfaceRef, aContentsScaleFactor, aHasAlpha);
254 if (!ioSurface) {
255 ::CFRelease(surfaceRef);
256 return nullptr;
257 }
258
259 return ioSurface.forget();
260 }
261
262 TemporaryRef<MacIOSurface> MacIOSurface::LookupSurface(IOSurfaceID aIOSurfaceID,
263 double aContentsScaleFactor,
264 bool aHasAlpha) {
265 if (!MacIOSurfaceLib::isInit() || aContentsScaleFactor <= 0)
266 return nullptr;
267
268 IOSurfacePtr surfaceRef = MacIOSurfaceLib::IOSurfaceLookup(aIOSurfaceID);
269 if (!surfaceRef)
270 return nullptr;
271
272 RefPtr<MacIOSurface> ioSurface = new MacIOSurface(surfaceRef, aContentsScaleFactor, aHasAlpha);
273 if (!ioSurface) {
274 ::CFRelease(surfaceRef);
275 return nullptr;
276 }
277 return ioSurface.forget();
278 }
279
280 IOSurfaceID MacIOSurface::GetIOSurfaceID() {
281 return MacIOSurfaceLib::IOSurfaceGetID(mIOSurfacePtr);
282 }
283
284 void* MacIOSurface::GetBaseAddress() {
285 return MacIOSurfaceLib::IOSurfaceGetBaseAddress(mIOSurfacePtr);
286 }
287
288 size_t MacIOSurface::GetWidth() {
289 size_t intScaleFactor = ceil(mContentsScaleFactor);
290 return GetDevicePixelWidth() / intScaleFactor;
291 }
292
293 size_t MacIOSurface::GetHeight() {
294 size_t intScaleFactor = ceil(mContentsScaleFactor);
295 return GetDevicePixelHeight() / intScaleFactor;
296 }
297
298 size_t MacIOSurface::GetDevicePixelWidth() {
299 return MacIOSurfaceLib::IOSurfaceGetWidth(mIOSurfacePtr);
300 }
301
302 size_t MacIOSurface::GetDevicePixelHeight() {
303 return MacIOSurfaceLib::IOSurfaceGetHeight(mIOSurfacePtr);
304 }
305
306 size_t MacIOSurface::GetBytesPerRow() {
307 return MacIOSurfaceLib::IOSurfaceGetBytesPerRow(mIOSurfacePtr);
308 }
309
310 #define READ_ONLY 0x1
311 void MacIOSurface::Lock() {
312 MacIOSurfaceLib::IOSurfaceLock(mIOSurfacePtr, READ_ONLY, nullptr);
313 }
314
315 void MacIOSurface::Unlock() {
316 MacIOSurfaceLib::IOSurfaceUnlock(mIOSurfacePtr, READ_ONLY, nullptr);
317 }
318
319 #include "SourceSurfaceRawData.h"
320 using mozilla::gfx::SourceSurface;
321 using mozilla::gfx::SourceSurfaceRawData;
322 using mozilla::gfx::IntSize;
323 using mozilla::gfx::SurfaceFormat;
324
325 TemporaryRef<SourceSurface>
326 MacIOSurface::GetAsSurface() {
327 Lock();
328 size_t bytesPerRow = GetBytesPerRow();
329 size_t ioWidth = GetDevicePixelWidth();
330 size_t ioHeight = GetDevicePixelHeight();
331
332 unsigned char* ioData = (unsigned char*)GetBaseAddress();
333 unsigned char* dataCpy = (unsigned char*)malloc(bytesPerRow*ioHeight);
334 for (size_t i = 0; i < ioHeight; i++) {
335 memcpy(dataCpy + i * bytesPerRow,
336 ioData + i * bytesPerRow, ioWidth * 4);
337 }
338
339 Unlock();
340
341 SurfaceFormat format = HasAlpha() ? mozilla::gfx::SurfaceFormat::B8G8R8A8 :
342 mozilla::gfx::SurfaceFormat::B8G8R8X8;
343
344 RefPtr<SourceSurfaceRawData> surf = new SourceSurfaceRawData();
345 surf->InitWrappingData(dataCpy, IntSize(ioWidth, ioHeight), bytesPerRow, format, true);
346
347 return surf.forget();
348 }
349
350 CGLError
351 MacIOSurface::CGLTexImageIOSurface2D(CGLContextObj ctx)
352 {
353 return MacIOSurfaceLib::CGLTexImageIOSurface2D(ctx,
354 GL_TEXTURE_RECTANGLE_ARB,
355 HasAlpha() ? GL_RGBA : GL_RGB,
356 GetDevicePixelWidth(),
357 GetDevicePixelHeight(),
358 GL_BGRA,
359 GL_UNSIGNED_INT_8_8_8_8_REV,
360 mIOSurfacePtr, 0);
361 }
362
363 static
364 CGColorSpaceRef CreateSystemColorSpace() {
365 CGColorSpaceRef cspace = ::CGDisplayCopyColorSpace(::CGMainDisplayID());
366 if (!cspace) {
367 cspace = ::CGColorSpaceCreateDeviceRGB();
368 }
369 return cspace;
370 }
371
372 CGContextRef MacIOSurface::CreateIOSurfaceContext() {
373 CGColorSpaceRef cspace = CreateSystemColorSpace();
374 CGContextRef ref = MacIOSurfaceLib::IOSurfaceContextCreate(mIOSurfacePtr,
375 GetDevicePixelWidth(),
376 GetDevicePixelHeight(),
377 8, 32, cspace, 0x2002);
378 ::CGColorSpaceRelease(cspace);
379 return ref;
380 }
381
382 CGImageRef MacIOSurface::CreateImageFromIOSurfaceContext(CGContextRef aContext) {
383 if (!MacIOSurfaceLib::isInit())
384 return nullptr;
385
386 return MacIOSurfaceLib::IOSurfaceContextCreateImage(aContext);
387 }
388
389 TemporaryRef<MacIOSurface> MacIOSurface::IOSurfaceContextGetSurface(CGContextRef aContext,
390 double aContentsScaleFactor,
391 bool aHasAlpha) {
392 if (!MacIOSurfaceLib::isInit() || aContentsScaleFactor <= 0)
393 return nullptr;
394
395 IOSurfacePtr surfaceRef = MacIOSurfaceLib::IOSurfaceContextGetSurface(aContext);
396 if (!surfaceRef)
397 return nullptr;
398
399 // Retain the IOSurface because MacIOSurface will release it
400 CFRetain(surfaceRef);
401
402 RefPtr<MacIOSurface> ioSurface = new MacIOSurface(surfaceRef, aContentsScaleFactor, aHasAlpha);
403 if (!ioSurface) {
404 ::CFRelease(surfaceRef);
405 return nullptr;
406 }
407 return ioSurface.forget();
408 }
409
410
411 CGContextType GetContextType(CGContextRef ref)
412 {
413 if (!MacIOSurfaceLib::isInit() || !MacIOSurfaceLib::sCGContextGetTypePtr)
414 return CG_CONTEXT_TYPE_UNKNOWN;
415
416 unsigned int type = MacIOSurfaceLib::sCGContextGetTypePtr(ref);
417 if (type == CG_CONTEXT_TYPE_BITMAP) {
418 return CG_CONTEXT_TYPE_BITMAP;
419 } else if (type == CG_CONTEXT_TYPE_IOSURFACE) {
420 return CG_CONTEXT_TYPE_IOSURFACE;
421 } else {
422 return CG_CONTEXT_TYPE_UNKNOWN;
423 }
424 }
425
426

mercurial