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 = adoptPtr(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));
89 SkDeferredCanvas* Canvas2DLayerBridge::deferredCanvas()
91 if (m_deferralMode == Deferred)
92 return static_cast<SkDeferredCanvas*>(m_canvas);
96 void Canvas2DLayerBridge::prepareForDraw()
98 ASSERT(deferredCanvas());
99 if (!m_useDoubleBuffering)
100 m_layer->willModifyTexture();
101 m_context->makeContextCurrent();
104 SkCanvas* Canvas2DLayerBridge::skCanvas(SkDevice* device)
107 if (m_deferralMode == Deferred) {
108 SkDeferredCanvas* deferred = new SkDeferredCanvas(device);
109 deferred->setNotificationClient(this);
112 m_canvas = new SkCanvas(device);
118 unsigned Canvas2DLayerBridge::prepareTexture(WebTextureUpdater& updater)
120 m_context->makeContextCurrent();
123 TRACE_EVENT0("cc", "Canvas2DLayerBridge::SkCanvas::flush");
129 if (m_useDoubleBuffering) {
130 updater.appendCopy(m_backBufferTexture, m_frontBufferTexture, m_size);
131 return m_frontBufferTexture;
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());
138 renderTarget->asTexture()->invalidateCachedState();
140 return m_backBufferTexture;
143 WebGraphicsContext3D* Canvas2DLayerBridge::context()
145 return GraphicsContext3DPrivate::extractWebGraphicsContext3D(m_context.get());
148 WebKit::WebLayer* Canvas2DLayerBridge::layer()
150 return m_layer->layer();
153 void Canvas2DLayerBridge::contextAcquired()
155 if (m_deferralMode == NonDeferred && !m_useDoubleBuffering)
156 m_layer->willModifyTexture();
159 unsigned Canvas2DLayerBridge::backBufferTexture()
165 return m_backBufferTexture;