- Revision
- 222951
- Author
- [email protected]
- Date
- 2017-10-05 19:31:39 -0700 (Thu, 05 Oct 2017)
Log Message
Lots of missing frames in YouTube360 when fullscreen on MacBook
https://bugs.webkit.org/show_bug.cgi?id=177903
<rdar://problem/33273300>
Reviewed by Sam Weinig.
Our compositing path for WebGL on macOS was too slow, requiring a copy
of the framebuffer into another GL context. Replace this by having
WebGL render into a texture that is backed by an IOSurface, and then
set the WebGLLayer to use the IOSurface as contents.
Covered by the existing WebGL tests.
* platform/graphics/GraphicsContext3D.h:
(WebCore::GraphicsContext3D::platformTexture const): We no longer use the
framebuffer object outside the class, so change this to return the GL texture
that the framebuffer is rendering in to. It was kind-of strange that it was
named this way originally.
Also make endPaint available on macOS, and add the definitions for
createIOSurfaceBackingStore and updateFramebufferTextureBackingStoreFromLayer.
* platform/graphics/cocoa/GraphicsContext3DCocoa.mm:
(WebCore::GraphicsContext3D::GraphicsContext3D): Now that we're using an IOSurface,
we're binding to a new attachment point, GL_TEXTURE_RECTANGLE.
(WebCore::GraphicsContext3D::endPaint): This is now being called on macOS and iOS,
so add a comment that explains the extra work that iOS needs to do. At some future
point it would be nice to make this slightly cleaner, so that iOS and macOS are
more similar.
(WebCore::GraphicsContext3D::allocateIOSurfaceBackingStore): New function that calls
into the corresponding WebGLLayer function.
(WebCore::GraphicsContext3D::updateFramebufferTextureBackingStoreFromLayer): Ditto.
* platform/graphics/opengl/GraphicsContext3DOpenGL.cpp:
(WebCore::wipeAlphaChannelFromPixels): Both readPixels and drawing a WebGL context
into another buffer need to fill out the alpha channel if this context was
created without one, otherwise the IOSurface backing store will happily provide
what might be non-zero values.
(WebCore::GraphicsContext3D::readPixelsAndConvertToBGRAIfNecessary): Call the helper above.
(WebCore::GraphicsContext3D::reshapeFBOs): Add more code to call into the macOS-specific
function to use an IOSurface as the framebuffer texture.
(WebCore::GraphicsContext3D::readPixels): Call the helper above.
* platform/graphics/ca/cocoa/PlatformCALayerCocoa.mm:
(PlatformCALayerCocoa::copyContentsFromLayer): Replace the use of the
deprecated setContentsChanged with reloadValueForKeyPath.
* platform/graphics/cocoa/WebGLLayer.h: The macOS implementation now
inherits from CALayer directly rather than CAOpenGLLayer. It also adds
a few member variables to handle the IOSurfaces used for triple buffering.
* platform/graphics/cocoa/WebGLLayer.mm:
(-[WebGLLayer initWithGraphicsContext3D:]): If we were created without an
alpha channel, tell CA that we're an opaque layer. Also set the layer's transform
to identity, so that it calls into the code below to flip the contents.
(-[WebGLLayer setTransform:]): Because an IOSurface is used for the layer contents,
we don't get a chance to flip the drawing the way we do via the drawInContext delegate.
Instead we have to apply a scale(1, -1) transform on top of the layer transform to
make sure the layer is rendered right-way up.
(-[WebGLLayer setAnchorPoint:]): Ditto, except we have to assume the anchor point is
at the bottom of the layer, so flip the Y value.
(-[WebGLLayer display]): Swap between the drawing buffer and the contents buffer, and
then get a new buffer ready for display.
(createAppropriateIOSurface): Helper.
(-[WebGLLayer allocateIOSurfaceBackingStoreWithSize:usingAlpha:]): Initializes the
IOSurfaces used for drawing buffers.
(-[WebGLLayer bindFramebufferToNextAvailableSurface]): Take the next available IOSurface and
make it the drawing buffer (binding in to WebGL at the same time).
(-[WebGLLayer copyCGLPixelFormatForDisplayMask:]): Deleted.
(-[WebGLLayer copyCGLContextForPixelFormat:]): Deleted.
(-[WebGLLayer drawInCGLContext:pixelFormat:forLayerTime:displayTime:]): Deleted.
* platform/graphics/mac/WebLayer.mm: Remove the definition of reloadValueForKeyPath.
Modified Paths
Diff
Modified: trunk/Source/WebCore/ChangeLog (222950 => 222951)
--- trunk/Source/WebCore/ChangeLog 2017-10-06 01:30:40 UTC (rev 222950)
+++ trunk/Source/WebCore/ChangeLog 2017-10-06 02:31:39 UTC (rev 222951)
@@ -1,3 +1,78 @@
+2017-10-05 Dean Jackson <[email protected]>
+
+ Lots of missing frames in YouTube360 when fullscreen on MacBook
+ https://bugs.webkit.org/show_bug.cgi?id=177903
+ <rdar://problem/33273300>
+
+ Reviewed by Sam Weinig.
+
+ Our compositing path for WebGL on macOS was too slow, requiring a copy
+ of the framebuffer into another GL context. Replace this by having
+ WebGL render into a texture that is backed by an IOSurface, and then
+ set the WebGLLayer to use the IOSurface as contents.
+
+ Covered by the existing WebGL tests.
+
+ * platform/graphics/GraphicsContext3D.h:
+ (WebCore::GraphicsContext3D::platformTexture const): We no longer use the
+ framebuffer object outside the class, so change this to return the GL texture
+ that the framebuffer is rendering in to. It was kind-of strange that it was
+ named this way originally.
+ Also make endPaint available on macOS, and add the definitions for
+ createIOSurfaceBackingStore and updateFramebufferTextureBackingStoreFromLayer.
+
+ * platform/graphics/cocoa/GraphicsContext3DCocoa.mm:
+ (WebCore::GraphicsContext3D::GraphicsContext3D): Now that we're using an IOSurface,
+ we're binding to a new attachment point, GL_TEXTURE_RECTANGLE.
+ (WebCore::GraphicsContext3D::endPaint): This is now being called on macOS and iOS,
+ so add a comment that explains the extra work that iOS needs to do. At some future
+ point it would be nice to make this slightly cleaner, so that iOS and macOS are
+ more similar.
+ (WebCore::GraphicsContext3D::allocateIOSurfaceBackingStore): New function that calls
+ into the corresponding WebGLLayer function.
+ (WebCore::GraphicsContext3D::updateFramebufferTextureBackingStoreFromLayer): Ditto.
+
+ * platform/graphics/opengl/GraphicsContext3DOpenGL.cpp:
+ (WebCore::wipeAlphaChannelFromPixels): Both readPixels and drawing a WebGL context
+ into another buffer need to fill out the alpha channel if this context was
+ created without one, otherwise the IOSurface backing store will happily provide
+ what might be non-zero values.
+ (WebCore::GraphicsContext3D::readPixelsAndConvertToBGRAIfNecessary): Call the helper above.
+ (WebCore::GraphicsContext3D::reshapeFBOs): Add more code to call into the macOS-specific
+ function to use an IOSurface as the framebuffer texture.
+ (WebCore::GraphicsContext3D::readPixels): Call the helper above.
+
+ * platform/graphics/ca/cocoa/PlatformCALayerCocoa.mm:
+ (PlatformCALayerCocoa::copyContentsFromLayer): Replace the use of the
+ deprecated setContentsChanged with reloadValueForKeyPath.
+
+ * platform/graphics/cocoa/WebGLLayer.h: The macOS implementation now
+ inherits from CALayer directly rather than CAOpenGLLayer. It also adds
+ a few member variables to handle the IOSurfaces used for triple buffering.
+
+ * platform/graphics/cocoa/WebGLLayer.mm:
+ (-[WebGLLayer initWithGraphicsContext3D:]): If we were created without an
+ alpha channel, tell CA that we're an opaque layer. Also set the layer's transform
+ to identity, so that it calls into the code below to flip the contents.
+ (-[WebGLLayer setTransform:]): Because an IOSurface is used for the layer contents,
+ we don't get a chance to flip the drawing the way we do via the drawInContext delegate.
+ Instead we have to apply a scale(1, -1) transform on top of the layer transform to
+ make sure the layer is rendered right-way up.
+ (-[WebGLLayer setAnchorPoint:]): Ditto, except we have to assume the anchor point is
+ at the bottom of the layer, so flip the Y value.
+ (-[WebGLLayer display]): Swap between the drawing buffer and the contents buffer, and
+ then get a new buffer ready for display.
+ (createAppropriateIOSurface): Helper.
+ (-[WebGLLayer allocateIOSurfaceBackingStoreWithSize:usingAlpha:]): Initializes the
+ IOSurfaces used for drawing buffers.
+ (-[WebGLLayer bindFramebufferToNextAvailableSurface]): Take the next available IOSurface and
+ make it the drawing buffer (binding in to WebGL at the same time).
+ (-[WebGLLayer copyCGLPixelFormatForDisplayMask:]): Deleted.
+ (-[WebGLLayer copyCGLContextForPixelFormat:]): Deleted.
+ (-[WebGLLayer drawInCGLContext:pixelFormat:forLayerTime:displayTime:]): Deleted.
+
+ * platform/graphics/mac/WebLayer.mm: Remove the definition of reloadValueForKeyPath.
+
2017-10-05 Myles C. Maxfield <[email protected]>
Add "display" to FontFace _javascript_ object
Modified: trunk/Source/WebCore/PAL/ChangeLog (222950 => 222951)
--- trunk/Source/WebCore/PAL/ChangeLog 2017-10-06 01:30:40 UTC (rev 222950)
+++ trunk/Source/WebCore/PAL/ChangeLog 2017-10-06 02:31:39 UTC (rev 222951)
@@ -1,3 +1,15 @@
+2017-10-05 Dean Jackson <[email protected]>
+
+ Lots of missing frames in YouTube360 when fullscreen on MacBook
+ https://bugs.webkit.org/show_bug.cgi?id=177903
+ <rdar://problem/33273300>
+
+ Reviewed by Sam Weinig.
+
+ Add reloadValueForKeyPath to replace setContentsChanged on CALayer.
+
+ * pal/spi/cocoa/QuartzCoreSPI.h:
+
2017-10-05 Jer Noble <[email protected]>
[Cocoa] Enable ENABLE_ENCRYPTED_MEDIA build-time setting
Modified: trunk/Source/WebCore/PAL/pal/spi/cocoa/QuartzCoreSPI.h (222950 => 222951)
--- trunk/Source/WebCore/PAL/pal/spi/cocoa/QuartzCoreSPI.h 2017-10-06 01:30:40 UTC (rev 222950)
+++ trunk/Source/WebCore/PAL/pal/spi/cocoa/QuartzCoreSPI.h 2017-10-06 02:31:39 UTC (rev 222951)
@@ -91,7 +91,7 @@
- (void)setContextId:(uint32_t)contextID;
- (CGSize)size;
- (void *)regionBeingDrawn;
-- (void)setContentsChanged;
+- (void)reloadValueForKeyPath:(NSString *)keyPath;
@property BOOL allowsGroupBlending;
@property BOOL canDrawConcurrently;
@property BOOL contentsOpaque;
Modified: trunk/Source/WebCore/platform/graphics/GraphicsContext3D.h (222950 => 222951)
--- trunk/Source/WebCore/platform/graphics/GraphicsContext3D.h 2017-10-06 01:30:40 UTC (rev 222950)
+++ trunk/Source/WebCore/platform/graphics/GraphicsContext3D.h 2017-10-06 02:31:39 UTC (rev 222951)
@@ -747,7 +747,7 @@
#if PLATFORM(COCOA)
PlatformGraphicsContext3D platformGraphicsContext3D() const { return m_contextObj; }
- Platform3DObject platformTexture() const { return m_fbo; }
+ Platform3DObject platformTexture() const { return m_texture; }
CALayer* platformLayer() const { return reinterpret_cast<CALayer*>(m_webGLLayer.get()); }
#else
PlatformGraphicsContext3D platformGraphicsContext3D();
@@ -1147,12 +1147,16 @@
RefPtr<ImageData> paintRenderingResultsToImageData();
bool paintCompositedResultsToCanvas(ImageBuffer*);
-#if PLATFORM(IOS)
+#if PLATFORM(COCOA)
void endPaint();
#endif
+
#if PLATFORM(MAC)
+ void allocateIOSurfaceBackingStore(IntSize);
+ void updateFramebufferTextureBackingStoreFromLayer();
void updateCGLContext();
#endif
+
void setContextVisibility(bool);
GraphicsContext3DPowerPreference powerPreferenceUsedForCreation() const { return m_powerPreferenceUsedForCreation; }
Modified: trunk/Source/WebCore/platform/graphics/ca/cocoa/PlatformCALayerCocoa.mm (222950 => 222951)
--- trunk/Source/WebCore/platform/graphics/ca/cocoa/PlatformCALayerCocoa.mm 2017-10-06 01:30:40 UTC (rev 222950)
+++ trunk/Source/WebCore/platform/graphics/ca/cocoa/PlatformCALayerCocoa.mm 2017-10-06 02:31:39 UTC (rev 222951)
@@ -411,7 +411,7 @@
if ([m_layer contents] != [caLayer contents])
[m_layer setContents:[caLayer contents]];
else
- [m_layer setContentsChanged];
+ [m_layer reloadValueForKeyPath:@"contents"];
END_BLOCK_OBJC_EXCEPTIONS
}
Modified: trunk/Source/WebCore/platform/graphics/cocoa/GraphicsContext3DCocoa.mm (222950 => 222951)
--- trunk/Source/WebCore/platform/graphics/cocoa/GraphicsContext3DCocoa.mm 2017-10-06 01:30:40 UTC (rev 222950)
+++ trunk/Source/WebCore/platform/graphics/cocoa/GraphicsContext3DCocoa.mm 2017-10-06 02:31:39 UTC (rev 222951)
@@ -479,20 +479,22 @@
::glEnable(GL_MULTISAMPLE);
#endif
+ // Create the texture that will be used for the framebuffer.
#if PLATFORM(IOS)
::glGenRenderbuffers(1, &m_texture);
#else
- // create a texture to render into
::glGenTextures(1, &m_texture);
- ::glBindTexture(GL_TEXTURE_2D, m_texture);
- ::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
- ::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
- ::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
- ::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
- ::glBindTexture(GL_TEXTURE_2D, 0);
+ // We bind to GL_TEXTURE_RECTANGLE_EXT rather than TEXTURE_2D because
+ // that's what is required for a texture backed by IOSurface.
+ ::glBindTexture(GL_TEXTURE_RECTANGLE_EXT, m_texture);
+ ::glTexParameteri(GL_TEXTURE_RECTANGLE_EXT, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ ::glTexParameteri(GL_TEXTURE_RECTANGLE_EXT, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ ::glTexParameteri(GL_TEXTURE_RECTANGLE_EXT, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ ::glTexParameteri(GL_TEXTURE_RECTANGLE_EXT, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+ ::glBindTexture(GL_TEXTURE_RECTANGLE_EXT, 0);
#endif
- // create an FBO
+ // Create the framebuffer object.
::glGenFramebuffersEXT(1, &m_fbo);
::glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_fbo);
@@ -500,7 +502,7 @@
if (!m_attrs.antialias && (m_attrs.stencil || m_attrs.depth))
::glGenRenderbuffersEXT(1, &m_depthStencilBuffer);
- // create an multisample FBO
+ // If necessary, create another framebuffer for the multisample results.
if (m_attrs.antialias) {
::glGenFramebuffersEXT(1, &m_multisampleFBO);
::glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_multisampleFBO);
@@ -654,20 +656,35 @@
#endif
}
-#if PLATFORM(IOS)
void GraphicsContext3D::endPaint()
{
makeContextCurrent();
if (m_attrs.antialias)
resolveMultisamplingIfNecessary();
+#if PLATFORM(IOS)
+ // This is the place where we actually push our current rendering
+ // results to the compositor on iOS. On macOS it comes from the
+ // calling function, which is inside WebGLLayer.
::glFlush();
::glBindRenderbuffer(GL_RENDERBUFFER, m_texture);
[static_cast<EAGLContext*>(m_contextObj) presentRenderbuffer:GL_RENDERBUFFER];
[EAGLContext setCurrentContext:nil];
+#endif
}
-#endif
#if PLATFORM(MAC)
+void GraphicsContext3D::allocateIOSurfaceBackingStore(IntSize size)
+{
+ LOG(WebGL, "GraphicsContext3D::allocateIOSurfaceBackingStore at %d x %d. (%p)", size.width(), size.height(), this);
+ [m_webGLLayer allocateIOSurfaceBackingStoreWithSize:size usingAlpha:m_attrs.alpha];
+}
+
+void GraphicsContext3D::updateFramebufferTextureBackingStoreFromLayer()
+{
+ LOG(WebGL, "GraphicsContext3D::updateFramebufferTextureBackingStoreFromLayer(). (%p)", this);
+ [m_webGLLayer bindFramebufferToNextAvailableSurface];
+}
+
void GraphicsContext3D::updateCGLContext()
{
if (!m_contextObj)
Modified: trunk/Source/WebCore/platform/graphics/cocoa/WebGLLayer.h (222950 => 222951)
--- trunk/Source/WebCore/platform/graphics/cocoa/WebGLLayer.h 2017-10-06 01:30:40 UTC (rev 222950)
+++ trunk/Source/WebCore/platform/graphics/cocoa/WebGLLayer.h 2017-10-06 02:31:39 UTC (rev 222951)
@@ -25,6 +25,8 @@
#pragma once
+#import "IOSurface.h"
+#import "IntSize.h"
#import <QuartzCore/QuartzCore.h>
namespace WebCore {
@@ -32,14 +34,21 @@
class GraphicsContext3D;
}
-#if PLATFORM(IOS)
+#if PLATFORM(MAC)
+@interface WebGLLayer : CALayer
+#else
@interface WebGLLayer : CAEAGLLayer
-#else
-@interface WebGLLayer : CAOpenGLLayer
#endif
{
WebCore::GraphicsContext3D* _context;
float _devicePixelRatio;
+#if PLATFORM(MAC)
+ std::unique_ptr<WebCore::IOSurface> _contentsBuffer;
+ std::unique_ptr<WebCore::IOSurface> _drawingBuffer;
+ std::unique_ptr<WebCore::IOSurface> _spareBuffer;
+ WebCore::IntSize _bufferSize;
+ BOOL _usingAlpha;
+#endif
}
@property (nonatomic) WebCore::GraphicsContext3D* context;
@@ -48,5 +57,10 @@
- (CGImageRef)copyImageSnapshotWithColorSpace:(CGColorSpaceRef)colorSpace;
+#if PLATFORM(MAC)
+- (void)allocateIOSurfaceBackingStoreWithSize:(WebCore::IntSize)size usingAlpha:(BOOL)usingAlpha;
+- (void)bindFramebufferToNextAvailableSurface;
+#endif
+
@end
Modified: trunk/Source/WebCore/platform/graphics/cocoa/WebGLLayer.mm (222950 => 222951)
--- trunk/Source/WebCore/platform/graphics/cocoa/WebGLLayer.mm 2017-10-06 01:30:40 UTC (rev 222950)
+++ trunk/Source/WebCore/platform/graphics/cocoa/WebGLLayer.mm 2017-10-06 02:31:39 UTC (rev 222951)
@@ -33,10 +33,11 @@
#import "GraphicsLayer.h"
#import "GraphicsLayerCA.h"
#import "PlatformCALayer.h"
+#import <pal/spi/cocoa/QuartzCoreSPI.h>
#import <wtf/FastMalloc.h>
#import <wtf/RetainPtr.h>
-#if !PLATFORM(IOS)
+#if PLATFORM(MAC)
#import <OpenGL/OpenGL.h>
#import <OpenGL/gl.h>
#endif
@@ -53,113 +54,37 @@
self = [super init];
_devicePixelRatio = context->getContextAttributes().devicePixelRatio;
#if PLATFORM(MAC)
+ if (!context->getContextAttributes().alpha)
+ self.opaque = YES;
+ self.transform = CATransform3DIdentity;
self.contentsScale = _devicePixelRatio;
- self.colorspace = sRGBColorSpaceRef();
#endif
return self;
}
-#if !PLATFORM(IOS)
--(CGLPixelFormatObj)copyCGLPixelFormatForDisplayMask:(uint32_t)mask
-{
- // We're basically copying the pixel format object from the existing
- // WebGL context, so we don't need to use the display mask.
- UNUSED_PARAM(mask);
+#if PLATFORM(MAC)
+// On Mac, we need to flip the layer to take into account
+// that the IOSurface provides content in Y-up. This
+// means that any incoming transform (unlikely, since this
+// is a contents layer) and anchor point must add a
+// Y scale of -1 and make sure the transform happens from
+// the top.
- CGLPixelFormatObj webglPixelFormat = CGLGetPixelFormat(_context->platformGraphicsContext3D());
-
- Vector<CGLPixelFormatAttribute> attribs;
- GLint value;
-
- CGLDescribePixelFormat(webglPixelFormat, 0, kCGLPFAColorSize, &value);
- attribs.append(kCGLPFAColorSize);
- attribs.append(static_cast<CGLPixelFormatAttribute>(value));
-
- // We don't need to specify a depth size since we're only
- // using this context as a 2d blit destination for the WebGL FBO.
- attribs.append(kCGLPFADepthSize);
- attribs.append(static_cast<CGLPixelFormatAttribute>(0));
-
- CGLDescribePixelFormat(webglPixelFormat, 0, kCGLPFAAllowOfflineRenderers, &value);
- if (value)
- attribs.append(kCGLPFAAllowOfflineRenderers);
-
- CGLDescribePixelFormat(webglPixelFormat, 0, kCGLPFAAccelerated, &value);
- if (value)
- attribs.append(kCGLPFAAccelerated);
-
- CGLDescribePixelFormat(webglPixelFormat, 0, kCGLPFAOpenGLProfile, &value);
- if (value) {
- attribs.append(kCGLPFAOpenGLProfile);
- attribs.append(static_cast<CGLPixelFormatAttribute>(value));
- }
-
- attribs.append(static_cast<CGLPixelFormatAttribute>(0));
-
- CGLPixelFormatObj pixelFormat;
- GLint numPixelFormats = 0;
- CGLChoosePixelFormat(attribs.data(), &pixelFormat, &numPixelFormats);
-
- ASSERT(pixelFormat);
- ASSERT(numPixelFormats);
-
- return pixelFormat;
-}
-
--(CGLContextObj)copyCGLContextForPixelFormat:(CGLPixelFormatObj)pixelFormat
+- (void)setTransform:(CATransform3D)t
{
- CGLContextObj contextObj;
- CGLCreateContext(pixelFormat, _context->platformGraphicsContext3D(), &contextObj);
- return contextObj;
+ [super setTransform:CATransform3DScale(t, 1, -1, 1)];
}
--(void)drawInCGLContext:(CGLContextObj)glContext pixelFormat:(CGLPixelFormatObj)pixelFormat forLayerTime:(CFTimeInterval)timeInterval displayTime:(const CVTimeStamp *)timeStamp
+- (void)setAnchorPoint:(CGPoint)p
{
- if (!_context)
- return;
-
- _context->prepareTexture();
-
- CGLSetCurrentContext(glContext);
-
- CGRect frame = [self frame];
- frame.size.width *= _devicePixelRatio;
- frame.size.height *= _devicePixelRatio;
-
- // draw the FBO into the layer
- glViewport(0, 0, frame.size.width, frame.size.height);
- glMatrixMode(GL_PROJECTION);
- glLoadIdentity();
- glOrtho(-1, 1, -1, 1, -1, 1);
- glMatrixMode(GL_MODELVIEW);
- glLoadIdentity();
-
- glEnable(GL_TEXTURE_2D);
- glBindTexture(GL_TEXTURE_2D, _context->platformTexture());
-
- glBegin(GL_TRIANGLE_FAN);
- glTexCoord2f(0, 0);
- glVertex2f(-1, -1);
- glTexCoord2f(1, 0);
- glVertex2f(1, -1);
- glTexCoord2f(1, 1);
- glVertex2f(1, 1);
- glTexCoord2f(0, 1);
- glVertex2f(-1, 1);
- glEnd();
-
- glBindTexture(GL_TEXTURE_2D, 0);
- glDisable(GL_TEXTURE_2D);
-
- // Call super to finalize the drawing. By default all it does is call glFlush().
- [super drawInCGLContext:glContext pixelFormat:pixelFormat forLayerTime:timeInterval displayTime:timeStamp];
+ [super setAnchorPoint:CGPointMake(p.x, 1.0 - p.y)];
}
+#endif
static void freeData(void *, const void *data, size_t /* size */)
{
fastFree(const_cast<void *>(data));
}
-#endif
-(CGImageRef)copyImageSnapshotWithColorSpace:(CGColorSpaceRef)colorSpace
{
@@ -203,11 +128,18 @@
if (!_context)
return;
-#if PLATFORM(IOS)
_context->endPaint();
-#else
- [super display];
+
+#if PLATFORM(MAC)
+ _context->prepareTexture();
+ if (_drawingBuffer) {
+ std::swap(_contentsBuffer, _drawingBuffer);
+ self.contents = _contentsBuffer->asLayerContents();
+ [self reloadValueForKeyPath:@"contents"];
+ [self bindFramebufferToNextAvailableSurface];
+ }
#endif
+
_context->markLayerComposited();
PlatformCALayer* layer = PlatformCALayer::platformCALayer(self);
if (layer && layer->owner())
@@ -214,6 +146,37 @@
layer->owner()->platformCALayerLayerDidDisplay(layer);
}
+#if PLATFORM(MAC)
+- (void)allocateIOSurfaceBackingStoreWithSize:(IntSize)size usingAlpha:(BOOL)usingAlpha
+{
+ _bufferSize = size;
+ _usingAlpha = usingAlpha;
+ _contentsBuffer = WebCore::IOSurface::create(size, sRGBColorSpaceRef());
+ _drawingBuffer = WebCore::IOSurface::create(size, sRGBColorSpaceRef());
+ ASSERT(_contentsBuffer);
+ ASSERT(_drawingBuffer);
+}
+
+- (void)bindFramebufferToNextAvailableSurface
+{
+ GC3Denum texture = _context->platformTexture();
+ glBindTexture(GL_TEXTURE_RECTANGLE_ARB, texture);
+
+ if (_drawingBuffer && _drawingBuffer->isInUse()) {
+ if (!_spareBuffer)
+ _spareBuffer = WebCore::IOSurface::create(_bufferSize, sRGBColorSpaceRef());
+ std::swap(_drawingBuffer, _spareBuffer);
+ }
+
+ IOSurfaceRef ioSurface = _drawingBuffer->surface();
+ GC3Denum internalFormat = _usingAlpha ? GL_RGBA : GL_RGB;
+
+ // Link the IOSurface to the texture.
+ CGLError error = CGLTexImageIOSurface2D(_context->platformGraphicsContext3D(), GL_TEXTURE_RECTANGLE_ARB, internalFormat, _bufferSize.width(), _bufferSize.height(), GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, ioSurface, 0);
+ ASSERT_UNUSED(error, error == kCGLNoError);
+}
+#endif
+
@end
#endif // ENABLE(WEBGL)
Modified: trunk/Source/WebCore/platform/graphics/mac/WebLayer.mm (222950 => 222951)
--- trunk/Source/WebCore/platform/graphics/mac/WebLayer.mm 2017-10-06 01:30:40 UTC (rev 222950)
+++ trunk/Source/WebCore/platform/graphics/mac/WebLayer.mm 2017-10-06 02:31:39 UTC (rev 222951)
@@ -30,6 +30,7 @@
#import "GraphicsLayerCA.h"
#import "PlatformCALayer.h"
#import <QuartzCore/QuartzCore.h>
+#import <pal/spi/cocoa/QuartzCoreSPI.h>
#import <wtf/SetForScope.h>
#if PLATFORM(IOS)
@@ -38,10 +39,6 @@
#import "WebCoreThread.h"
#endif
-@interface CALayer(WebCoreCALayerPrivate)
-- (void)reloadValueForKeyPath:(NSString *)keyPath;
-@end
-
using namespace WebCore;
#if PLATFORM(IOS)
Modified: trunk/Source/WebCore/platform/graphics/opengl/GraphicsContext3DOpenGL.cpp (222950 => 222951)
--- trunk/Source/WebCore/platform/graphics/opengl/GraphicsContext3DOpenGL.cpp 2017-10-06 01:30:40 UTC (rev 222950)
+++ trunk/Source/WebCore/platform/graphics/opengl/GraphicsContext3DOpenGL.cpp 2017-10-06 02:31:39 UTC (rev 222951)
@@ -29,16 +29,15 @@
#if ENABLE(GRAPHICS_CONTEXT_3D)
#include "GraphicsContext3D.h"
+
#if PLATFORM(IOS)
#include "GraphicsContext3DIOS.h"
#endif
-
#include "Extensions3DOpenGL.h"
#include "IntRect.h"
#include "IntSize.h"
#include "NotImplemented.h"
#include "TemporaryOpenGLSetting.h"
-
#include <algorithm>
#include <cstring>
#include <wtf/MainThread.h>
@@ -70,6 +69,15 @@
notImplemented();
}
+static void wipeAlphaChannelFromPixels(int width, int height, unsigned char* pixels)
+{
+ // We can assume this doesn't overflow because the calling functions
+ // use checked arithmetic.
+ int totalBytes = width * height * 4;
+ for (int i = 0; i < totalBytes; i += 4)
+ pixels[i + 3] = 255;
+}
+
void GraphicsContext3D::readPixelsAndConvertToBGRAIfNecessary(int x, int y, int width, int height, unsigned char* pixels)
{
// NVIDIA drivers have a bug where calling readPixels in BGRA can return the wrong values for the alpha channel when the alpha is off for the context.
@@ -98,6 +106,11 @@
#endif
} else
::glReadPixels(x, y, width, height, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, pixels);
+
+#if PLATFORM(MAC)
+ if (!m_attrs.alpha)
+ wipeAlphaChannelFromPixels(width, height, pixels);
+#endif
}
void GraphicsContext3D::validateAttributes()
@@ -170,6 +183,10 @@
::glBindRenderbuffer(GL_RENDERBUFFER, m_texture);
::glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, m_texture);
setRenderbufferStorageFromDrawable(m_currentWidth, m_currentHeight);
+#elif PLATFORM(MAC)
+ allocateIOSurfaceBackingStore(IntSize(width, height));
+ updateFramebufferTextureBackingStoreFromLayer();
+ ::glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_RECTANGLE_ARB, m_texture, 0);
#else
::glBindTexture(GL_TEXTURE_2D, m_texture);
::glTexImage2D(GL_TEXTURE_2D, 0, m_internalColorFormat, width, height, 0, colorFormat, GL_UNSIGNED_BYTE, 0);
@@ -442,6 +459,11 @@
::glReadPixels(x, y, width, height, format, type, data);
if (m_attrs.antialias && m_state.boundFBO == m_multisampleFBO)
::glBindFramebufferEXT(GraphicsContext3D::FRAMEBUFFER, m_multisampleFBO);
+
+#if PLATFORM(MAC)
+ if (!m_attrs.alpha && (format == GraphicsContext3D::RGBA || format == GraphicsContext3D::BGRA) && (m_state.boundFBO == m_fbo || (m_attrs.antialias && m_state.boundFBO == m_multisampleFBO)))
+ wipeAlphaChannelFromPixels(width, height, static_cast<unsigned char*>(data));
+#endif
}
}