2 * Copyright (C) 2010 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 are
8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above
11 * copyright notice, this list of conditions and the following disclaimer
12 * in the documentation and/or other materials provided with the
14 * * Neither the name of Google Inc. nor the names of its
15 * contributors may be used to endorse or promote products derived from
16 * this software without specific prior written permission.
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 #if USE(ACCELERATED_COMPOSITING)
34 #include "VideoLayerChromium.h"
36 #include "Extensions3DChromium.h"
37 #include "GraphicsContext3D.h"
38 #include "LayerRendererChromium.h"
39 #include "NotImplemented.h"
40 #include "VideoFrameChromium.h"
41 #include "VideoFrameProvider.h"
42 #include "cc/CCLayerImpl.h"
43 #include "cc/CCVideoLayerImpl.h"
47 PassRefPtr<VideoLayerChromium> VideoLayerChromium::create(CCLayerDelegate* delegate,
48 VideoFrameProvider* provider)
50 return adoptRef(new VideoLayerChromium(delegate, provider));
53 VideoLayerChromium::VideoLayerChromium(CCLayerDelegate* delegate, VideoFrameProvider* provider)
54 : LayerChromium(delegate)
56 , m_frameFormat(VideoFrameChromium::Invalid)
57 , m_provider(provider)
62 VideoLayerChromium::~VideoLayerChromium()
67 PassRefPtr<CCLayerImpl> VideoLayerChromium::createCCLayerImpl()
69 return CCVideoLayerImpl::create(m_layerId);
72 void VideoLayerChromium::cleanupResources()
74 LayerChromium::cleanupResources();
75 for (size_t i = 0; i < 3; ++i)
76 m_textures[i].m_texture.clear();
77 releaseCurrentFrame();
80 void VideoLayerChromium::updateCompositorResources(GraphicsContext3D* context)
82 if (!m_contentsDirty || !m_delegate)
85 ASSERT(drawsContent());
88 VideoFrameChromium* frame = m_provider->getCurrentFrame();
91 m_provider->putCurrentFrame(frame);
95 m_frameFormat = frame->format();
96 GC3Denum textureFormat = determineTextureFormat(frame);
97 if (textureFormat == GraphicsContext3D::INVALID_VALUE) {
98 // FIXME: Implement other paths.
101 m_provider->putCurrentFrame(frame);
105 // Allocate textures for planes if they are not allocated already, or
106 // reallocate textures that are the wrong size for the frame.
107 bool texturesReserved = reserveTextures(frame, textureFormat);
108 if (!texturesReserved) {
110 m_provider->putCurrentFrame(frame);
114 // Update texture planes.
115 for (unsigned plane = 0; plane < frame->planes(); plane++) {
116 Texture& texture = m_textures[plane];
117 ASSERT(texture.m_texture);
118 ASSERT(frame->requiredTextureSize(plane) == texture.m_texture->size());
119 updateTexture(context, texture, frame->data(plane));
122 m_dirtyRect.setSize(FloatSize());
123 m_contentsDirty = false;
125 m_provider->putCurrentFrame(frame);
128 void VideoLayerChromium::pushPropertiesTo(CCLayerImpl* layer)
130 LayerChromium::pushPropertiesTo(layer);
132 CCVideoLayerImpl* videoLayer = static_cast<CCVideoLayerImpl*>(layer);
133 videoLayer->setSkipsDraw(m_skipsDraw);
134 videoLayer->setFrameFormat(m_frameFormat);
135 for (size_t i = 0; i < 3; ++i) {
136 if (!m_textures[i].m_texture) {
137 videoLayer->setSkipsDraw(true);
140 videoLayer->setTexture(i, m_textures[i].m_texture->textureId(), m_textures[i].m_texture->size(), m_textures[i].m_visibleSize);
144 void VideoLayerChromium::setLayerTreeHost(CCLayerTreeHost* host)
146 if (host && layerTreeHost() != host) {
147 for (size_t i = 0; i < 3; ++i) {
148 m_textures[i].m_visibleSize = IntSize();
149 m_textures[i].m_texture = ManagedTexture::create(host->contentsTextureManager());
153 LayerChromium::setLayerTreeHost(host);
156 GC3Denum VideoLayerChromium::determineTextureFormat(const VideoFrameChromium* frame)
158 switch (frame->format()) {
159 case VideoFrameChromium::YV12:
160 case VideoFrameChromium::YV16:
161 return GraphicsContext3D::LUMINANCE;
162 case VideoFrameChromium::RGBA:
163 return GraphicsContext3D::RGBA;
167 return GraphicsContext3D::INVALID_VALUE;
170 bool VideoLayerChromium::reserveTextures(const VideoFrameChromium* frame, GC3Denum textureFormat)
172 ASSERT(layerTreeHost());
174 ASSERT(textureFormat != GraphicsContext3D::INVALID_VALUE);
176 int maxTextureSize = layerTreeHost()->layerRendererCapabilities().maxTextureSize;
178 for (unsigned plane = 0; plane < frame->planes(); plane++) {
179 IntSize requiredTextureSize = frame->requiredTextureSize(plane);
181 // If the renderer cannot handle this large of a texture, return false.
182 // FIXME: Remove this test when tiled layers are implemented.
183 if (requiredTextureSize.isZero() || requiredTextureSize.width() > maxTextureSize || requiredTextureSize.height() > maxTextureSize)
186 if (!m_textures[plane].m_texture)
189 if (m_textures[plane].m_texture->size() != requiredTextureSize)
190 m_textures[plane].m_visibleSize = computeVisibleSize(frame, plane);
192 m_textures[plane].m_texture->reserve(requiredTextureSize, textureFormat);
198 IntSize VideoLayerChromium::computeVisibleSize(const VideoFrameChromium* frame, unsigned plane)
200 int visibleWidth = frame->width(plane);
201 int visibleHeight = frame->height(plane);
202 // When there are dead pixels at the edge of the texture, decrease
203 // the frame width by 1 to prevent the rightmost pixels from
204 // interpolating with the dead pixels.
205 if (frame->hasPaddingBytes(plane))
208 // In YV12, every 2x2 square of Y values corresponds to one U and
209 // one V value. If we decrease the width of the UV plane, we must decrease the
210 // width of the Y texture by 2 for proper alignment. This must happen
211 // always, even if Y's texture does not have padding bytes.
212 if (plane == VideoFrameChromium::yPlane && frame->format() == VideoFrameChromium::YV12) {
213 if (frame->hasPaddingBytes(VideoFrameChromium::uPlane)) {
214 int originalWidth = frame->width(plane);
215 visibleWidth = originalWidth - 2;
219 return IntSize(visibleWidth, visibleHeight);
222 void VideoLayerChromium::updateTexture(GraphicsContext3D* context, Texture& texture, const void* data) const
225 ASSERT(texture.m_texture);
227 texture.m_texture->bindTexture(context);
229 GC3Denum format = texture.m_texture->format();
230 IntSize dimensions = texture.m_texture->size();
232 void* mem = static_cast<Extensions3DChromium*>(context->getExtensions())->mapTexSubImage2DCHROMIUM(GraphicsContext3D::TEXTURE_2D, 0, 0, 0, dimensions.width(), dimensions.height(), format, GraphicsContext3D::UNSIGNED_BYTE, Extensions3DChromium::WRITE_ONLY);
234 memcpy(mem, data, dimensions.width() * dimensions.height());
235 GLC(context, static_cast<Extensions3DChromium*>(context->getExtensions())->unmapTexSubImage2DCHROMIUM(mem));
237 // If mapTexSubImage2DCHROMIUM fails, then do the slower texSubImage2D
238 // upload. This does twice the copies as mapTexSubImage2DCHROMIUM, one
239 // in the command buffer and another to the texture.
240 GLC(context, context->texSubImage2D(GraphicsContext3D::TEXTURE_2D, 0, 0, 0, dimensions.width(), dimensions.height(), format, GraphicsContext3D::UNSIGNED_BYTE, data));
244 void VideoLayerChromium::releaseCurrentFrame()
249 m_provider->putCurrentFrame(m_currentFrame);
253 } // namespace WebCore
255 #endif // USE(ACCELERATED_COMPOSITING)