[chromium] Change WebLayer from a concrete type to a pure virtual interface
[WebKit-https.git] / Source / WebCore / platform / graphics / chromium / Canvas2DLayerBridge.cpp
1 /*
2  * Copyright (C) 2012 Google 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  *
8  * 1.  Redistributions of source code must retain the above copyright
9  *     notice, this list of conditions and the following disclaimer.
10  * 2.  Redistributions in binary form must reproduce the above copyright
11  *     notice, this list of conditions and the following disclaimer in the
12  *     documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
15  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
16  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
17  * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
18  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
19  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
20  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
21  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
23  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24  */
25
26 #include "config.h"
27
28 #include "Canvas2DLayerBridge.h"
29
30 #include "GrContext.h"
31 #include "GraphicsContext3D.h"
32 #include "GraphicsContext3DPrivate.h"
33 #include "LayerRendererChromium.h" // For GLC() macro.
34 #include "TraceEvent.h"
35 #include <public/WebCompositor.h>
36 #include <public/WebGraphicsContext3D.h>
37
38 using WebKit::WebExternalTextureLayer;
39 using WebKit::WebGraphicsContext3D;
40 using WebKit::WebTextureUpdater;
41
42 namespace WebCore {
43
44 Canvas2DLayerBridge::Canvas2DLayerBridge(PassRefPtr<GraphicsContext3D> context, const IntSize& size, DeferralMode deferralMode, unsigned textureId)
45     : m_deferralMode(deferralMode)
46     // FIXME: We currently turn off double buffering when canvas rendering is
47     // deferred. What we should be doing is to use a smarter heuristic based
48     // on GPU resource monitoring and other factors to chose between single
49     // and double buffering.
50     , m_useDoubleBuffering(WebKit::WebCompositor::threadingEnabled() && deferralMode == NonDeferred)
51     , m_frontBufferTexture(0)
52     , m_backBufferTexture(textureId)
53     , m_size(size)
54     , m_canvas(0)
55     , m_context(context)
56 {
57     if (m_useDoubleBuffering) {
58         m_context->makeContextCurrent();
59         GLC(m_context.get(), m_frontBufferTexture = m_context->createTexture());
60         GLC(m_context.get(), m_context->bindTexture(GraphicsContext3D::TEXTURE_2D, m_frontBufferTexture));
61         // Do basic linear filtering on resize.
62         GLC(m_context.get(), m_context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_MIN_FILTER, GraphicsContext3D::LINEAR));
63         GLC(m_context.get(), m_context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_MAG_FILTER, GraphicsContext3D::LINEAR));
64         // NPOT textures in GL ES only work when the wrap mode is set to GraphicsContext3D::CLAMP_TO_EDGE.
65         GLC(m_context.get(), m_context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_WRAP_S, GraphicsContext3D::CLAMP_TO_EDGE));
66         GLC(m_context.get(), m_context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_WRAP_T, GraphicsContext3D::CLAMP_TO_EDGE));
67         GLC(m_context.get(), m_context->texImage2DResourceSafe(GraphicsContext3D::TEXTURE_2D, 0, GraphicsContext3D::RGBA, size.width(), size.height(), 0, GraphicsContext3D::RGBA, GraphicsContext3D::UNSIGNED_BYTE));
68         if (GrContext* grContext = m_context->grContext())
69             grContext->resetContext();
70     }
71
72     m_layer = adoptPtr(WebExternalTextureLayer::create(this));
73     m_layer->setTextureId(textureId);
74     m_layer->setRateLimitContext(!WebKit::WebCompositor::threadingEnabled() || m_useDoubleBuffering);
75 }
76
77 Canvas2DLayerBridge::~Canvas2DLayerBridge()
78 {
79     if (SkDeferredCanvas* deferred = deferredCanvas())
80         deferred->setNotificationClient(0);
81     m_layer->setTextureId(0);
82     if (m_useDoubleBuffering) {
83         m_context->makeContextCurrent();
84         GLC(m_context.get(), m_context->deleteTexture(m_frontBufferTexture));
85         m_context->flush();
86     }
87 }
88
89 SkDeferredCanvas* Canvas2DLayerBridge::deferredCanvas()
90 {
91     if (m_deferralMode == Deferred)
92         return static_cast<SkDeferredCanvas*>(m_canvas);
93     return 0;
94 }
95
96 void Canvas2DLayerBridge::prepareForDraw()
97 {
98     ASSERT(deferredCanvas());
99     if (!m_useDoubleBuffering)
100         m_layer->willModifyTexture();
101     m_context->makeContextCurrent();
102 }
103
104 SkCanvas* Canvas2DLayerBridge::skCanvas(SkDevice* device)
105 {
106     ASSERT(!m_canvas);
107     if (m_deferralMode == Deferred) {
108         SkDeferredCanvas* deferred = new SkDeferredCanvas(device);
109         deferred->setNotificationClient(this);
110         m_canvas = deferred;
111     } else
112         m_canvas = new SkCanvas(device);
113
114     return m_canvas;
115 }
116
117
118 unsigned Canvas2DLayerBridge::prepareTexture(WebTextureUpdater& updater)
119 {
120     m_context->makeContextCurrent();
121
122     if (m_canvas) {
123         TRACE_EVENT0("cc", "Canvas2DLayerBridge::SkCanvas::flush");
124         m_canvas->flush();
125     }
126
127     m_context->flush();
128
129     if (m_useDoubleBuffering) {
130         updater.appendCopy(m_backBufferTexture, m_frontBufferTexture, m_size);
131         return m_frontBufferTexture;
132     }
133
134     if (m_canvas) {
135         // Notify skia that the state of the backing store texture object will be touched by the compositor
136         GrRenderTarget* renderTarget = reinterpret_cast<GrRenderTarget*>(m_canvas->getDevice()->accessRenderTarget());
137         if (renderTarget)
138             renderTarget->asTexture()->invalidateCachedState();
139     }
140     return m_backBufferTexture;
141 }
142
143 WebGraphicsContext3D* Canvas2DLayerBridge::context()
144 {
145     return GraphicsContext3DPrivate::extractWebGraphicsContext3D(m_context.get());
146 }
147
148 WebKit::WebLayer* Canvas2DLayerBridge::layer()
149 {
150     return m_layer->layer();
151 }
152
153 void Canvas2DLayerBridge::contextAcquired()
154 {
155     if (m_deferralMode == NonDeferred && !m_useDoubleBuffering)
156         m_layer->willModifyTexture();
157 }
158
159 unsigned Canvas2DLayerBridge::backBufferTexture()
160 {
161     contextAcquired();
162     if (m_canvas)
163         m_canvas->flush();
164     m_context->flush();
165     return m_backBufferTexture;
166 }
167
168 }
169