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 /* ***** BEGIN LICENSE BLOCK *****
4 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
6 * The contents of this file are subject to the Mozilla Public License Version
7 * 1.1 (the "License"); you may not use this file except in compliance with
8 * the License. You may obtain a copy of the License at
9 * http://www.mozilla.org/MPL/
11 * Software distributed under the License is distributed on an "AS IS" basis,
12 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
13 * for the specific language governing rights and limitations under the
16 * The Original Code is Mozilla.org code.
18 * The Initial Developer of the Original Code is
19 * Mozilla Corporation.
20 * Portions created by the Initial Developer are Copyright (C) 2008
21 * the Initial Developer. All Rights Reserved.
24 * Benoit Girard <b56girard@gmail.com>
26 * Alternatively, the contents of this file may be used under the terms of
27 * either of the GNU General Public License Version 2 or later (the "GPL"),
28 * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
29 * in which case the provisions of the GPL or the LGPL are applicable instead
30 * of those above. If you wish to allow use of your version of this file only
31 * under the terms of either the GPL or the LGPL, and not to allow others to
32 * use your version of this file under the terms of the MPL, indicate your
33 * decision by deleting the provisions above and replace them with the notice
34 * and other provisions required by the GPL or the LGPL. If you do not delete
35 * the provisions above, a recipient may use your version of this file under
36 * the terms of any one of the MPL, the GPL or the LGPL.
38 * ***** END LICENSE BLOCK ***** */
40 #include "nsCoreAnimationSupport.h"
43 #import <QuartzCore/QuartzCore.h>
46 #define IOSURFACE_FRAMEWORK_PATH \
47 "/System/Library/Frameworks/IOSurface.framework/IOSurface"
48 #define OPENGL_FRAMEWORK_PATH \
49 "/System/Library/Frameworks/OpenGL.framework/OpenGL"
52 // IOSurface signatures
53 typedef CFTypeRef IOSurfacePtr;
54 typedef IOSurfacePtr (*IOSurfaceCreateFunc) (CFDictionaryRef properties);
55 typedef IOSurfacePtr (*IOSurfaceLookupFunc) (uint32_t io_surface_id);
56 typedef IOSurfaceID (*IOSurfaceGetIDFunc) (CFTypeRef io_surface);
57 typedef IOReturn (*IOSurfaceLockFunc) (CFTypeRef io_surface,
60 typedef IOReturn (*IOSurfaceUnlockFunc) (CFTypeRef io_surface,
63 typedef void* (*IOSurfaceGetBaseAddressFunc) (CFTypeRef io_surface);
64 typedef size_t (*IOSurfaceGetWidthFunc) (IOSurfacePtr io_surface);
65 typedef size_t (*IOSurfaceGetHeightFunc) (IOSurfacePtr io_surface);
66 typedef size_t (*IOSurfaceGetBytesPerRowFunc) (IOSurfacePtr io_surface);
67 typedef CGLError (*CGLTexImageIOSurface2DFunc) (CGLContextObj ctxt,
68 GLenum target, GLenum internalFormat,
69 GLsizei width, GLsizei height,
70 GLenum format, GLenum type,
71 IOSurfacePtr ioSurface, GLuint plane);
73 #define GET_CONST(const_name) \
74 ((CFStringRef*) dlsym(sIOSurfaceFramework, const_name))
75 #define GET_IOSYM(dest,sym_name) \
76 (typeof(dest)) dlsym(sIOSurfaceFramework, sym_name)
77 #define GET_CGLSYM(dest,sym_name) \
78 (typeof(dest)) dlsym(sOpenGLFramework, sym_name)
80 class nsIOSurfaceLib: public nsIOSurface {
82 static void *sIOSurfaceFramework;
83 static void *sOpenGLFramework;
85 static IOSurfaceCreateFunc sCreate;
86 static IOSurfaceGetIDFunc sGetID;
87 static IOSurfaceLookupFunc sLookup;
88 static IOSurfaceGetBaseAddressFunc sGetBaseAddress;
89 static IOSurfaceLockFunc sLock;
90 static IOSurfaceUnlockFunc sUnlock;
91 static IOSurfaceGetWidthFunc sWidth;
92 static IOSurfaceGetHeightFunc sHeight;
93 static IOSurfaceGetBytesPerRowFunc sBytesPerRow;
94 static CGLTexImageIOSurface2DFunc sTexImage;
95 static CFStringRef kPropWidth;
96 static CFStringRef kPropHeight;
97 static CFStringRef kPropBytesPerElem;
98 static CFStringRef kPropBytesPerRow;
99 static CFStringRef kPropIsGlobal;
101 static bool isInit();
102 static CFStringRef GetIOConst(const char* symbole);
103 static IOSurfacePtr IOSurfaceCreate(CFDictionaryRef properties);
104 static IOSurfacePtr IOSurfaceLookup(IOSurfaceID aIOSurfaceID);
105 static IOSurfaceID IOSurfaceGetID(IOSurfacePtr aIOSurfacePtr);
106 static void *IOSurfaceGetBaseAddress(IOSurfacePtr aIOSurfacePtr);
107 static size_t IOSurfaceGetWidth(IOSurfacePtr aIOSurfacePtr);
108 static size_t IOSurfaceGetHeight(IOSurfacePtr aIOSurfacePtr);
109 static size_t IOSurfaceGetBytesPerRow(IOSurfacePtr aIOSurfacePtr);
110 static IOReturn IOSurfaceLock(IOSurfacePtr aIOSurfacePtr,
111 uint32_t options, uint32_t *seed);
112 static IOReturn IOSurfaceUnlock(IOSurfacePtr aIOSurfacePtr,
113 uint32_t options, uint32_t *seed);
114 static CGLError CGLTexImageIOSurface2D(CGLContextObj ctxt,
115 GLenum target, GLenum internalFormat,
116 GLsizei width, GLsizei height,
117 GLenum format, GLenum type,
118 IOSurfacePtr ioSurface, GLuint plane);
119 static void LoadLibrary();
120 static void CloseLibrary();
122 // Static deconstructor
123 static class LibraryUnloader {
131 nsIOSurfaceLib::LibraryUnloader nsIOSurfaceLib::sLibraryUnloader;
132 bool nsIOSurfaceLib::isLoaded = false;
133 void* nsIOSurfaceLib::sIOSurfaceFramework;
134 void* nsIOSurfaceLib::sOpenGLFramework;
135 IOSurfaceCreateFunc nsIOSurfaceLib::sCreate;
136 IOSurfaceGetIDFunc nsIOSurfaceLib::sGetID;
137 IOSurfaceLookupFunc nsIOSurfaceLib::sLookup;
138 IOSurfaceGetBaseAddressFunc nsIOSurfaceLib::sGetBaseAddress;
139 IOSurfaceGetHeightFunc nsIOSurfaceLib::sWidth;
140 IOSurfaceGetWidthFunc nsIOSurfaceLib::sHeight;
141 IOSurfaceGetBytesPerRowFunc nsIOSurfaceLib::sBytesPerRow;
142 IOSurfaceLockFunc nsIOSurfaceLib::sLock;
143 IOSurfaceUnlockFunc nsIOSurfaceLib::sUnlock;
144 CGLTexImageIOSurface2DFunc nsIOSurfaceLib::sTexImage;
145 CFStringRef nsIOSurfaceLib::kPropWidth;
146 CFStringRef nsIOSurfaceLib::kPropHeight;
147 CFStringRef nsIOSurfaceLib::kPropBytesPerElem;
148 CFStringRef nsIOSurfaceLib::kPropBytesPerRow;
149 CFStringRef nsIOSurfaceLib::kPropIsGlobal;
151 bool nsIOSurfaceLib::isInit() {
152 // Guard against trying to reload the library
153 // if it is not available.
156 if (!sIOSurfaceFramework) {
157 NS_ERROR("nsIOSurfaceLib failed to initialize");
159 return sIOSurfaceFramework;
162 IOSurfacePtr nsIOSurfaceLib::IOSurfaceCreate(CFDictionaryRef properties) {
163 return sCreate(properties);
166 IOSurfacePtr nsIOSurfaceLib::IOSurfaceLookup(IOSurfaceID aIOSurfaceID) {
167 return sLookup(aIOSurfaceID);
170 IOSurfaceID nsIOSurfaceLib::IOSurfaceGetID(IOSurfacePtr aIOSurfacePtr) {
171 return sGetID(aIOSurfacePtr);
174 void* nsIOSurfaceLib::IOSurfaceGetBaseAddress(IOSurfacePtr aIOSurfacePtr) {
175 return sGetBaseAddress(aIOSurfacePtr);
178 size_t nsIOSurfaceLib::IOSurfaceGetWidth(IOSurfacePtr aIOSurfacePtr) {
179 return sWidth(aIOSurfacePtr);
182 size_t nsIOSurfaceLib::IOSurfaceGetHeight(IOSurfacePtr aIOSurfacePtr) {
183 return sHeight(aIOSurfacePtr);
186 size_t nsIOSurfaceLib::IOSurfaceGetBytesPerRow(IOSurfacePtr aIOSurfacePtr) {
187 return sBytesPerRow(aIOSurfacePtr);
190 IOReturn nsIOSurfaceLib::IOSurfaceLock(IOSurfacePtr aIOSurfacePtr,
191 uint32_t options, uint32_t *seed) {
192 return sLock(aIOSurfacePtr, options, seed);
195 IOReturn nsIOSurfaceLib::IOSurfaceUnlock(IOSurfacePtr aIOSurfacePtr,
196 uint32_t options, uint32_t *seed) {
197 return sUnlock(aIOSurfacePtr, options, seed);
200 CGLError nsIOSurfaceLib::CGLTexImageIOSurface2D(CGLContextObj ctxt,
201 GLenum target, GLenum internalFormat,
202 GLsizei width, GLsizei height,
203 GLenum format, GLenum type,
204 IOSurfacePtr ioSurface, GLuint plane) {
205 return sTexImage(ctxt, target, internalFormat, width, height,
206 format, type, ioSurface, plane);
209 CFStringRef nsIOSurfaceLib::GetIOConst(const char* symbole) {
210 CFStringRef *address = (CFStringRef*)dlsym(sIOSurfaceFramework, symbole);
217 void nsIOSurfaceLib::LoadLibrary() {
222 sIOSurfaceFramework = dlopen(IOSURFACE_FRAMEWORK_PATH,
223 RTLD_LAZY | RTLD_LOCAL);
224 sOpenGLFramework = dlopen(OPENGL_FRAMEWORK_PATH,
225 RTLD_LAZY | RTLD_LOCAL);
226 if (!sIOSurfaceFramework) {
229 if (!sOpenGLFramework) {
230 dlclose(sIOSurfaceFramework);
231 sIOSurfaceFramework = nsnull;
235 kPropWidth = GetIOConst("kIOSurfaceWidth");
236 kPropHeight = GetIOConst("kIOSurfaceHeight");
237 kPropBytesPerElem = GetIOConst("kIOSurfaceBytesPerElement");
238 kPropBytesPerRow = GetIOConst("kIOSurfaceBytesPerRow");
239 kPropIsGlobal = GetIOConst("kIOSurfaceIsGlobal");
240 sCreate = GET_IOSYM(sCreate, "IOSurfaceCreate");
241 sGetID = GET_IOSYM(sGetID, "IOSurfaceGetID");
242 sWidth = GET_IOSYM(sWidth, "IOSurfaceGetWidth");
243 sHeight = GET_IOSYM(sHeight, "IOSurfaceGetHeight");
244 sBytesPerRow = GET_IOSYM(sBytesPerRow, "IOSurfaceGetBytesPerRow");
245 sLookup = GET_IOSYM(sLookup, "IOSurfaceLookup");
246 sLock = GET_IOSYM(sLock, "IOSurfaceLock");
247 sUnlock = GET_IOSYM(sUnlock, "IOSurfaceUnlock");
248 sGetBaseAddress = GET_IOSYM(sGetBaseAddress, "IOSurfaceGetBaseAddress");
249 sTexImage = GET_CGLSYM(sTexImage, "CGLTexImageIOSurface2D");
251 if (!sCreate || !sGetID || !sLookup || !sTexImage || !sGetBaseAddress ||
252 !kPropWidth || !kPropHeight || !kPropBytesPerElem || !kPropIsGlobal ||
253 !sLock || !sUnlock || !sWidth || !sHeight || !kPropBytesPerRow ||
259 void nsIOSurfaceLib::CloseLibrary() {
260 if (sIOSurfaceFramework) {
261 dlclose(sIOSurfaceFramework);
263 if (sOpenGLFramework) {
264 dlclose(sOpenGLFramework);
266 sIOSurfaceFramework = nsnull;
267 sOpenGLFramework = nsnull;
270 nsIOSurface* nsIOSurface::CreateIOSurface(int aWidth, int aHeight) {
271 if (!nsIOSurfaceLib::isInit())
274 CFMutableDictionaryRef props = ::CFDictionaryCreateMutable(
275 kCFAllocatorDefault, 4,
276 &kCFTypeDictionaryKeyCallBacks,
277 &kCFTypeDictionaryValueCallBacks);
281 int32_t bytesPerElem = 4;
282 CFNumberRef cfWidth = ::CFNumberCreate(NULL, kCFNumberSInt32Type, &aWidth);
283 CFNumberRef cfHeight = ::CFNumberCreate(NULL, kCFNumberSInt32Type, &aHeight);
284 CFNumberRef cfBytesPerElem = ::CFNumberCreate(NULL, kCFNumberSInt32Type, &bytesPerElem);
285 ::CFDictionaryAddValue(props, nsIOSurfaceLib::kPropWidth,
287 ::CFRelease(cfWidth);
288 ::CFDictionaryAddValue(props, nsIOSurfaceLib::kPropHeight,
290 ::CFRelease(cfHeight);
291 ::CFDictionaryAddValue(props, nsIOSurfaceLib::kPropBytesPerElem,
293 ::CFRelease(cfBytesPerElem);
294 ::CFDictionaryAddValue(props, nsIOSurfaceLib::kPropIsGlobal,
297 IOSurfacePtr surfaceRef = nsIOSurfaceLib::IOSurfaceCreate(props);
303 nsIOSurface* ioSurface = new nsIOSurface(surfaceRef);
305 ::CFRelease(surfaceRef);
312 nsIOSurface* nsIOSurface::LookupSurface(IOSurfaceID aIOSurfaceID) {
313 if (!nsIOSurfaceLib::isInit())
316 IOSurfacePtr surfaceRef = nsIOSurfaceLib::IOSurfaceLookup(aIOSurfaceID);
319 // IOSurfaceLookup does not retain the object for us,
320 // we want IOSurfacePtr to remain for the lifetime of
322 CFRetain(surfaceRef);
324 nsIOSurface* ioSurface = new nsIOSurface(surfaceRef);
326 ::CFRelease(ioSurface);
332 IOSurfaceID nsIOSurface::GetIOSurfaceID() {
333 return nsIOSurfaceLib::IOSurfaceGetID(mIOSurfacePtr);
336 void* nsIOSurface::GetBaseAddress() {
337 return nsIOSurfaceLib::IOSurfaceGetBaseAddress(mIOSurfacePtr);
340 size_t nsIOSurface::GetWidth() {
341 return nsIOSurfaceLib::IOSurfaceGetWidth(mIOSurfacePtr);
344 size_t nsIOSurface::GetHeight() {
345 return nsIOSurfaceLib::IOSurfaceGetHeight(mIOSurfacePtr);
348 size_t nsIOSurface::GetBytesPerRow() {
349 return nsIOSurfaceLib::IOSurfaceGetBytesPerRow(mIOSurfacePtr);
352 #define READ_ONLY 0x1
353 void nsIOSurface::Lock() {
354 nsIOSurfaceLib::IOSurfaceLock(mIOSurfacePtr, READ_ONLY, NULL);
357 void nsIOSurface::Unlock() {
358 nsIOSurfaceLib::IOSurfaceUnlock(mIOSurfacePtr, READ_ONLY, NULL);
361 nsCARenderer::~nsCARenderer() {
365 CGColorSpaceRef CreateSystemColorSpace() {
366 CMProfileRef system_profile = nsnull;
367 CGColorSpaceRef cspace = nsnull;
369 if (::CMGetSystemProfile(&system_profile) == noErr) {
370 // Create a colorspace with the systems profile
371 cspace = ::CGColorSpaceCreateWithPlatformColorSpace(system_profile);
372 ::CMCloseProfile(system_profile);
374 // Default to generic
375 cspace = ::CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB);
381 void cgdata_release_callback(void *aCGData, const void *data, size_t size) {
387 void nsCARenderer::Destroy() {
389 CARenderer* caRenderer = (CARenderer*)mCARenderer;
391 // Explicitly remove the layer from the renderer
392 // otherwise it does not always happen right away.
393 caRenderer.layer = nsnull;
394 [caRenderer release];
397 ::CGLDestroyPBuffer((CGLPBufferObj)mPixelBuffer);
399 if (mOpenGLContext) {
400 if (mFBO || mIOTexture) {
401 // Release these resources with the context that allocated them
402 CGLContextObj oldContext = ::CGLGetCurrentContext();
403 ::CGLSetCurrentContext(mOpenGLContext);
406 ::glDeleteTextures(1, &mIOTexture);
409 ::glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
410 ::glDeleteFramebuffersEXT(1, &mFBO);
414 ::CGLSetCurrentContext(oldContext);
416 ::CGLDestroyContext((CGLContextObj)mOpenGLContext);
419 ::CGImageRelease(mCGImage);
424 // mCGData is deallocated by cgdata_release_callback
427 mPixelBuffer = nsnull;
428 mOpenGLContext = nsnull;
435 nsresult nsCARenderer::SetupRenderer(void *aCALayer, int aWidth, int aHeight) {
436 if (aWidth == 0 || aHeight == 0)
437 return NS_ERROR_FAILURE;
439 CALayer* layer = (CALayer*)aCALayer;
440 CARenderer* caRenderer = nsnull;
442 CGLPixelFormatAttribute attributes[] = {
446 kCGLPFADepthSize, (CGLPixelFormatAttribute)24,
447 (CGLPixelFormatAttribute)0
451 CGLError result = ::CGLCreatePBuffer(aWidth, aHeight,
452 GL_TEXTURE_2D, GL_RGBA, 0, &mPixelBuffer);
453 if (result != kCGLNoError) {
455 return NS_ERROR_FAILURE;
460 CGLPixelFormatObj format;
461 if (::CGLChoosePixelFormat(attributes, &format, &screen) != kCGLNoError) {
463 return NS_ERROR_FAILURE;
466 if (::CGLCreateContext(format, nsnull, &mOpenGLContext) != kCGLNoError) {
468 return NS_ERROR_FAILURE;
470 ::CGLDestroyPixelFormat(format);
472 caRenderer = [[CARenderer rendererWithCGLContext:mOpenGLContext
473 options:nil] retain];
474 mCARenderer = caRenderer;
475 if (caRenderer == nil) {
477 return NS_ERROR_FAILURE;
479 [layer setBounds:CGRectMake(0, 0, aWidth, aHeight)];
480 [layer setPosition:CGPointMake(aWidth/2.0, aHeight/2.0)];
481 caRenderer.layer = layer;
482 caRenderer.bounds = CGRectMake(0, 0, aWidth, aHeight);
484 // We either target rendering to a CGImage or IOSurface.
486 mCGData = malloc(aWidth*aHeight*4);
490 memset(mCGData, 0, aWidth*aHeight*4);
492 CGDataProviderRef dataProvider = nsnull;
493 dataProvider = ::CGDataProviderCreateWithData(mCGData,
494 mCGData, aHeight*aWidth*4,
495 cgdata_release_callback);
497 cgdata_release_callback(mCGData, mCGData, aHeight*aWidth*4);
499 return NS_ERROR_FAILURE;
502 CGColorSpaceRef colorSpace = CreateSystemColorSpace();
504 mCGImage = ::CGImageCreate(aWidth, aHeight, 8, 32, aWidth * 4, colorSpace,
505 kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Host,
506 dataProvider, NULL, true, kCGRenderingIntentDefault);
508 ::CGDataProviderRelease(dataProvider);
510 ::CGColorSpaceRelease(colorSpace);
514 return NS_ERROR_FAILURE;
517 CGLContextObj oldContext = ::CGLGetCurrentContext();
518 ::CGLSetCurrentContext(mOpenGLContext);
520 // Create the IOSurface mapped texture.
521 ::glGenTextures(1, &mIOTexture);
522 ::glBindTexture(GL_TEXTURE_RECTANGLE_ARB, mIOTexture);
523 ::glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
524 ::glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
525 nsIOSurfaceLib::CGLTexImageIOSurface2D(mOpenGLContext, GL_TEXTURE_RECTANGLE_ARB,
526 GL_RGBA, aWidth, aHeight,
527 GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV,
528 mIOSurface->mIOSurfacePtr, 0);
529 ::glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0);
532 ::glGenFramebuffersEXT(1, &mFBO);
533 ::glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, mFBO);
534 ::glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
535 GL_TEXTURE_RECTANGLE_ARB, mIOTexture, 0);
537 // Make sure that the Framebuffer configuration is supported on the client machine
539 fboStatus = ::glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
540 if (fboStatus != GL_FRAMEBUFFER_COMPLETE_EXT) {
541 NS_ERROR("FBO not supported");
543 ::CGLSetCurrentContext(oldContext);
545 return NS_ERROR_FAILURE;
549 ::CGLSetCurrentContext(oldContext);
552 CGLContextObj oldContext = ::CGLGetCurrentContext();
553 ::CGLSetCurrentContext(mOpenGLContext);
555 ::glViewport(0.0, 0.0, aWidth, aHeight);
556 ::glMatrixMode(GL_PROJECTION);
558 ::glOrtho (0.0, aWidth, 0.0, aHeight, -1, 1);
560 // Render upside down to speed up CGContextDrawImage
561 ::glTranslatef(0.0f, aHeight, 0.0);
562 ::glScalef(1.0, -1.0, 1.0);
564 GLenum result = ::glGetError();
565 if (result != GL_NO_ERROR) {
566 NS_ERROR("Unexpected OpenGL Error");
569 ::CGLSetCurrentContext(oldContext);
570 return NS_ERROR_FAILURE;
574 ::CGLSetCurrentContext(oldContext);
579 void nsCARenderer::AttachIOSurface(nsIOSurface *aSurface) {
581 aSurface->GetIOSurfaceID() == mIOSurface->GetIOSurfaceID()) {
586 // We are attaching a larger IOSurface, we need to
587 // resize our elements.
593 mIOSurface = aSurface;
596 nsresult nsCARenderer::Render(int aWidth, int aHeight,
597 CGImageRef *aOutCGImage) {
598 if (!aOutCGImage && !mIOSurface) {
599 NS_ERROR("No target destination for rendering");
600 } else if (aOutCGImage) {
601 // We are expected to return a CGImageRef, we will set
602 // it to NULL in case we fail before the image is ready.
606 if (aWidth == 0 || aHeight == 0)
610 return NS_ERROR_FAILURE;
613 CARenderer* caRenderer = (CARenderer*)mCARenderer;
614 int renderer_width = caRenderer.bounds.size.width;
615 int renderer_height = caRenderer.bounds.size.height;
617 if (renderer_width != aWidth || renderer_height != aHeight) {
618 // XXX: This should be optimized to not rescale the buffer
619 // if we are resizing down.
620 CALayer* caLayer = [caRenderer layer];
622 if (SetupRenderer(caLayer, aWidth, aHeight) != NS_OK) {
623 return NS_ERROR_FAILURE;
625 caRenderer = (CARenderer*)mCARenderer;
628 CGLContextObj oldContext = ::CGLGetCurrentContext();
629 ::CGLSetCurrentContext(mOpenGLContext);
631 ::CGLSetPBuffer(mOpenGLContext, mPixelBuffer, 0, 0, 0);
634 GLenum result = ::glGetError();
635 if (result != GL_NO_ERROR) {
636 NS_ERROR("Unexpected OpenGL Error");
639 ::CGLSetCurrentContext(oldContext);
640 return NS_ERROR_FAILURE;
643 ::glClearColor(0.0, 0.0, 0.0, 0.0);
644 ::glClear(GL_COLOR_BUFFER_BIT);
646 double caTime = ::CACurrentMediaTime();
647 [caRenderer beginFrameAtTime:caTime timeStamp:NULL];
648 [caRenderer addUpdateRect:CGRectMake(0,0, aWidth, aHeight)];
650 [caRenderer endFrame];
652 // Read the data back either to the IOSurface or mCGImage.
656 ::glPixelStorei(GL_PACK_ALIGNMENT, 4);
657 ::glPixelStorei(GL_PACK_ROW_LENGTH, 0);
658 ::glPixelStorei(GL_PACK_SKIP_ROWS, 0);
659 ::glPixelStorei(GL_PACK_SKIP_PIXELS, 0);
661 ::glReadPixels(0.0f, 0.0f, aWidth, aHeight,
662 GL_BGRA, GL_UNSIGNED_BYTE,
665 *aOutCGImage = mCGImage;
669 ::CGLSetCurrentContext(oldContext);
675 nsresult nsCARenderer::DrawSurfaceToCGContext(CGContextRef aContext,
677 CGColorSpaceRef aColorSpace,
679 int aWidth, int aHeight) {
681 size_t bytesPerRow = surf->GetBytesPerRow();
682 size_t ioWidth = surf->GetWidth();
683 size_t ioHeight = surf->GetHeight();
684 void* ioData = surf->GetBaseAddress();
685 CGDataProviderRef dataProvider = ::CGDataProviderCreateWithData(ioData,
686 ioData, ioHeight*(bytesPerRow)*4,
687 NULL); //No release callback
690 return NS_ERROR_FAILURE;
693 // We get rendering glitches if we use a width/height that falls
694 // outside of the IOSurface.
695 if (aWidth > ioWidth - aX)
696 aWidth = ioWidth - aX;
697 if (aHeight > ioHeight - aY)
698 aHeight = ioHeight - aY;
700 CGImageRef cgImage = ::CGImageCreate(ioWidth, ioHeight, 8, 32, bytesPerRow,
701 aColorSpace, kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Host,
702 dataProvider, NULL, true, kCGRenderingIntentDefault);
703 ::CGDataProviderRelease(dataProvider);
706 return NS_ERROR_FAILURE;
708 CGImageRef subImage = ::CGImageCreateWithImageInRect(cgImage,
709 ::CGRectMake(aX, aY, aWidth, aHeight));
711 ::CGImageRelease(cgImage);
713 return NS_ERROR_FAILURE;
716 ::CGContextScaleCTM(aContext, 1.0f, -1.0f);
717 ::CGContextDrawImage(aContext, CGRectMake(aX, -aY-aHeight, aWidth, aHeight), subImage);
719 ::CGImageRelease(subImage);
720 ::CGImageRelease(cgImage);