tizen beta release
[framework/web/webkit-efl.git] / Source / WebCore / platform / graphics / chromium / cc / CCPluginLayerImpl.cpp
1 /*
2  * Copyright (C) 2011 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 #if USE(ACCELERATED_COMPOSITING)
29
30 #include "cc/CCPluginLayerImpl.h"
31
32 #include "Extensions3DChromium.h"
33 #include "GraphicsContext3D.h"
34 #include "LayerRendererChromium.h"
35 #include "cc/CCProxy.h"
36 #include <wtf/text/WTFString.h>
37
38 namespace {
39
40 struct PluginProgramBinding {
41     template<class Program> void set(Program* program)
42     {
43         ASSERT(program && program->initialized());
44         programId = program->program();
45         samplerLocation = program->fragmentShader().samplerLocation();
46         matrixLocation = program->vertexShader().matrixLocation();
47         alphaLocation = program->fragmentShader().alphaLocation();
48     }
49     int programId;
50     int samplerLocation;
51     int matrixLocation;
52     int alphaLocation;
53 };
54
55 struct TexStretchPluginProgramBinding : PluginProgramBinding {
56     template<class Program> void set(Program* program)
57     {
58         PluginProgramBinding::set(program);
59         offsetLocation = program->vertexShader().offsetLocation();
60         scaleLocation = program->vertexShader().scaleLocation();
61     }
62     int offsetLocation;
63     int scaleLocation;
64 };
65
66 struct TexTransformPluginProgramBinding : PluginProgramBinding {
67     template<class Program> void set(Program* program)
68     {
69         PluginProgramBinding::set(program);
70         texTransformLocation = program->vertexShader().texTransformLocation();
71     }
72     int texTransformLocation;
73 };
74
75 } // anonymous namespace
76
77 namespace WebCore {
78
79 CCPluginLayerImpl::CCPluginLayerImpl(int id)
80     : CCLayerImpl(id)
81     , m_textureId(0)
82     , m_flipped(true)
83     , m_uvRect(0, 0, 1, 1)
84     , m_ioSurfaceId(0)
85     , m_ioSurfaceWidth(0)
86     , m_ioSurfaceHeight(0)
87     , m_ioSurfaceChanged(false)
88     , m_ioSurfaceTextureId(0)
89 {
90 }
91
92 CCPluginLayerImpl::~CCPluginLayerImpl()
93 {
94     cleanupResources();
95 }
96
97 void CCPluginLayerImpl::draw(LayerRendererChromium* layerRenderer)
98 {
99     ASSERT(CCProxy::isImplThread());
100
101     if (m_ioSurfaceChanged) {
102         GraphicsContext3D* context = layerRenderer->context();
103         Extensions3DChromium* extensions = static_cast<Extensions3DChromium*>(context->getExtensions());
104         ASSERT(extensions->supports("GL_CHROMIUM_iosurface"));
105         ASSERT(extensions->supports("GL_ARB_texture_rectangle"));
106
107         if (!m_ioSurfaceTextureId)
108             m_ioSurfaceTextureId = context->createTexture();
109
110         GLC(context, context->activeTexture(GraphicsContext3D::TEXTURE0));
111         GLC(context, context->bindTexture(Extensions3D::TEXTURE_RECTANGLE_ARB, m_ioSurfaceTextureId));
112         GLC(context, context->texParameteri(Extensions3D::TEXTURE_RECTANGLE_ARB, GraphicsContext3D::TEXTURE_MIN_FILTER, GraphicsContext3D::LINEAR));
113         GLC(context, context->texParameteri(Extensions3D::TEXTURE_RECTANGLE_ARB, GraphicsContext3D::TEXTURE_MAG_FILTER, GraphicsContext3D::LINEAR));
114         GLC(context, context->texParameteri(Extensions3D::TEXTURE_RECTANGLE_ARB, GraphicsContext3D::TEXTURE_WRAP_S, GraphicsContext3D::CLAMP_TO_EDGE));
115         GLC(context, context->texParameteri(Extensions3D::TEXTURE_RECTANGLE_ARB, GraphicsContext3D::TEXTURE_WRAP_T, GraphicsContext3D::CLAMP_TO_EDGE));
116         extensions->texImageIOSurface2DCHROMIUM(Extensions3D::TEXTURE_RECTANGLE_ARB,
117                                                 m_ioSurfaceWidth,
118                                                 m_ioSurfaceHeight,
119                                                 m_ioSurfaceId,
120                                                 0);
121         // Do not check for error conditions. texImageIOSurface2DCHROMIUM is supposed to hold on to
122         // the last good IOSurface if the new one is already closed. This is only a possibility
123         // during live resizing of plugins. However, it seems that this is not sufficient to
124         // completely guard against garbage being drawn. If this is found to be a significant issue,
125         // it may be necessary to explicitly tell the embedder when to free the surfaces it has
126         // allocated.
127         m_ioSurfaceChanged = false;
128     }
129
130     if (m_ioSurfaceTextureId) {
131         TexTransformPluginProgramBinding binding;
132         if (m_flipped)
133             binding.set(layerRenderer->pluginLayerTexRectProgramFlip());
134         else
135             binding.set(layerRenderer->pluginLayerTexRectProgram());
136
137         GraphicsContext3D* context = layerRenderer->context();
138         GLC(context, context->activeTexture(GraphicsContext3D::TEXTURE0));
139         GLC(context, context->bindTexture(Extensions3D::TEXTURE_RECTANGLE_ARB, m_ioSurfaceTextureId));
140
141         GLC(context, context->useProgram(binding.programId));
142         GLC(context, context->uniform1i(binding.samplerLocation, 0));
143         // Note: this code path ignores m_uvRect.
144         GLC(context, context->uniform4f(binding.texTransformLocation, 0, 0, m_ioSurfaceWidth, m_ioSurfaceHeight));
145         layerRenderer->drawTexturedQuad(drawTransform(), bounds().width(), bounds().height(), drawOpacity(), layerRenderer->sharedGeometryQuad(),
146                                         binding.matrixLocation,
147                                         binding.alphaLocation,
148                                         -1);
149         GLC(context, context->bindTexture(Extensions3D::TEXTURE_RECTANGLE_ARB, 0));
150     } else {
151         TexStretchPluginProgramBinding binding;
152         if (m_flipped)
153             binding.set(layerRenderer->pluginLayerProgramFlip());
154         else
155             binding.set(layerRenderer->pluginLayerProgram());
156
157         GraphicsContext3D* context = layerRenderer->context();
158         GLC(context, context->activeTexture(GraphicsContext3D::TEXTURE0));
159         GLC(context, context->bindTexture(GraphicsContext3D::TEXTURE_2D, m_textureId));
160
161         // FIXME: setting the texture parameters every time is redundant. Move this code somewhere
162         // where it will only happen once per texture.
163         GLC(context, context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_MIN_FILTER, GraphicsContext3D::LINEAR));
164         GLC(context, context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_MAG_FILTER, GraphicsContext3D::LINEAR));
165         GLC(context, context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_WRAP_S, GraphicsContext3D::CLAMP_TO_EDGE));
166         GLC(context, context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_WRAP_T, GraphicsContext3D::CLAMP_TO_EDGE));
167
168         GLC(context, context->useProgram(binding.programId));
169         GLC(context, context->uniform1i(binding.samplerLocation, 0));
170         GLC(context, context->uniform2f(binding.offsetLocation, m_uvRect.x(), m_uvRect.y()));
171         GLC(context, context->uniform2f(binding.scaleLocation, m_uvRect.width(), m_uvRect.height()));
172         layerRenderer->drawTexturedQuad(drawTransform(), bounds().width(), bounds().height(), drawOpacity(), layerRenderer->sharedGeometryQuad(),
173                                         binding.matrixLocation,
174                                         binding.alphaLocation,
175                                         -1);
176     }
177 }
178
179
180 void CCPluginLayerImpl::dumpLayerProperties(TextStream& ts, int indent) const
181 {
182     writeIndent(ts, indent);
183     ts << "plugin layer texture id: " << m_textureId << "\n";
184     CCLayerImpl::dumpLayerProperties(ts, indent);
185 }
186
187 void CCPluginLayerImpl::setIOSurfaceProperties(int width, int height, uint32_t ioSurfaceId)
188 {
189     if (m_ioSurfaceId != ioSurfaceId)
190         m_ioSurfaceChanged = true;
191
192     m_ioSurfaceWidth = width;
193     m_ioSurfaceHeight = height;
194     m_ioSurfaceId = ioSurfaceId;
195 }
196
197 void CCPluginLayerImpl::cleanupResources()
198 {
199     // FIXME: it seems there is no layer renderer / GraphicsContext3D available here. Ideally we
200     // would like to delete m_ioSurfaceTextureId.
201     m_ioSurfaceTextureId = 0;
202 }
203
204 } // namespace WebCore
205
206 #endif // USE(ACCELERATED_COMPOSITING)