646962f7e660f32ff11a1137b23530e59177f6b7
[WebKit-https.git] / Source / WebKit2 / UIProcess / mac / BackingStoreMac.mm
1 /*
2  * Copyright (C) 2011 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. AND ITS CONTRIBUTORS ``AS IS''
14  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
17  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23  * THE POSSIBILITY OF SUCH DAMAGE.
24  */
25
26 #import "config.h"
27 #import "BackingStore.h"
28
29 #import "CGUtilities.h"
30 #import "ShareableBitmap.h"
31 #import "UpdateInfo.h"
32 #import "WebPageProxy.h"
33 #import <WebCore/GraphicsContext.h>
34
35 using namespace WebCore;
36
37 namespace WebKit {
38
39 void BackingStore::paint(PlatformGraphicsContext context, const IntRect& rect)
40 {
41     if (m_cgLayer) {
42         CGContextSaveGState(context);
43         CGContextClipToRect(context, rect);
44
45         CGContextScaleCTM(context, 1, -1);
46         CGContextDrawLayerAtPoint(context, CGPointMake(0, -m_size.height()), m_cgLayer.get());
47
48         CGContextRestoreGState(context);
49         return;
50     }
51
52     ASSERT(m_bitmapContext);
53     paintBitmapContext(context, m_bitmapContext.get(), rect.location(), rect);
54 }
55
56 CGContextRef BackingStore::backingStoreContext()
57 {
58     if (m_cgLayer)
59         return CGLayerGetContext(m_cgLayer.get());
60
61     // Try to create a layer.
62     if (CGContextRef containingWindowContext = m_webPageProxy->containingWindowGraphicsContext()) {
63         m_cgLayer.adoptCF(CGLayerCreateWithContext(containingWindowContext, NSSizeToCGSize(m_size), 0));
64         CGContextRef layerContext = CGLayerGetContext(m_cgLayer.get());
65         
66         CGContextSetBlendMode(layerContext, kCGBlendModeCopy);
67
68         // We want the origin to be in the top left corner so flip the backing store context.
69         CGContextTranslateCTM(layerContext, 0, m_size.height());
70         CGContextScaleCTM(layerContext, 1, -1);
71
72         if (m_bitmapContext) {
73             // Paint the contents of the bitmap into the layer context.
74             paintBitmapContext(layerContext, m_bitmapContext.get(), CGPointZero, CGRectMake(0, 0, m_size.width(), m_size.height()));
75             m_bitmapContext = nullptr;
76         }
77
78         return layerContext;
79     }
80
81     if (!m_bitmapContext) {
82         RetainPtr<CGColorSpaceRef> colorSpace(AdoptCF, CGColorSpaceCreateDeviceRGB());
83         
84         m_bitmapContext.adoptCF(CGBitmapContextCreate(0, m_size.width(), m_size.height(), 8, m_size.width() * 4, colorSpace.get(), kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Host));
85
86         CGContextSetBlendMode(m_bitmapContext.get(), kCGBlendModeCopy);
87
88         // We want the origin to be in the top left corner so flip the backing store context.
89         CGContextTranslateCTM(m_bitmapContext.get(), 0, m_size.height());
90         CGContextScaleCTM(m_bitmapContext.get(), 1, -1);
91     }
92
93     return m_bitmapContext.get();
94 }
95
96 void BackingStore::incorporateUpdate(ShareableBitmap* bitmap, const UpdateInfo& updateInfo)
97 {
98     CGContextRef context = backingStoreContext();
99
100     scroll(updateInfo.scrollRect, updateInfo.scrollOffset);
101
102     IntPoint updateRectLocation = updateInfo.updateRectBounds.location();
103
104     GraphicsContext graphicsContext(context);
105
106     // Paint all update rects.
107     for (size_t i = 0; i < updateInfo.updateRects.size(); ++i) {
108         IntRect updateRect = updateInfo.updateRects[i];
109         IntRect srcRect = updateRect;
110         srcRect.move(-updateRectLocation.x(), -updateRectLocation.y());
111
112         bitmap->paint(graphicsContext, updateInfo.deviceScaleFactor, updateRect.location(), srcRect);
113     }
114 }
115
116 void BackingStore::scroll(const IntRect& scrollRect, const IntSize& scrollOffset)
117 {
118     if (scrollOffset.isZero())
119         return;
120
121     if (m_cgLayer) {
122         CGContextRef layerContext = CGLayerGetContext(m_cgLayer.get());
123
124         // Scroll the layer by painting it into itself with the given offset.
125         CGContextSaveGState(layerContext);
126         CGContextClipToRect(layerContext, scrollRect);
127         CGContextScaleCTM(layerContext, 1, -1);
128         CGContextDrawLayerAtPoint(layerContext, CGPointMake(scrollOffset.width(), -m_size.height() - scrollOffset.height()), m_cgLayer.get());
129         CGContextRestoreGState(layerContext);
130
131         return;
132     }
133
134     ASSERT(m_bitmapContext);
135
136     CGContextSaveGState(m_bitmapContext.get());
137     CGContextClipToRect(m_bitmapContext.get(), scrollRect);
138     CGPoint destination = CGPointMake(scrollRect.x() + scrollOffset.width(), scrollRect.y() + scrollOffset.height());
139     paintBitmapContext(m_bitmapContext.get(), m_bitmapContext.get(), destination, scrollRect);
140     CGContextRestoreGState(m_bitmapContext.get());
141 }
142
143 } // namespace WebKit