diff options
author | Steve Block <steveblock@google.com> | 2011-05-25 19:08:45 +0100 |
---|---|---|
committer | Steve Block <steveblock@google.com> | 2011-06-08 13:51:31 +0100 |
commit | 2bde8e466a4451c7319e3a072d118917957d6554 (patch) | |
tree | 28f4a1b869a513e565c7760d0e6a06e7cf1fe95a /Source/WebCore/platform/graphics/chromium/VideoLayerChromium.cpp | |
parent | 6939c99b71d9372d14a0c74a772108052e8c48c8 (diff) | |
download | external_webkit-2bde8e466a4451c7319e3a072d118917957d6554.zip external_webkit-2bde8e466a4451c7319e3a072d118917957d6554.tar.gz external_webkit-2bde8e466a4451c7319e3a072d118917957d6554.tar.bz2 |
Merge WebKit at r82507: Initial merge by git
Change-Id: I60ce9d780725b58b45e54165733a8ffee23b683e
Diffstat (limited to 'Source/WebCore/platform/graphics/chromium/VideoLayerChromium.cpp')
-rw-r--r-- | Source/WebCore/platform/graphics/chromium/VideoLayerChromium.cpp | 227 |
1 files changed, 89 insertions, 138 deletions
diff --git a/Source/WebCore/platform/graphics/chromium/VideoLayerChromium.cpp b/Source/WebCore/platform/graphics/chromium/VideoLayerChromium.cpp index 5d7a6e7..182e730 100644 --- a/Source/WebCore/platform/graphics/chromium/VideoLayerChromium.cpp +++ b/Source/WebCore/platform/graphics/chromium/VideoLayerChromium.cpp @@ -33,7 +33,6 @@ #if USE(ACCELERATED_COMPOSITING) #include "VideoLayerChromium.h" -#include "cc/CCLayerImpl.h" #include "Extensions3DChromium.h" #include "GraphicsContext3D.h" #include "LayerRendererChromium.h" @@ -41,17 +40,11 @@ #include "RenderLayerBacking.h" #include "VideoFrameChromium.h" #include "VideoFrameProvider.h" +#include "cc/CCLayerImpl.h" +#include "cc/CCVideoLayerImpl.h" namespace WebCore { -// These values are magic numbers that are used in the transformation -// from YUV to RGB color values. -const float VideoLayerChromium::yuv2RGB[9] = { - 1.f, 1.f, 1.f, - 0.f, -.344f, 1.772f, - 1.403f, -.714f, 0.f, -}; - PassRefPtr<VideoLayerChromium> VideoLayerChromium::create(GraphicsLayerChromium* owner, VideoFrameProvider* provider) { @@ -71,23 +64,37 @@ VideoLayerChromium::VideoLayerChromium(GraphicsLayerChromium* owner, VideoFrameP VideoLayerChromium::~VideoLayerChromium() { cleanupResources(); + deleteTexturesInUse(); } -void VideoLayerChromium::cleanupResources() +PassRefPtr<CCLayerImpl> VideoLayerChromium::createCCLayerImpl() +{ + return CCVideoLayerImpl::create(this); +} + +void VideoLayerChromium::deleteTexturesInUse() { - LayerChromium::cleanupResources(); - releaseCurrentFrame(); if (!layerRenderer()) return; GraphicsContext3D* context = layerRendererContext(); for (unsigned plane = 0; plane < VideoFrameChromium::maxPlanes; plane++) { - if (m_textures[plane]) - GLC(context, context->deleteTexture(m_textures[plane])); + Texture texture = m_textures[plane]; + if (!texture.isEmpty && texture.ownedByLayerRenderer) + GLC(context, context->deleteTexture(texture.id)); } } -void VideoLayerChromium::updateContentsIfDirty() +void VideoLayerChromium::cleanupResources() +{ + LayerChromium::cleanupResources(); + if (m_currentFrame) + releaseCurrentFrame(); + else + resetFrameParameters(); +} + +void VideoLayerChromium::updateCompositorResources() { if (!m_contentsDirty) return; @@ -116,6 +123,9 @@ void VideoLayerChromium::updateContentsIfDirty() return; } + // If the incoming frame is backed by a texture (i.e. decoded in hardware), + // then we do not need to allocate a texture via the layer renderer. Instead + // we save the texture data then exit. if (frame->surfaceType() == VideoFrameChromium::TypeTexture) { releaseCurrentFrame(); saveCurrentFrame(frame); @@ -136,8 +146,9 @@ void VideoLayerChromium::updateContentsIfDirty() // Update texture planes. for (unsigned plane = 0; plane < frame->planes(); plane++) { - ASSERT(frame->requiredTextureSize(plane) == m_textureSizes[plane]); - updateTexture(context, m_textures[plane], frame->requiredTextureSize(plane), textureFormat, frame->data(plane)); + Texture texture = m_textures[plane]; + ASSERT(frame->requiredTextureSize(plane) == texture.size); + updateTexture(context, texture.id, texture.size, textureFormat, frame->data(plane)); } m_dirtyRect.setSize(FloatSize()); @@ -146,7 +157,19 @@ void VideoLayerChromium::updateContentsIfDirty() m_provider->putCurrentFrame(frame); } -unsigned VideoLayerChromium::determineTextureFormat(VideoFrameChromium* frame) +void VideoLayerChromium::pushPropertiesTo(CCLayerImpl* layer) +{ + LayerChromium::pushPropertiesTo(layer); + + CCVideoLayerImpl* videoLayer = static_cast<CCVideoLayerImpl*>(layer); + videoLayer->setSkipsDraw(m_skipsDraw); + videoLayer->setFrameFormat(m_frameFormat); + for (size_t i = 0; i < 3; ++i) + videoLayer->setTexture(i, m_textures[i]); +} + + +unsigned VideoLayerChromium::determineTextureFormat(const VideoFrameChromium* frame) { switch (frame->format()) { case VideoFrameChromium::YV12: @@ -160,56 +183,68 @@ unsigned VideoLayerChromium::determineTextureFormat(VideoFrameChromium* frame) return GraphicsContext3D::INVALID_VALUE; } -bool VideoLayerChromium::allocateTexturesIfNeeded(GraphicsContext3D* context, VideoFrameChromium* frame, unsigned textureFormat) +bool VideoLayerChromium::allocateTexturesIfNeeded(GraphicsContext3D* context, const VideoFrameChromium* frame, unsigned textureFormat) { ASSERT(context); ASSERT(frame); for (unsigned plane = 0; plane < frame->planes(); plane++) { - IntSize planeTextureSize = frame->requiredTextureSize(plane); + IntSize requiredTextureSize = frame->requiredTextureSize(plane); + Texture texture = m_textures[plane]; // If the renderer cannot handle this large of a texture, return false. // FIXME: Remove this test when tiled layers are implemented. - if (!layerRenderer()->checkTextureSize(planeTextureSize)) + if (!layerRenderer()->checkTextureSize(requiredTextureSize)) return false; - if (!m_textures[plane]) - m_textures[plane] = layerRenderer()->createLayerTexture(); - - if (!planeTextureSize.isZero() && planeTextureSize != m_textureSizes[plane]) { - allocateTexture(context, m_textures[plane], planeTextureSize, textureFormat); - m_textureSizes[plane] = planeTextureSize; - int frameWidth = frame->width(plane); - int frameHeight = frame->height(plane); - // When there are dead pixels at the edge of the texture, decrease - // the frame width by 1 to prevent the rightmost pixels from - // interpolating with the dead pixels. - if (frame->hasPaddingBytes(plane)) - --frameWidth; - m_frameSizes[plane] = IntSize(frameWidth, frameHeight); + if (texture.isEmpty) { + texture.id = layerRenderer()->createLayerTexture(); + texture.ownedByLayerRenderer = true; + texture.isEmpty = false; + } + + if (!requiredTextureSize.isZero() && requiredTextureSize != texture.size) { + allocateTexture(context, texture.id, requiredTextureSize, textureFormat); + texture.size = requiredTextureSize; + texture.visibleSize = computeVisibleSize(frame, plane); } + m_textures[plane] = texture; } + return true; +} + +IntSize VideoLayerChromium::computeVisibleSize(const VideoFrameChromium* frame, unsigned plane) +{ + int visibleWidth = frame->width(plane); + int visibleHeight = frame->height(plane); + // When there are dead pixels at the edge of the texture, decrease + // the frame width by 1 to prevent the rightmost pixels from + // interpolating with the dead pixels. + if (frame->hasPaddingBytes(plane)) + --visibleWidth; + // In YV12, every 2x2 square of Y values corresponds to one U and // one V value. If we decrease the width of the UV plane, we must decrease the // width of the Y texture by 2 for proper alignment. This must happen // always, even if Y's texture does not have padding bytes. - if (frame->format() == VideoFrameChromium::YV12) { - int yPlaneOriginalWidth = frame->width(VideoFrameChromium::yPlane); - if (frame->hasPaddingBytes(VideoFrameChromium::uPlane)) - m_frameSizes[VideoFrameChromium::yPlane].setWidth(yPlaneOriginalWidth - 2); + if (plane == VideoFrameChromium::yPlane && frame->format() == VideoFrameChromium::YV12) { + if (frame->hasPaddingBytes(VideoFrameChromium::uPlane)) { + int originalWidth = frame->width(plane); + visibleWidth = originalWidth - 2; + } } - return true; + return IntSize(visibleWidth, visibleHeight); } -void VideoLayerChromium::allocateTexture(GraphicsContext3D* context, unsigned textureId, const IntSize& dimensions, unsigned textureFormat) +void VideoLayerChromium::allocateTexture(GraphicsContext3D* context, unsigned textureId, const IntSize& dimensions, unsigned textureFormat) const { GLC(context, context->bindTexture(GraphicsContext3D::TEXTURE_2D, textureId)); GLC(context, context->texImage2DResourceSafe(GraphicsContext3D::TEXTURE_2D, 0, textureFormat, dimensions.width(), dimensions.height(), 0, textureFormat, GraphicsContext3D::UNSIGNED_BYTE)); } -void VideoLayerChromium::updateTexture(GraphicsContext3D* context, unsigned textureId, const IntSize& dimensions, unsigned format, const void* data) +void VideoLayerChromium::updateTexture(GraphicsContext3D* context, unsigned textureId, const IntSize& dimensions, unsigned format, const void* data) const { ASSERT(context); GLC(context, context->bindTexture(GraphicsContext3D::TEXTURE_2D, textureId)); @@ -225,33 +260,6 @@ void VideoLayerChromium::updateTexture(GraphicsContext3D* context, unsigned text } } -void VideoLayerChromium::draw() -{ - if (m_skipsDraw) - return; - - ASSERT(layerRenderer()); - const RGBAProgram* rgbaProgram = layerRenderer()->videoLayerRGBAProgram(); - ASSERT(rgbaProgram && rgbaProgram->initialized()); - const YUVProgram* yuvProgram = layerRenderer()->videoLayerYUVProgram(); - ASSERT(yuvProgram && yuvProgram->initialized()); - - switch (m_frameFormat) { - case VideoFrameChromium::YV12: - case VideoFrameChromium::YV16: - drawYUV(yuvProgram); - break; - case VideoFrameChromium::RGBA: - drawRGBA(rgbaProgram); - break; - default: - // FIXME: Implement other paths. - notImplemented(); - break; - } - releaseCurrentFrame(); -} - void VideoLayerChromium::releaseCurrentFrame() { if (!m_currentFrame) @@ -262,86 +270,29 @@ void VideoLayerChromium::releaseCurrentFrame() resetFrameParameters(); } -void VideoLayerChromium::drawYUV(const VideoLayerChromium::YUVProgram* program) -{ - GraphicsContext3D* context = layerRendererContext(); - GLC(context, context->activeTexture(GraphicsContext3D::TEXTURE1)); - GLC(context, context->bindTexture(GraphicsContext3D::TEXTURE_2D, m_textures[VideoFrameChromium::yPlane])); - GLC(context, context->activeTexture(GraphicsContext3D::TEXTURE2)); - GLC(context, context->bindTexture(GraphicsContext3D::TEXTURE_2D, m_textures[VideoFrameChromium::uPlane])); - GLC(context, context->activeTexture(GraphicsContext3D::TEXTURE3)); - GLC(context, context->bindTexture(GraphicsContext3D::TEXTURE_2D, m_textures[VideoFrameChromium::vPlane])); - - layerRenderer()->useShader(program->program()); - unsigned yFrameWidth = m_frameSizes[VideoFrameChromium::yPlane].width(); - unsigned yTextureWidth = m_textureSizes[VideoFrameChromium::yPlane].width(); - // Arbitrarily take the u sizes because u and v dimensions are identical. - unsigned uvFrameWidth = m_frameSizes[VideoFrameChromium::uPlane].width(); - unsigned uvTextureWidth = m_textureSizes[VideoFrameChromium::uPlane].width(); - - float yWidthScaleFactor = static_cast<float>(yFrameWidth) / yTextureWidth; - float uvWidthScaleFactor = static_cast<float>(uvFrameWidth) / uvTextureWidth; - GLC(context, context->uniform1f(program->vertexShader().yWidthScaleFactorLocation(), yWidthScaleFactor)); - GLC(context, context->uniform1f(program->vertexShader().uvWidthScaleFactorLocation(), uvWidthScaleFactor)); - - GLC(context, context->uniform1i(program->fragmentShader().yTextureLocation(), 1)); - GLC(context, context->uniform1i(program->fragmentShader().uTextureLocation(), 2)); - GLC(context, context->uniform1i(program->fragmentShader().vTextureLocation(), 3)); - - // This value of 0.5 maps to 128. It is used in the YUV to RGB conversion - // formula to turn unsigned u and v values to signed u and v values. - // This is loaded as a uniform because certain drivers have problems - // reading literal float values. - GLC(context, context->uniform1f(program->fragmentShader().signAdjLocation(), 0.5)); - - GLC(context, context->uniformMatrix3fv(program->fragmentShader().ccMatrixLocation(), 0, const_cast<float*>(yuv2RGB), 1)); - - drawTexturedQuad(context, layerRenderer()->projectionMatrix(), ccLayerImpl()->drawTransform(), - bounds().width(), bounds().height(), ccLayerImpl()->drawOpacity(), - program->vertexShader().matrixLocation(), - program->fragmentShader().alphaLocation()); - - // Reset active texture back to texture 0. - GLC(context, context->activeTexture(GraphicsContext3D::TEXTURE0)); -} - -void VideoLayerChromium::drawRGBA(const VideoLayerChromium::RGBAProgram* program) -{ - GraphicsContext3D* context = layerRendererContext(); - GLC(context, context->activeTexture(GraphicsContext3D::TEXTURE0)); - GLC(context, context->bindTexture(GraphicsContext3D::TEXTURE_2D, m_textures[VideoFrameChromium::rgbPlane])); - - layerRenderer()->useShader(program->program()); - unsigned frameWidth = m_frameSizes[VideoFrameChromium::rgbPlane].width(); - unsigned textureWidth = m_textureSizes[VideoFrameChromium::rgbPlane].width(); - float widthScaleFactor = static_cast<float>(frameWidth) / textureWidth; - GLC(context, context->uniform4f(program->vertexShader().texTransformLocation(), 0, 0, widthScaleFactor, 1)); - - GLC(context, context->uniform1i(program->fragmentShader().samplerLocation(), 0)); - - drawTexturedQuad(context, layerRenderer()->projectionMatrix(), ccLayerImpl()->drawTransform(), - bounds().width(), bounds().height(), ccLayerImpl()->drawOpacity(), - program->vertexShader().matrixLocation(), - program->fragmentShader().alphaLocation()); -} - void VideoLayerChromium::resetFrameParameters() { + deleteTexturesInUse(); for (unsigned plane = 0; plane < VideoFrameChromium::maxPlanes; plane++) { - m_textures[plane] = 0; - m_textureSizes[plane] = IntSize(); - m_frameSizes[plane] = IntSize(); + m_textures[plane].id = 0; + m_textures[plane].size = IntSize(); + m_textures[plane].visibleSize = IntSize(); + m_textures[plane].ownedByLayerRenderer = false; + m_textures[plane].isEmpty = true; } } void VideoLayerChromium::saveCurrentFrame(VideoFrameChromium* frame) { ASSERT(!m_currentFrame); + deleteTexturesInUse(); m_currentFrame = frame; for (unsigned plane = 0; plane < frame->planes(); plane++) { - m_textures[plane] = frame->texture(plane); - m_textureSizes[plane] = frame->requiredTextureSize(plane); - m_frameSizes[plane] = m_textureSizes[plane]; + m_textures[plane].id = frame->texture(plane); + m_textures[plane].size = frame->requiredTextureSize(plane); + m_textures[plane].visibleSize = computeVisibleSize(frame, plane); + m_textures[plane].ownedByLayerRenderer = false; + m_textures[plane].isEmpty = false; } } |