2 * Copyright (C) 2012 Google Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
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.
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.
28 #include "Canvas2DLayerBridge.h"
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>
38 using WebKit::WebExternalTextureLayer;
39 using WebKit::WebGraphicsContext3D;
40 using WebKit::WebTextureUpdater;
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)
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();
72 m_layer = WebExternalTextureLayer::create(this);
73 m_layer.setTextureId(textureId);
74 m_layer.setRateLimitContext(!WebKit::WebCompositor::threadingEnabled() || m_useDoubleBuffering);
77 Canvas2DLayerBridge::~Canvas2DLayerBridge()
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));
87 m_layer.clearClient();
90 SkDeferredCanvas* Canvas2DLayerBridge::deferredCanvas()
92 if (m_deferralMode == Deferred)
93 return static_cast<SkDeferredCanvas*>(m_canvas);
97 void Canvas2DLayerBridge::prepareForDraw()
99 ASSERT(deferredCanvas());
100 if (!m_useDoubleBuffering)
101 m_layer.willModifyTexture();
102 m_context->makeContextCurrent();
105 SkCanvas* Canvas2DLayerBridge::skCanvas(SkDevice* device)
108 if (m_deferralMode == Deferred) {
109 SkDeferredCanvas* deferred = new SkDeferredCanvas(device);
110 deferred->setNotificationClient(this);
113 m_canvas = new SkCanvas(device);
119 unsigned Canvas2DLayerBridge::prepareTexture(WebTextureUpdater& updater)
121 m_context->makeContextCurrent();
124 TRACE_EVENT0("cc", "Canvas2DLayerBridge::SkCanvas::flush");
130 if (m_useDoubleBuffering) {
131 updater.appendCopy(m_backBufferTexture, m_frontBufferTexture, m_size);
132 return m_frontBufferTexture;
136 // Notify skia that the state of the backing store texture object will be touched by the compositor
137 GrRenderTarget* renderTarget = reinterpret_cast<GrRenderTarget*>(m_canvas->getDevice()->accessRenderTarget());
139 renderTarget->asTexture()->invalidateCachedState();
141 return m_backBufferTexture;
144 WebGraphicsContext3D* Canvas2DLayerBridge::context()
146 return GraphicsContext3DPrivate::extractWebGraphicsContext3D(m_context.get());
149 WebKit::WebLayer* Canvas2DLayerBridge::layer()
154 void Canvas2DLayerBridge::contextAcquired()
156 if (m_deferralMode == NonDeferred && !m_useDoubleBuffering)
157 m_layer.willModifyTexture();
160 unsigned Canvas2DLayerBridge::backBufferTexture()
166 return m_backBufferTexture;