d360f92dd04858adfb437ae3a15c5a9fb10a072b
[WebKit-https.git] / Source / WebCore / platform / graphics / mac / WebGLLayer.mm
1 /*
2  * Copyright (C) 2009 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
30 #import "WebGLLayer.h"
31
32 #import "GraphicsContext3D.h"
33 #import "GraphicsContextCG.h"
34 #import "GraphicsLayer.h"
35 #import <wtf/FastMalloc.h>
36 #import <wtf/RetainPtr.h>
37
38 #if !PLATFORM(IOS)
39 #import <OpenGL/OpenGL.h>
40 #import <OpenGL/gl.h>
41 #endif
42
43 using namespace WebCore;
44
45 @implementation WebGLLayer
46
47 @synthesize context=_context;
48
49 -(id)initWithGraphicsContext3D:(GraphicsContext3D*)context
50 {
51     _context = context;
52     self = [super init];
53     _devicePixelRatio = context->getContextAttributes().devicePixelRatio;
54 #if PLATFORM(MAC)
55     self.contentsScale = _devicePixelRatio;
56 #if __MAC_OS_X_VERSION_MIN_REQUIRED >= 101100
57     self.colorspace = sRGBColorSpaceRef();
58 #endif
59 #endif
60     return self;
61 }
62
63 #if !PLATFORM(IOS)
64 -(CGLPixelFormatObj)copyCGLPixelFormatForDisplayMask:(uint32_t)mask
65 {
66     // FIXME: The mask param tells you which display (on a multi-display system)
67     // is to be used. But since we are now getting the pixel format from the
68     // Canvas CGL context, we don't use it. This seems to do the right thing on
69     // one multi-display system. But there may be cases where this is not the case.
70     // If needed we will have to set the display mask in the Canvas CGLContext and
71     // make sure it matches.
72     UNUSED_PARAM(mask);
73     return CGLRetainPixelFormat(CGLGetPixelFormat(_context->platformGraphicsContext3D()));
74 }
75
76 -(CGLContextObj)copyCGLContextForPixelFormat:(CGLPixelFormatObj)pixelFormat
77 {
78     CGLContextObj contextObj;
79     CGLCreateContext(pixelFormat, _context->platformGraphicsContext3D(), &contextObj);
80     return contextObj;
81 }
82
83 -(void)drawInCGLContext:(CGLContextObj)glContext pixelFormat:(CGLPixelFormatObj)pixelFormat forLayerTime:(CFTimeInterval)timeInterval displayTime:(const CVTimeStamp *)timeStamp
84 {
85     if (!_context)
86         return;
87
88     _context->prepareTexture();
89
90     CGLSetCurrentContext(glContext);
91
92     CGRect frame = [self frame];
93     frame.size.width *= _devicePixelRatio;
94     frame.size.height *= _devicePixelRatio;
95
96     // draw the FBO into the layer
97     glViewport(0, 0, frame.size.width, frame.size.height);
98     glMatrixMode(GL_PROJECTION);
99     glLoadIdentity();
100     glOrtho(-1, 1, -1, 1, -1, 1);
101     glMatrixMode(GL_MODELVIEW);
102     glLoadIdentity();
103
104     glEnable(GL_TEXTURE_2D);
105     glBindTexture(GL_TEXTURE_2D, _context->platformTexture());
106
107     glBegin(GL_TRIANGLE_FAN);
108         glTexCoord2f(0, 0);
109         glVertex2f(-1, -1);
110         glTexCoord2f(1, 0);
111         glVertex2f(1, -1);
112         glTexCoord2f(1, 1);
113         glVertex2f(1, 1);
114         glTexCoord2f(0, 1);
115         glVertex2f(-1, 1);
116     glEnd();
117
118     glBindTexture(GL_TEXTURE_2D, 0);
119     glDisable(GL_TEXTURE_2D);
120
121     // Call super to finalize the drawing. By default all it does is call glFlush().
122     [super drawInCGLContext:glContext pixelFormat:pixelFormat forLayerTime:timeInterval displayTime:timeStamp];
123 }
124
125 static void freeData(void *, const void *data, size_t /* size */)
126 {
127     fastFree(const_cast<void *>(data));
128 }
129 #endif
130
131 -(CGImageRef)copyImageSnapshotWithColorSpace:(CGColorSpaceRef)colorSpace
132 {
133     if (!_context)
134         return nullptr;
135
136 #if PLATFORM(IOS)
137     UNUSED_PARAM(colorSpace);
138     return nullptr;
139 #else
140     CGLSetCurrentContext(_context->platformGraphicsContext3D());
141
142     RetainPtr<CGColorSpaceRef> imageColorSpace = colorSpace;
143     if (!imageColorSpace)
144         imageColorSpace = adoptCF(CGColorSpaceCreateDeviceRGB());
145
146     CGRect layerBounds = CGRectIntegral([self bounds]);
147
148     size_t width = layerBounds.size.width * _devicePixelRatio;
149     size_t height = layerBounds.size.height * _devicePixelRatio;
150
151     size_t rowBytes = (width * 4 + 15) & ~15;
152     size_t dataSize = rowBytes * height;
153     void* data = fastMalloc(dataSize);
154     if (!data)
155         return nullptr;
156
157     glPixelStorei(GL_PACK_ROW_LENGTH, rowBytes / 4);
158     glReadPixels(0, 0, width, height, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, data);
159
160     CGDataProviderRef provider = CGDataProviderCreateWithData(0, data, dataSize, freeData);
161     CGImageRef image = CGImageCreate(width, height, 8, 32, rowBytes, imageColorSpace.get(),
162                                                  kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Host,
163                                                  provider, 0, true,
164                                                  kCGRenderingIntentDefault);
165     CGDataProviderRelease(provider);
166     return image;
167 #endif
168 }
169
170 - (void)display
171 {
172     if (!_context)
173         return;
174
175 #if PLATFORM(IOS)
176     _context->endPaint();
177 #else
178     [super display];
179 #endif
180     _context->markLayerComposited();
181 }
182
183 @end
184
185 #endif // ENABLE(WEBGL)