Bundle unified sources more tightly in projects with deep directory structures
[WebKit-https.git] / Source / WebCore / platform / graphics / cocoa / WebGLLayer.mm
1 /*
2  * Copyright (C) 2009-2017 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
24  */
25
26 #include "config.h"
27
28 #if ENABLE(WEBGL)
29 #import "WebGLLayer.h"
30
31 #import "GraphicsContext3D.h"
32 #import "GraphicsContextCG.h"
33 #import "GraphicsLayer.h"
34 #import "GraphicsLayerCA.h"
35 #import "PlatformCALayer.h"
36 #import <pal/spi/cocoa/QuartzCoreSPI.h>
37 #import <wtf/FastMalloc.h>
38 #import <wtf/RetainPtr.h>
39
40 #if USE(OPENGL)
41 #import <OpenGL/OpenGL.h>
42 #import <OpenGL/gl.h>
43 #endif
44
45 @implementation WebGLLayer
46
47 @synthesize context=_context;
48
49 -(id)initWithGraphicsContext3D:(WebCore::GraphicsContext3D*)context
50 {
51     _context = context;
52     self = [super init];
53     _devicePixelRatio = context->getContextAttributes().devicePixelRatio;
54 #if USE(OPENGL)
55     self.contentsOpaque = !context->getContextAttributes().alpha;
56     self.transform = CATransform3DIdentity;
57     self.contentsScale = _devicePixelRatio;
58 #else
59     self.opaque = !context->getContextAttributes().alpha;
60 #endif
61     return self;
62 }
63
64 #if USE(OPENGL)
65 // When using an IOSurface as layer contents, we need to flip the
66 // layer to take into account that the IOSurface provides content
67 // in Y-up. This means that any incoming transform (unlikely, since
68 // this is a contents layer) and anchor point must add a Y scale of
69 // -1 and make sure the transform happens from the top.
70
71 - (void)setTransform:(CATransform3D)t
72 {
73     [super setTransform:CATransform3DScale(t, 1, -1, 1)];
74 }
75
76 - (void)setAnchorPoint:(CGPoint)p
77 {
78     [super setAnchorPoint:CGPointMake(p.x, 1.0 - p.y)];
79 }
80
81 static void freeData(void *, const void *data, size_t /* size */)
82 {
83     fastFree(const_cast<void *>(data));
84 }
85 #endif
86
87 - (CGImageRef)copyImageSnapshotWithColorSpace:(CGColorSpaceRef)colorSpace
88 {
89     if (!_context)
90         return nullptr;
91
92 #if USE(OPENGL)
93     CGLSetCurrentContext(_context->platformGraphicsContext3D());
94
95     RetainPtr<CGColorSpaceRef> imageColorSpace = colorSpace;
96     if (!imageColorSpace)
97         imageColorSpace = WebCore::sRGBColorSpaceRef();
98
99     CGRect layerBounds = CGRectIntegral([self bounds]);
100
101     size_t width = layerBounds.size.width * _devicePixelRatio;
102     size_t height = layerBounds.size.height * _devicePixelRatio;
103
104     size_t rowBytes = (width * 4 + 15) & ~15;
105     size_t dataSize = rowBytes * height;
106     void* data = fastMalloc(dataSize);
107     if (!data)
108         return nullptr;
109
110     glPixelStorei(GL_PACK_ROW_LENGTH, rowBytes / 4);
111     glReadPixels(0, 0, width, height, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, data);
112
113     CGDataProviderRef provider = CGDataProviderCreateWithData(0, data, dataSize, freeData);
114     CGImageRef image = CGImageCreate(width, height, 8, 32, rowBytes, imageColorSpace.get(),
115         kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Host, provider, 0, true, kCGRenderingIntentDefault);
116     CGDataProviderRelease(provider);
117     return image;
118 #else
119     UNUSED_PARAM(colorSpace);
120     return nullptr;
121 #endif
122 }
123
124 - (void)display
125 {
126     if (!_context)
127         return;
128
129 #if USE(OPENGL)
130     _context->prepareTexture();
131     if (_drawingBuffer) {
132         std::swap(_contentsBuffer, _drawingBuffer);
133         self.contents = _contentsBuffer->asLayerContents();
134         [self reloadValueForKeyPath:@"contents"];
135         [self bindFramebufferToNextAvailableSurface];
136     }
137 #else
138     _context->presentRenderbuffer();
139 #endif
140
141     _context->markLayerComposited();
142     WebCore::PlatformCALayer* layer = WebCore::PlatformCALayer::platformCALayer((__bridge void*)self);
143     if (layer && layer->owner())
144         layer->owner()->platformCALayerLayerDidDisplay(layer);
145 }
146
147 #if USE(OPENGL)
148 - (void)allocateIOSurfaceBackingStoreWithSize:(WebCore::IntSize)size usingAlpha:(BOOL)usingAlpha
149 {
150     _bufferSize = size;
151     _usingAlpha = usingAlpha;
152     _contentsBuffer = WebCore::IOSurface::create(size, WebCore::sRGBColorSpaceRef());
153     _drawingBuffer = WebCore::IOSurface::create(size, WebCore::sRGBColorSpaceRef());
154     _spareBuffer = WebCore::IOSurface::create(size, WebCore::sRGBColorSpaceRef());
155
156     ASSERT(_contentsBuffer);
157     ASSERT(_drawingBuffer);
158     ASSERT(_spareBuffer);
159
160     _contentsBuffer->migrateColorSpaceToProperties();
161     _drawingBuffer->migrateColorSpaceToProperties();
162     _spareBuffer->migrateColorSpaceToProperties();
163 }
164
165 - (void)bindFramebufferToNextAvailableSurface
166 {
167     GC3Denum texture = _context->platformTexture();
168     glBindTexture(GL_TEXTURE_RECTANGLE_ARB, texture);
169
170     if (_drawingBuffer && _drawingBuffer->isInUse())
171         std::swap(_drawingBuffer, _spareBuffer);
172
173     IOSurfaceRef ioSurface = _drawingBuffer->surface();
174     GC3Denum internalFormat = _usingAlpha ? GL_RGBA : GL_RGB;
175
176     // Link the IOSurface to the texture.
177     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);
178     ASSERT_UNUSED(error, error == kCGLNoError);
179 }
180 #endif
181
182 @end
183
184 #endif // ENABLE(WEBGL)