diff options
author | Ben Murdoch <benm@google.com> | 2011-05-24 11:24:40 +0100 |
---|---|---|
committer | Ben Murdoch <benm@google.com> | 2011-06-02 09:53:15 +0100 |
commit | 81bc750723a18f21cd17d1b173cd2a4dda9cea6e (patch) | |
tree | 7a9e5ed86ff429fd347a25153107221543909b19 /Source/WebCore/platform/graphics/chromium | |
parent | 94088a6d336c1dd80a1e734af51e96abcbb689a7 (diff) | |
download | external_webkit-81bc750723a18f21cd17d1b173cd2a4dda9cea6e.zip external_webkit-81bc750723a18f21cd17d1b173cd2a4dda9cea6e.tar.gz external_webkit-81bc750723a18f21cd17d1b173cd2a4dda9cea6e.tar.bz2 |
Merge WebKit at r80534: Intial merge by Git
Change-Id: Ia7a83357124c9e1cdb1debf55d9661ec0bd09a61
Diffstat (limited to 'Source/WebCore/platform/graphics/chromium')
43 files changed, 2873 insertions, 1383 deletions
diff --git a/Source/WebCore/platform/graphics/chromium/Canvas2DLayerChromium.h b/Source/WebCore/platform/graphics/chromium/Canvas2DLayerChromium.h index 44ef050..a14cb98 100644 --- a/Source/WebCore/platform/graphics/chromium/Canvas2DLayerChromium.h +++ b/Source/WebCore/platform/graphics/chromium/Canvas2DLayerChromium.h @@ -45,7 +45,7 @@ class Canvas2DLayerChromium : public CanvasLayerChromium { public: static PassRefPtr<Canvas2DLayerChromium> create(DrawingBuffer*, GraphicsLayerChromium* owner); virtual ~Canvas2DLayerChromium(); - virtual bool drawsContent() { return true; } + virtual bool drawsContent() const { return true; } virtual void updateContentsIfDirty(); void setTextureChanged(); diff --git a/Source/WebCore/platform/graphics/chromium/CanvasLayerChromium.cpp b/Source/WebCore/platform/graphics/chromium/CanvasLayerChromium.cpp index 4aef25b..0264868 100644 --- a/Source/WebCore/platform/graphics/chromium/CanvasLayerChromium.cpp +++ b/Source/WebCore/platform/graphics/chromium/CanvasLayerChromium.cpp @@ -34,6 +34,7 @@ #include "CanvasLayerChromium.h" +#include "cc/CCLayerImpl.h" #include "GraphicsContext3D.h" #include "LayerRendererChromium.h" @@ -41,64 +42,11 @@ namespace WebCore { unsigned CanvasLayerChromium::m_shaderProgramId = 0; -CanvasLayerChromium::SharedValues::SharedValues(GraphicsContext3D* context) - : m_context(context) - , m_canvasShaderProgram(0) - , m_shaderSamplerLocation(-1) - , m_shaderMatrixLocation(-1) - , m_shaderAlphaLocation(-1) - , m_initialized(false) -{ - char vertexShaderString[] = - "attribute vec4 a_position; \n" - "attribute vec2 a_texCoord; \n" - "uniform mat4 matrix; \n" - "varying vec2 v_texCoord; \n" - "void main() \n" - "{ \n" - " gl_Position = matrix * a_position; \n" - " v_texCoord = a_texCoord; \n" - "} \n"; - - // Canvas layers need to be flipped vertically and their colors shouldn't be - // swizzled. - char fragmentShaderString[] = - "precision mediump float; \n" - "varying vec2 v_texCoord; \n" - "uniform sampler2D s_texture; \n" - "uniform float alpha; \n" - "void main() \n" - "{ \n" - " vec4 texColor = texture2D(s_texture, vec2(v_texCoord.x, 1.0 - v_texCoord.y)); \n" - " gl_FragColor = vec4(texColor.x, texColor.y, texColor.z, texColor.w) * alpha; \n" - "} \n"; - - m_canvasShaderProgram = createShaderProgram(m_context, vertexShaderString, fragmentShaderString); - if (!m_canvasShaderProgram) { - LOG_ERROR("CanvasLayerChromium: Failed to create shader program"); - return; - } - - m_shaderSamplerLocation = m_context->getUniformLocation(m_canvasShaderProgram, "s_texture"); - m_shaderMatrixLocation = m_context->getUniformLocation(m_canvasShaderProgram, "matrix"); - m_shaderAlphaLocation = m_context->getUniformLocation(m_canvasShaderProgram, "alpha"); - ASSERT(m_shaderSamplerLocation != -1); - ASSERT(m_shaderMatrixLocation != -1); - ASSERT(m_shaderAlphaLocation != -1); - - m_initialized = true; -} - -CanvasLayerChromium::SharedValues::~SharedValues() -{ - if (m_canvasShaderProgram) - GLC(m_context, m_context->deleteProgram(m_canvasShaderProgram)); -} - CanvasLayerChromium::CanvasLayerChromium(GraphicsLayerChromium* owner) : LayerChromium(owner) , m_textureChanged(true) , m_textureId(0) + , m_premultipliedAlpha(true) { } @@ -109,17 +57,19 @@ CanvasLayerChromium::~CanvasLayerChromium() void CanvasLayerChromium::draw() { ASSERT(layerRenderer()); - const CanvasLayerChromium::SharedValues* sv = layerRenderer()->canvasLayerSharedValues(); - ASSERT(sv && sv->initialized()); + const CanvasLayerChromium::Program* program = layerRenderer()->canvasLayerProgram(); + ASSERT(program && program->initialized()); GraphicsContext3D* context = layerRendererContext(); GLC(context, context->activeTexture(GraphicsContext3D::TEXTURE0)); GLC(context, context->bindTexture(GraphicsContext3D::TEXTURE_2D, m_textureId)); - layerRenderer()->useShader(sv->canvasShaderProgram()); - GLC(context, context->uniform1i(sv->shaderSamplerLocation(), 0)); - drawTexturedQuad(context, layerRenderer()->projectionMatrix(), drawTransform(), - bounds().width(), bounds().height(), drawOpacity(), - sv->shaderMatrixLocation(), sv->shaderAlphaLocation()); - + GC3Denum sfactor = m_premultipliedAlpha ? GraphicsContext3D::ONE : GraphicsContext3D::SRC_ALPHA; + GLC(context, context->blendFunc(sfactor, GraphicsContext3D::ONE_MINUS_SRC_ALPHA)); + layerRenderer()->useShader(program->program()); + 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()); } } diff --git a/Source/WebCore/platform/graphics/chromium/CanvasLayerChromium.h b/Source/WebCore/platform/graphics/chromium/CanvasLayerChromium.h index 6520b55..ed3a06f 100644 --- a/Source/WebCore/platform/graphics/chromium/CanvasLayerChromium.h +++ b/Source/WebCore/platform/graphics/chromium/CanvasLayerChromium.h @@ -45,30 +45,16 @@ public: virtual void draw(); - class SharedValues { - public: - explicit SharedValues(GraphicsContext3D*); - ~SharedValues(); - - unsigned canvasShaderProgram() const { return m_canvasShaderProgram; } - int shaderSamplerLocation() const { return m_shaderSamplerLocation; } - int shaderMatrixLocation() const { return m_shaderMatrixLocation; } - int shaderAlphaLocation() const { return m_shaderAlphaLocation; } - bool initialized() const { return m_initialized; } - - private: - GraphicsContext3D* m_context; - unsigned m_canvasShaderProgram; - int m_shaderSamplerLocation; - int m_shaderMatrixLocation; - int m_shaderAlphaLocation; - bool m_initialized; - }; + typedef ProgramBinding<VertexShaderPosTex, FragmentShaderRGBATexFlipAlpha> Program; protected: explicit CanvasLayerChromium(GraphicsLayerChromium* owner); + + virtual const char* layerTypeAsString() const { return "CanvasLayer"; } + bool m_textureChanged; unsigned m_textureId; + bool m_premultipliedAlpha; private: static unsigned m_shaderProgramId; diff --git a/Source/WebCore/platform/graphics/chromium/ContentLayerChromium.cpp b/Source/WebCore/platform/graphics/chromium/ContentLayerChromium.cpp index a38f6bd..78f93d5 100644 --- a/Source/WebCore/platform/graphics/chromium/ContentLayerChromium.cpp +++ b/Source/WebCore/platform/graphics/chromium/ContentLayerChromium.cpp @@ -34,97 +34,15 @@ #include "ContentLayerChromium.h" +#include "cc/CCLayerImpl.h" #include "GraphicsContext3D.h" #include "LayerRendererChromium.h" #include "LayerTexture.h" #include "RenderLayerBacking.h" - -#if PLATFORM(SKIA) -#include "NativeImageSkia.h" -#include "PlatformContextSkia.h" -#include "SkColorPriv.h" -#include "skia/ext/platform_canvas.h" -#elif PLATFORM(CG) -#include <CoreGraphics/CGBitmapContext.h> -#endif +#include "TextStream.h" namespace WebCore { -ContentLayerChromium::SharedValues::SharedValues(GraphicsContext3D* context) - : m_context(context) - , m_contentShaderProgram(0) - , m_shaderSamplerLocation(-1) - , m_shaderMatrixLocation(-1) - , m_shaderAlphaLocation(-1) - , m_initialized(false) -{ - // Shaders for drawing the layer contents. - char vertexShaderString[] = - "attribute vec4 a_position; \n" - "attribute vec2 a_texCoord; \n" - "uniform mat4 matrix; \n" - "varying vec2 v_texCoord; \n" - "void main() \n" - "{ \n" - " gl_Position = matrix * a_position; \n" - " v_texCoord = a_texCoord; \n" - "} \n"; - -#if PLATFORM(SKIA) - // Color is in RGBA order. - char rgbaFragmentShaderString[] = - "precision mediump float; \n" - "varying vec2 v_texCoord; \n" - "uniform sampler2D s_texture; \n" - "uniform float alpha; \n" - "void main() \n" - "{ \n" - " vec4 texColor = texture2D(s_texture, v_texCoord); \n" - " gl_FragColor = texColor * alpha; \n" - "} \n"; -#endif - - // Color is in BGRA order. - char bgraFragmentShaderString[] = - "precision mediump float; \n" - "varying vec2 v_texCoord; \n" - "uniform sampler2D s_texture; \n" - "uniform float alpha; \n" - "void main() \n" - "{ \n" - " vec4 texColor = texture2D(s_texture, v_texCoord); \n" - " gl_FragColor = vec4(texColor.z, texColor.y, texColor.x, texColor.w) * alpha; \n" - "} \n"; - -#if PLATFORM(SKIA) - // Assuming the packing is either Skia default RGBA or Chromium default BGRA. - char* fragmentShaderString = SK_B32_SHIFT ? rgbaFragmentShaderString : bgraFragmentShaderString; -#else - char* fragmentShaderString = bgraFragmentShaderString; -#endif - m_contentShaderProgram = createShaderProgram(m_context, vertexShaderString, fragmentShaderString); - if (!m_contentShaderProgram) { - LOG_ERROR("ContentLayerChromium: Failed to create shader program"); - return; - } - - m_shaderSamplerLocation = m_context->getUniformLocation(m_contentShaderProgram, "s_texture"); - m_shaderMatrixLocation = m_context->getUniformLocation(m_contentShaderProgram, "matrix"); - m_shaderAlphaLocation = m_context->getUniformLocation(m_contentShaderProgram, "alpha"); - ASSERT(m_shaderSamplerLocation != -1); - ASSERT(m_shaderMatrixLocation != -1); - ASSERT(m_shaderAlphaLocation != -1); - - m_initialized = true; -} - -ContentLayerChromium::SharedValues::~SharedValues() -{ - if (m_contentShaderProgram) - GLC(m_context, m_context->deleteProgram(m_contentShaderProgram)); -} - - PassRefPtr<ContentLayerChromium> ContentLayerChromium::create(GraphicsLayerChromium* owner) { return adoptRef(new ContentLayerChromium(owner)); @@ -154,9 +72,9 @@ bool ContentLayerChromium::requiresClippedUpdateRect() const // one of the layer's dimensions is larger than 2000 pixels or the size of // surface it's rendering into. This is a temporary measure until layer tiling is implemented. static const int maxLayerSize = 2000; - return (m_bounds.width() > max(maxLayerSize, m_targetRenderSurface->contentRect().width()) - || m_bounds.height() > max(maxLayerSize, m_targetRenderSurface->contentRect().height()) - || !layerRenderer()->checkTextureSize(m_bounds)); + return (bounds().width() > max(maxLayerSize, ccLayerImpl()->targetRenderSurface()->contentRect().width()) + || bounds().height() > max(maxLayerSize, ccLayerImpl()->targetRenderSurface()->contentRect().height()) + || !layerRenderer()->checkTextureSize(bounds())); } void ContentLayerChromium::updateContentsIfDirty() @@ -169,28 +87,25 @@ void ContentLayerChromium::updateContentsIfDirty() ASSERT(layerRenderer()); - void* pixels = 0; IntRect dirtyRect; - IntRect updateRect; - IntSize requiredTextureSize; - IntSize bitmapSize; - IntRect boundsRect(IntPoint(0, 0), m_bounds); + IntRect boundsRect(IntPoint(0, 0), bounds()); + IntPoint paintingOffset; // FIXME: Remove this test when tiled layers are implemented. if (requiresClippedUpdateRect()) { // A layer with 3D transforms could require an arbitrarily large number // of texels to be repainted, so ignore these layers until tiling is // implemented. - if (!drawTransform().isIdentityOrTranslation()) { + if (!ccLayerImpl()->drawTransform().isIdentityOrTranslation()) { m_skipsDraw = true; return; } // Calculate the region of this layer that is currently visible. - const IntRect clipRect = m_targetRenderSurface->contentRect(); + const IntRect clipRect = ccLayerImpl()->targetRenderSurface()->contentRect(); - TransformationMatrix layerOriginTransform = drawTransform(); - layerOriginTransform.translate3d(-0.5 * m_bounds.width(), -0.5 * m_bounds.height(), 0); + TransformationMatrix layerOriginTransform = ccLayerImpl()->drawTransform(); + layerOriginTransform.translate3d(-0.5 * bounds().width(), -0.5 * bounds().height(), 0); // For now we apply the large layer treatment only for layers that are either untransformed // or are purely translated. Their matrix is expected to be invertible. @@ -198,7 +113,7 @@ void ContentLayerChromium::updateContentsIfDirty() TransformationMatrix targetToLayerMatrix = layerOriginTransform.inverse(); IntRect visibleRectInLayerCoords = targetToLayerMatrix.mapRect(clipRect); - visibleRectInLayerCoords.intersect(IntRect(0, 0, m_bounds.width(), m_bounds.height())); + visibleRectInLayerCoords.intersect(IntRect(0, 0, bounds().width(), bounds().height())); // For normal layers, the center of the texture corresponds with the center of the layer. // In large layers the center of the texture is the center of the visible region so we have @@ -212,9 +127,13 @@ void ContentLayerChromium::updateContentsIfDirty() return; } - // If the visible portion of the layer is different from the last upload, or if our backing - // texture has been evicted, then the whole layer is considered dirty. - if (visibleRectInLayerCoords != m_visibleRectInLayerCoords || !m_contentsTexture || !m_contentsTexture->isValid(requiredTextureSize, GraphicsContext3D::RGBA)) + // If we need to resize the upload buffer we have to repaint everything. + if (m_canvas.size() != visibleRectInLayerCoords.size()) { + resizeUploadBuffer(visibleRectInLayerCoords.size()); + m_dirtyRect = boundsRect; + } + // If the visible portion of the layer is different from the last upload. + if (visibleRectInLayerCoords != m_visibleRectInLayerCoords) m_dirtyRect = boundsRect; m_visibleRectInLayerCoords = visibleRectInLayerCoords; @@ -224,92 +143,52 @@ void ContentLayerChromium::updateContentsIfDirty() // What the rectangles mean: // dirtyRect: The region of this layer that will be updated. - // updateRect: The region of the layer's texture that will be uploaded into. - // requiredTextureSize: is the required size of this layer's texture. + // m_uploadUpdateRect: The region of the layer's texture that will be uploaded into. dirtyRect = visibleDirtyRectInLayerSpace; - updateRect = dirtyRect; + m_uploadUpdateRect = dirtyRect; IntSize visibleRectOffsetInLayerCoords(visibleRectInLayerCoords.x(), visibleRectInLayerCoords.y()); - updateRect.move(-visibleRectOffsetInLayerCoords); - requiredTextureSize = visibleRectInLayerCoords.size(); + paintingOffset = IntPoint(visibleRectOffsetInLayerCoords); + m_uploadUpdateRect.move(-visibleRectOffsetInLayerCoords); } else { dirtyRect = IntRect(m_dirtyRect); - requiredTextureSize = m_bounds; // If the texture needs to be reallocated then we must redraw the entire // contents of the layer. - if (!m_contentsTexture || !m_contentsTexture->isValid(requiredTextureSize, GraphicsContext3D::RGBA)) + if (m_canvas.size() != bounds()) { + resizeUploadBuffer(bounds()); dirtyRect = boundsRect; - else { + } else { // Clip the dirtyRect to the size of the layer to avoid drawing // outside the bounds of the backing texture. dirtyRect.intersect(boundsRect); } - updateRect = dirtyRect; + m_uploadUpdateRect = dirtyRect; } if (dirtyRect.isEmpty()) return; -#if PLATFORM(SKIA) - const SkBitmap* skiaBitmap = 0; - OwnPtr<skia::PlatformCanvas> canvas; - OwnPtr<PlatformContextSkia> skiaContext; - OwnPtr<GraphicsContext> graphicsContext; - - canvas.set(new skia::PlatformCanvas(dirtyRect.width(), dirtyRect.height(), false)); - skiaContext.set(new PlatformContextSkia(canvas.get())); - - // This is needed to get text to show up correctly. - // FIXME: Does this take us down a very slow text rendering path? - skiaContext->setDrawingToImageBuffer(true); - - graphicsContext.set(new GraphicsContext(reinterpret_cast<PlatformGraphicsContext*>(skiaContext.get()))); + PlatformCanvas::Painter painter(&m_canvas); + painter.context()->save(); + painter.context()->translate(-paintingOffset.x(), -paintingOffset.y()); + painter.context()->clearRect(dirtyRect); + painter.context()->clip(dirtyRect); - // Bring the canvas into the coordinate system of the paint rect. - canvas->translate(static_cast<SkScalar>(-dirtyRect.x()), static_cast<SkScalar>(-dirtyRect.y())); + m_owner->paintGraphicsLayerContents(*painter.context(), dirtyRect); + painter.context()->restore(); +} - m_owner->paintGraphicsLayerContents(*graphicsContext, dirtyRect); - const SkBitmap& bitmap = canvas->getDevice()->accessBitmap(false); - skiaBitmap = &bitmap; - ASSERT(skiaBitmap); +void ContentLayerChromium::resizeUploadBuffer(const IntSize& size) +{ + m_canvas.resize(size); +} - SkAutoLockPixels lock(*skiaBitmap); - SkBitmap::Config skiaConfig = skiaBitmap->config(); - // FIXME: do we need to support more image configurations? - if (skiaConfig == SkBitmap::kARGB_8888_Config) { - pixels = skiaBitmap->getPixels(); - bitmapSize = IntSize(skiaBitmap->width(), skiaBitmap->height()); - } -#elif PLATFORM(CG) - Vector<uint8_t> tempVector; - int rowBytes = 4 * dirtyRect.width(); - tempVector.resize(rowBytes * dirtyRect.height()); - memset(tempVector.data(), 0, tempVector.size()); - RetainPtr<CGColorSpaceRef> colorSpace(AdoptCF, CGColorSpaceCreateDeviceRGB()); - RetainPtr<CGContextRef> contextCG(AdoptCF, CGBitmapContextCreate(tempVector.data(), - dirtyRect.width(), dirtyRect.height(), 8, rowBytes, - colorSpace.get(), - kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Host)); - CGContextTranslateCTM(contextCG.get(), 0, dirtyRect.height()); - CGContextScaleCTM(contextCG.get(), 1, -1); - - GraphicsContext graphicsContext(contextCG.get()); - - // Translate the graphics context into the coordinate system of the dirty rect. - graphicsContext.translate(-dirtyRect.x(), -dirtyRect.y()); - - m_owner->paintGraphicsLayerContents(graphicsContext, dirtyRect); - - pixels = tempVector.data(); - bitmapSize = dirtyRect.size(); -#else -#error "Need to implement for your platform." -#endif - - if (pixels) - updateTextureRect(pixels, requiredTextureSize, updateRect); +void ContentLayerChromium::updateTextureIfNeeded() +{ + PlatformCanvas::AutoLocker locker(&m_canvas); + updateTexture(locker.pixels(), m_canvas.size()); } -void ContentLayerChromium::updateTextureRect(void* pixels, const IntSize& requiredTextureSize, const IntRect& updateRect) +void ContentLayerChromium::updateTexture(const uint8_t* pixels, const IntSize& size) { if (!pixels) return; @@ -318,15 +197,43 @@ void ContentLayerChromium::updateTextureRect(void* pixels, const IntSize& requir if (!m_contentsTexture) m_contentsTexture = LayerTexture::create(context, layerRenderer()->textureManager()); - if (!m_contentsTexture->reserve(requiredTextureSize, GraphicsContext3D::RGBA)) { + // If we have to allocate a new texture we have to upload the full contents. + if (!m_contentsTexture->isValid(size, GraphicsContext3D::RGBA)) + m_uploadUpdateRect = IntRect(IntPoint(0, 0), size); + + if (!m_contentsTexture->reserve(size, GraphicsContext3D::RGBA)) { m_skipsDraw = true; return; } - m_contentsTexture->bindTexture(); + IntRect srcRect = IntRect(IntPoint(0, 0), size); + if (requiresClippedUpdateRect()) + srcRect = m_visibleRectInLayerCoords; + + const size_t destStride = m_uploadUpdateRect.width() * 4; + const size_t srcStride = srcRect.width() * 4; + + const uint8_t* uploadPixels = pixels + srcStride * m_uploadUpdateRect.y(); + Vector<uint8_t> uploadBuffer; + if (srcStride != destStride || m_uploadUpdateRect.x()) { + uploadBuffer.resize(m_uploadUpdateRect.height() * destStride); + for (int row = 0; row < m_uploadUpdateRect.height(); ++row) { + size_t srcOffset = (m_uploadUpdateRect.y() + row) * srcStride + m_uploadUpdateRect.x() * 4; + ASSERT(srcOffset + destStride <= static_cast<size_t>(size.width() * size.height() * 4)); + size_t destOffset = row * destStride; + ASSERT(destOffset + destStride <= uploadBuffer.size()); + memcpy(uploadBuffer.data() + destOffset, pixels + srcOffset, destStride); + } + uploadPixels = uploadBuffer.data(); + } - GLC(context, context->texSubImage2D(GraphicsContext3D::TEXTURE_2D, 0, updateRect.x(), updateRect.y(), updateRect.width(), updateRect.height(), GraphicsContext3D::RGBA, GraphicsContext3D::UNSIGNED_BYTE, pixels)); + m_contentsTexture->bindTexture(); + GLC(context, context->texSubImage2D(GraphicsContext3D::TEXTURE_2D, 0, + m_uploadUpdateRect.x(), m_uploadUpdateRect.y(), m_uploadUpdateRect.width(), m_uploadUpdateRect.height(), + GraphicsContext3D::RGBA, GraphicsContext3D::UNSIGNED_BYTE, + uploadPixels)); + m_uploadUpdateRect = IntRect(); m_dirtyRect.setSize(FloatSize()); // Large layers always stay dirty, because they need to update when the content rect changes. m_contentsDirty = requiresClippedUpdateRect(); @@ -339,43 +246,59 @@ void ContentLayerChromium::draw() ASSERT(layerRenderer()); - const ContentLayerChromium::SharedValues* sv = layerRenderer()->contentLayerSharedValues(); - ASSERT(sv && sv->initialized()); + const ContentLayerChromium::Program* program = layerRenderer()->contentLayerProgram(); + ASSERT(program && program->initialized()); GraphicsContext3D* context = layerRendererContext(); GLC(context, context->activeTexture(GraphicsContext3D::TEXTURE0)); bindContentsTexture(); - layerRenderer()->useShader(sv->contentShaderProgram()); - GLC(context, context->uniform1i(sv->shaderSamplerLocation(), 0)); + layerRenderer()->useShader(program->program()); + GLC(context, context->uniform1i(program->fragmentShader().samplerLocation(), 0)); + GLC(context, context->blendFunc(GraphicsContext3D::ONE, GraphicsContext3D::ONE_MINUS_SRC_ALPHA)); if (requiresClippedUpdateRect()) { - float m43 = drawTransform().m43(); + float m43 = ccLayerImpl()->drawTransform().m43(); TransformationMatrix transform; transform.translate3d(m_layerCenterInSurfaceCoords.x(), m_layerCenterInSurfaceCoords.y(), m43); drawTexturedQuad(context, layerRenderer()->projectionMatrix(), transform, m_visibleRectInLayerCoords.width(), - m_visibleRectInLayerCoords.height(), drawOpacity(), - sv->shaderMatrixLocation(), sv->shaderAlphaLocation()); + m_visibleRectInLayerCoords.height(), ccLayerImpl()->drawOpacity(), + program->vertexShader().matrixLocation(), + program->fragmentShader().alphaLocation()); } else { drawTexturedQuad(context, layerRenderer()->projectionMatrix(), - drawTransform(), m_bounds.width(), m_bounds.height(), - drawOpacity(), sv->shaderMatrixLocation(), - sv->shaderAlphaLocation()); + ccLayerImpl()->drawTransform(), bounds().width(), bounds().height(), + ccLayerImpl()->drawOpacity(), program->vertexShader().matrixLocation(), + program->fragmentShader().alphaLocation()); } unreserveContentsTexture(); } void ContentLayerChromium::unreserveContentsTexture() { - if (m_contentsTexture) + if (!m_skipsDraw && m_contentsTexture) m_contentsTexture->unreserve(); } void ContentLayerChromium::bindContentsTexture() { - if (m_contentsTexture) + updateTextureIfNeeded(); + + if (!m_skipsDraw && m_contentsTexture) m_contentsTexture->bindTexture(); } +static void writeIndent(TextStream& ts, int indent) +{ + for (int i = 0; i != indent; ++i) + ts << " "; +} + +void ContentLayerChromium::dumpLayerProperties(TextStream& ts, int indent) const +{ + LayerChromium::dumpLayerProperties(ts, indent); + writeIndent(ts, indent); + ts << "skipsDraw: " << m_skipsDraw << "\n"; +} } #endif // USE(ACCELERATED_COMPOSITING) diff --git a/Source/WebCore/platform/graphics/chromium/ContentLayerChromium.h b/Source/WebCore/platform/graphics/chromium/ContentLayerChromium.h index 3363518..6f070c2 100644 --- a/Source/WebCore/platform/graphics/chromium/ContentLayerChromium.h +++ b/Source/WebCore/platform/graphics/chromium/ContentLayerChromium.h @@ -35,6 +35,7 @@ #if USE(ACCELERATED_COMPOSITING) #include "LayerChromium.h" +#include "PlatformCanvas.h" #include "TextureManager.h" namespace WebCore { @@ -54,43 +55,31 @@ public: virtual void bindContentsTexture(); virtual void draw(); - virtual bool drawsContent() { return m_owner && m_owner->drawsContent(); } - - // Stores values that are shared between instances of this class that are - // associated with the same LayerRendererChromium (and hence the same GL - // context). - class SharedValues { - public: - explicit SharedValues(GraphicsContext3D*); - ~SharedValues(); - - unsigned contentShaderProgram() const { return m_contentShaderProgram; } - int shaderSamplerLocation() const { return m_shaderSamplerLocation; } - int shaderMatrixLocation() const { return m_shaderMatrixLocation; } - int shaderAlphaLocation() const { return m_shaderAlphaLocation; } - int initialized() const { return m_initialized; } - - private: - GraphicsContext3D* m_context; - unsigned m_contentShaderProgram; - int m_shaderSamplerLocation; - int m_shaderMatrixLocation; - int m_shaderAlphaLocation; - int m_initialized; - }; + virtual bool drawsContent() const { return m_owner && m_owner->drawsContent(); } + + typedef ProgramBinding<VertexShaderPosTex, FragmentShaderTexAlpha> Program; protected: explicit ContentLayerChromium(GraphicsLayerChromium* owner); - void updateTextureRect(void* pixels, const IntSize& requiredTextureSize, const IntRect& updateRect); - virtual void cleanupResources(); bool requiresClippedUpdateRect() const; + void resizeUploadBuffer(const IntSize&); + + virtual const char* layerTypeAsString() const { return "ContentLayer"; } + virtual void dumpLayerProperties(TextStream&, int indent) const; OwnPtr<LayerTexture> m_contentsTexture; bool m_skipsDraw; + // The portion of the upload buffer that has a pending update, in the coordinates of the texture. + IntRect m_uploadUpdateRect; + + virtual void updateTextureIfNeeded(); + void updateTexture(const uint8_t* pixels, const IntSize&); + private: + PlatformCanvas m_canvas; IntRect m_visibleRectInLayerCoords; FloatPoint m_layerCenterInSurfaceCoords; diff --git a/Source/WebCore/platform/graphics/chromium/Extensions3DChromium.h b/Source/WebCore/platform/graphics/chromium/Extensions3DChromium.h index 92fb7b3..3b0fdbf 100644 --- a/Source/WebCore/platform/graphics/chromium/Extensions3DChromium.h +++ b/Source/WebCore/platform/graphics/chromium/Extensions3DChromium.h @@ -46,6 +46,10 @@ public: virtual int getGraphicsResetStatusARB(); virtual void blitFramebuffer(long srcX0, long srcY0, long srcX1, long srcY1, long dstX0, long dstY0, long dstX1, long dstY1, unsigned long mask, unsigned long filter); virtual void renderbufferStorageMultisample(unsigned long target, unsigned long samples, unsigned long internalformat, unsigned long width, unsigned long height); + virtual Platform3DObject createVertexArrayOES(); + virtual void deleteVertexArrayOES(Platform3DObject); + virtual GC3Dboolean isVertexArrayOES(Platform3DObject); + virtual void bindVertexArrayOES(Platform3DObject); enum { // GL_CHROMIUM_map_sub (enums inherited from GL_ARB_vertex_buffer_object) diff --git a/Source/WebCore/platform/graphics/chromium/FontCacheLinux.cpp b/Source/WebCore/platform/graphics/chromium/FontCacheLinux.cpp index a849a6c..bbe6d62 100644 --- a/Source/WebCore/platform/graphics/chromium/FontCacheLinux.cpp +++ b/Source/WebCore/platform/graphics/chromium/FontCacheLinux.cpp @@ -43,6 +43,7 @@ #include "SkTypeface.h" #include "SkUtils.h" +#include <unicode/locid.h> #include <wtf/Assertions.h> #include <wtf/text/AtomicString.h> #include <wtf/text/CString.h> @@ -57,7 +58,8 @@ const SimpleFontData* FontCache::getFontDataForCharacters(const Font& font, const UChar* characters, int length) { - String family = PlatformBridge::getFontFamilyForCharacters(characters, length); + icu::Locale locale = icu::Locale::getDefault(); + String family = PlatformBridge::getFontFamilyForCharacters(characters, length, locale.getLanguage()); if (family.isEmpty()) return 0; diff --git a/Source/WebCore/platform/graphics/chromium/GLES2Canvas.cpp b/Source/WebCore/platform/graphics/chromium/GLES2Canvas.cpp index 953ee2f..2ff6b8b 100644 --- a/Source/WebCore/platform/graphics/chromium/GLES2Canvas.cpp +++ b/Source/WebCore/platform/graphics/chromium/GLES2Canvas.cpp @@ -38,10 +38,12 @@ #include "GraphicsContext3D.h" #include "internal_glu.h" #include "IntRect.h" +#include "LoopBlinnPathProcessor.h" +#include "LoopBlinnSolidFillShader.h" #include "Path.h" #include "PlatformString.h" #include "SharedGraphicsContext3D.h" -#if PLATFORM(SKIA) +#if USE(SKIA) #include "SkPath.h" #endif #include "Texture.h" @@ -170,6 +172,7 @@ GLES2Canvas::GLES2Canvas(SharedGraphicsContext3D* context, DrawingBuffer* drawin , m_context(context) , m_drawingBuffer(drawingBuffer) , m_state(0) + , m_pathVertexBuffer(0) { m_flipMatrix.translate(-1.0f, 1.0f); m_flipMatrix.scale(2.0f / size.width(), -2.0f / size.height()); @@ -191,7 +194,7 @@ void GLES2Canvas::clearRect(const FloatRect& rect) { bindFramebuffer(); if (m_state->m_ctm.isIdentity() && !m_state->m_clippingEnabled) { - m_context->scissor(rect); + m_context->scissor(rect.x(), m_size.height() - rect.height() - rect.y(), rect.width(), rect.height()); m_context->enable(GraphicsContext3D::SCISSOR_TEST); m_context->clearColor(Color(RGBA32(0))); m_context->clear(GraphicsContext3D::COLOR_BUFFER_BIT); @@ -263,6 +266,11 @@ void GLES2Canvas::concatCTM(const AffineTransform& affine) m_state->m_ctm *= affine; } +void GLES2Canvas::setCTM(const AffineTransform& affine) +{ + m_state->m_ctm = affine; +} + void GLES2Canvas::clipPath(const Path& path) { bindFramebuffer(); @@ -396,9 +404,9 @@ Texture* GLES2Canvas::getTexture(NativeImagePtr ptr) return m_context->getTexture(ptr); } -#if PLATFORM(SKIA) +#if USE(SKIA) // This is actually cross-platform code, but since its only caller is inside a -// PLATFORM(SKIA), it will cause a warning-as-error on Chrome/Mac. +// USE(SKIA), it will cause a warning-as-error on Chrome/Mac. static void interpolateQuadratic(DoubleVector* vertices, const FloatPoint& p0, const FloatPoint& p1, const FloatPoint& p2) { float tIncrement = 1.0f / pathTesselation, t = tIncrement; @@ -473,7 +481,7 @@ void GLES2Canvas::createVertexBufferFromPath(const Path& path, int* count, unsig checkGLError("createVertexBufferFromPath, createBuffer"); DoubleVector inVertices; WTF::Vector<size_t> contours; -#if PLATFORM(SKIA) +#if USE(SKIA) const SkPath* skPath = path.platformPath(); SkPoint pts[4]; SkPath::Iter iter(*skPath, true); @@ -548,28 +556,61 @@ void GLES2Canvas::createVertexBufferFromPath(const Path& path, int* count, unsig void GLES2Canvas::fillPath(const Path& path, const Color& color) { - int count; - unsigned vertexBuffer, indexBuffer; - createVertexBufferFromPath(path, &count, &vertexBuffer, &indexBuffer); - m_context->graphicsContext3D()->bindBuffer(GraphicsContext3D::ARRAY_BUFFER, vertexBuffer); - checkGLError("bindBuffer"); - m_context->graphicsContext3D()->bindBuffer(GraphicsContext3D::ELEMENT_ARRAY_BUFFER, indexBuffer); - checkGLError("bindBuffer"); + if (SharedGraphicsContext3D::useLoopBlinnForPathRendering()) { + bindFramebuffer(); + m_context->applyCompositeOperator(m_state->m_compositeOp); + + m_pathCache.clear(); + LoopBlinnPathProcessor processor; + processor.process(path, m_pathCache); + if (!m_pathVertexBuffer) + m_pathVertexBuffer = m_context->createBuffer(); + m_context->bindBuffer(GraphicsContext3D::ARRAY_BUFFER, m_pathVertexBuffer); + int byteSizeOfVertices = 2 * m_pathCache.numberOfVertices() * sizeof(float); + int byteSizeOfTexCoords = 3 * m_pathCache.numberOfVertices() * sizeof(float); + int byteSizeOfInteriorVertices = 2 * m_pathCache.numberOfInteriorVertices() * sizeof(float); + m_context->bufferData(GraphicsContext3D::ARRAY_BUFFER, + byteSizeOfVertices + byteSizeOfTexCoords + byteSizeOfInteriorVertices, + GraphicsContext3D::STATIC_DRAW); + m_context->bufferSubData(GraphicsContext3D::ARRAY_BUFFER, 0, byteSizeOfVertices, m_pathCache.vertices()); + m_context->bufferSubData(GraphicsContext3D::ARRAY_BUFFER, byteSizeOfVertices, byteSizeOfTexCoords, m_pathCache.texcoords()); + m_context->bufferSubData(GraphicsContext3D::ARRAY_BUFFER, byteSizeOfVertices + byteSizeOfTexCoords, byteSizeOfInteriorVertices, m_pathCache.interiorVertices()); + + AffineTransform matrix(m_flipMatrix); + matrix *= m_state->m_ctm; + + // Draw the exterior + m_context->useLoopBlinnExteriorProgram(0, byteSizeOfVertices, matrix, color); + m_context->drawArrays(GraphicsContext3D::TRIANGLES, 0, m_pathCache.numberOfVertices()); + + // Draw the interior + m_context->useLoopBlinnInteriorProgram(byteSizeOfVertices + byteSizeOfTexCoords, matrix, color); + m_context->drawArrays(GraphicsContext3D::TRIANGLES, 0, m_pathCache.numberOfInteriorVertices()); + } else { + int count; + unsigned vertexBuffer, indexBuffer; + createVertexBufferFromPath(path, &count, &vertexBuffer, &indexBuffer); + m_context->graphicsContext3D()->bindBuffer(GraphicsContext3D::ARRAY_BUFFER, vertexBuffer); + checkGLError("bindBuffer"); + m_context->graphicsContext3D()->bindBuffer(GraphicsContext3D::ELEMENT_ARRAY_BUFFER, indexBuffer); + checkGLError("bindBuffer"); - AffineTransform matrix(m_flipMatrix); - matrix *= m_state->m_ctm; + AffineTransform matrix(m_flipMatrix); + matrix *= m_state->m_ctm; - m_context->useFillSolidProgram(matrix, color); - checkGLError("useFillSolidProgram"); + m_context->useFillSolidProgram(matrix, color); + checkGLError("useFillSolidProgram"); - m_context->graphicsContext3D()->drawElements(GraphicsContext3D::TRIANGLES, count, GraphicsContext3D::UNSIGNED_SHORT, 0); - checkGLError("drawArrays"); + bindFramebuffer(); + m_context->graphicsContext3D()->drawElements(GraphicsContext3D::TRIANGLES, count, GraphicsContext3D::UNSIGNED_SHORT, 0); + checkGLError("drawArrays"); - m_context->graphicsContext3D()->deleteBuffer(vertexBuffer); - checkGLError("deleteBuffer"); + m_context->graphicsContext3D()->deleteBuffer(vertexBuffer); + checkGLError("deleteBuffer"); - m_context->graphicsContext3D()->deleteBuffer(indexBuffer); - checkGLError("deleteBuffer"); + m_context->graphicsContext3D()->deleteBuffer(indexBuffer); + checkGLError("deleteBuffer"); + } } void GLES2Canvas::beginStencilDraw() diff --git a/Source/WebCore/platform/graphics/chromium/GLES2Canvas.h b/Source/WebCore/platform/graphics/chromium/GLES2Canvas.h index 605f86f..8887a16 100644 --- a/Source/WebCore/platform/graphics/chromium/GLES2Canvas.h +++ b/Source/WebCore/platform/graphics/chromium/GLES2Canvas.h @@ -36,6 +36,7 @@ #include "ColorSpace.h" #include "GraphicsTypes.h" #include "ImageSource.h" +#include "LoopBlinnPathCache.h" #include "Texture.h" #include <wtf/HashMap.h> @@ -68,6 +69,7 @@ public: void rotate(float angleInRadians); void scale(const FloatSize&); void concatCTM(const AffineTransform&); + void setCTM(const AffineTransform&); void clipPath(const Path&); void clipOut(const Path&); @@ -113,6 +115,10 @@ private: StateVector m_stateStack; State* m_state; AffineTransform m_flipMatrix; + + // Members for GPU-accelerated path rendering. + LoopBlinnPathCache m_pathCache; + unsigned m_pathVertexBuffer; }; } diff --git a/Source/WebCore/platform/graphics/chromium/GeometryBinding.cpp b/Source/WebCore/platform/graphics/chromium/GeometryBinding.cpp new file mode 100644 index 0000000..a859aae --- /dev/null +++ b/Source/WebCore/platform/graphics/chromium/GeometryBinding.cpp @@ -0,0 +1,82 @@ +/* + * Copyright (C) 2011 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" + +#if USE(ACCELERATED_COMPOSITING) + +#include "GeometryBinding.h" + +#include "GraphicsContext.h" +#include "GraphicsContext3D.h" +#include "LayerRendererChromium.h" + +namespace WebCore { + +GeometryBinding::GeometryBinding(GraphicsContext3D* context) + : m_context(context) + , m_quadVerticesVbo(0) + , m_quadElementsVbo(0) + , m_initialized(false) +{ + // Vertex positions and texture coordinates for the 4 corners of a 1x1 quad. + float vertices[] = { -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + -0.5f, -0.5f, 0.0f, 0.0f, 0.0f, + 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, + 0.5f, 0.5f, 0.0f, 1.0f, 1.0f }; + uint16_t indices[] = { 0, 1, 2, 0, 2, 3, // The two triangles that make up the layer quad. + 0, 1, 2, 3}; // A line path for drawing the layer border. + + GLC(m_context, m_quadVerticesVbo = m_context->createBuffer()); + GLC(m_context, m_quadElementsVbo = m_context->createBuffer()); + GLC(m_context, m_context->bindBuffer(GraphicsContext3D::ARRAY_BUFFER, m_quadVerticesVbo)); + GLC(m_context, m_context->bufferData(GraphicsContext3D::ARRAY_BUFFER, sizeof(vertices), vertices, GraphicsContext3D::STATIC_DRAW)); + GLC(m_context, m_context->bindBuffer(GraphicsContext3D::ELEMENT_ARRAY_BUFFER, m_quadElementsVbo)); + GLC(m_context, m_context->bufferData(GraphicsContext3D::ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GraphicsContext3D::STATIC_DRAW)); + + m_initialized = true; +} + +GeometryBinding::~GeometryBinding() +{ + GLC(m_context, m_context->deleteBuffer(m_quadVerticesVbo)); + GLC(m_context, m_context->deleteBuffer(m_quadElementsVbo)); +} + +void GeometryBinding::prepareForDraw() +{ + GLC(m_context, m_context->bindBuffer(GraphicsContext3D::ARRAY_BUFFER, quadVerticesVbo())); + GLC(m_context, m_context->bindBuffer(GraphicsContext3D::ELEMENT_ARRAY_BUFFER, quadElementsVbo())); + unsigned offset = 0; + GLC(m_context, m_context->vertexAttribPointer(positionAttribLocation(), 3, GraphicsContext3D::FLOAT, false, 5 * sizeof(float), offset)); + offset += 3 * sizeof(float); + GLC(m_context, m_context->vertexAttribPointer(texCoordAttribLocation(), 2, GraphicsContext3D::FLOAT, false, 5 * sizeof(float), offset)); + GLC(m_context, m_context->enableVertexAttribArray(positionAttribLocation())); + GLC(m_context, m_context->enableVertexAttribArray(texCoordAttribLocation())); +} + +} // namespace WebCore + +#endif // USE(ACCELERATED_COMPOSITING) diff --git a/Source/WebCore/platform/graphics/chromium/GeometryBinding.h b/Source/WebCore/platform/graphics/chromium/GeometryBinding.h new file mode 100644 index 0000000..ec19970 --- /dev/null +++ b/Source/WebCore/platform/graphics/chromium/GeometryBinding.h @@ -0,0 +1,67 @@ +/* + * Copyright (C) 2011 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef GeometryBinding_h +#define GeometryBinding_h + +#if USE(ACCELERATED_COMPOSITING) + +#include "PlatformString.h" + +namespace WebCore { + +class GraphicsContext3D; + +class GeometryBinding { +public: + explicit GeometryBinding(GraphicsContext3D*); + ~GeometryBinding(); + + bool initialized() const { return m_initialized; } + + GraphicsContext3D* context() const { return m_context; } + unsigned quadVerticesVbo() const { return m_quadVerticesVbo; } + unsigned quadElementsVbo() const { return m_quadElementsVbo; } + + void prepareForDraw(); + + // All layer shaders share the same attribute locations for the vertex + // positions and texture coordinates. This allows switching shaders without + // rebinding attribute arrays. + static int positionAttribLocation() { return 0; } + static int texCoordAttribLocation() { return 1; } + +private: + GraphicsContext3D* m_context; + unsigned m_quadVerticesVbo; + unsigned m_quadElementsVbo; + bool m_initialized; +}; + +} // namespace WebCore + +#endif // USE(ACCELERATED_COMPOSITING) + +#endif diff --git a/Source/WebCore/platform/graphics/chromium/GraphicsLayerChromium.cpp b/Source/WebCore/platform/graphics/chromium/GraphicsLayerChromium.cpp index 488230c..067c54d 100644 --- a/Source/WebCore/platform/graphics/chromium/GraphicsLayerChromium.cpp +++ b/Source/WebCore/platform/graphics/chromium/GraphicsLayerChromium.cpp @@ -111,8 +111,20 @@ GraphicsLayerChromium::~GraphicsLayerChromium() void GraphicsLayerChromium::setName(const String& inName) { + m_nameBase = inName; String name = String::format("GraphicsLayerChromium(%p) GraphicsLayer(%p) ", m_layer.get(), this) + inName; GraphicsLayer::setName(name); + updateNames(); +} + +void GraphicsLayerChromium::updateNames() +{ + if (m_layer) + m_layer->setName("Layer for " + m_nameBase); + if (m_transformLayer) + m_transformLayer->setName("TransformLayer for " + m_nameBase); + if (m_contentsLayer) + m_contentsLayer->setName("ContentsLayer for " + m_nameBase); } bool GraphicsLayerChromium::setChildren(const Vector<GraphicsLayer*>& children) @@ -590,6 +602,7 @@ void GraphicsLayerChromium::updateLayerPreserves3D() } updateOpacityOnLayer(); + updateNames(); } void GraphicsLayerChromium::updateLayerDrawsContent() @@ -653,6 +666,7 @@ void GraphicsLayerChromium::setupContentsLayer(LayerChromium* contentsLayer) } } updateDebugIndicators(); + updateNames(); } // This function simply mimics the operation of GraphicsLayerCA diff --git a/Source/WebCore/platform/graphics/chromium/GraphicsLayerChromium.h b/Source/WebCore/platform/graphics/chromium/GraphicsLayerChromium.h index 92c61fe..db8c6f7 100644 --- a/Source/WebCore/platform/graphics/chromium/GraphicsLayerChromium.h +++ b/Source/WebCore/platform/graphics/chromium/GraphicsLayerChromium.h @@ -107,6 +107,7 @@ private: LayerChromium* hostLayerForSublayers() const; LayerChromium* layerForSuperlayer() const; + void updateNames(); void updateSublayerList(); void updateLayerPosition(); void updateLayerSize(); @@ -127,6 +128,8 @@ private: void setupContentsLayer(LayerChromium*); LayerChromium* contentsLayer() const { return m_contentsLayer.get(); } + String m_nameBase; + RefPtr<LayerChromium> m_layer; RefPtr<LayerChromium> m_transformLayer; RefPtr<LayerChromium> m_contentsLayer; diff --git a/Source/WebCore/platform/graphics/chromium/ImageLayerChromium.cpp b/Source/WebCore/platform/graphics/chromium/ImageLayerChromium.cpp index cd299c1..7c42366 100644 --- a/Source/WebCore/platform/graphics/chromium/ImageLayerChromium.cpp +++ b/Source/WebCore/platform/graphics/chromium/ImageLayerChromium.cpp @@ -38,18 +38,6 @@ #include "LayerRendererChromium.h" #include "LayerTexture.h" -#if PLATFORM(SKIA) -#include "NativeImageSkia.h" -#include "PlatformContextSkia.h" -#endif - -#if PLATFORM(CG) -#include <CoreGraphics/CGBitmapContext.h> -#include <CoreGraphics/CGContext.h> -#include <CoreGraphics/CGImage.h> -#include <wtf/RetainPtr.h> -#endif - namespace WebCore { PassRefPtr<ImageLayerChromium> ImageLayerChromium::create(GraphicsLayerChromium* owner) @@ -84,80 +72,17 @@ void ImageLayerChromium::updateContentsIfDirty() return; } - void* pixels = 0; - IntSize bitmapSize; - - NativeImagePtr nativeImage = m_contents->nativeImageForCurrentFrame(); - -#if PLATFORM(SKIA) - // The layer contains an Image. - NativeImageSkia* skiaImage = static_cast<NativeImageSkia*>(nativeImage); - const SkBitmap* skiaBitmap = skiaImage; - bitmapSize = IntSize(skiaBitmap->width(), skiaBitmap->height()); - ASSERT(skiaBitmap); -#elif PLATFORM(CG) - // NativeImagePtr is a CGImageRef on Mac OS X. - int width = CGImageGetWidth(nativeImage); - int height = CGImageGetHeight(nativeImage); - bitmapSize = IntSize(width, height); -#endif - - // Clip the dirty rect to the bitmap dimensions. - IntRect dirtyRect(m_dirtyRect); - dirtyRect.intersect(IntRect(IntPoint(0, 0), bitmapSize)); + m_decodedImage.updateFromImage(m_contents->nativeImageForCurrentFrame()); +} - if (!m_contentsTexture || !m_contentsTexture->isValid(bitmapSize, GraphicsContext3D::RGBA)) - dirtyRect = IntRect(IntPoint(0, 0), bitmapSize); - else if (!m_contentsDirty) { - m_contentsTexture->reserve(bitmapSize, GraphicsContext3D::RGBA); +void ImageLayerChromium::updateTextureIfNeeded() +{ + // FIXME: Remove this test when tiled layers are implemented. + if (requiresClippedUpdateRect()) { + ContentLayerChromium::updateTextureIfNeeded(); return; } - -#if PLATFORM(SKIA) - SkAutoLockPixels lock(*skiaBitmap); - SkBitmap::Config skiaConfig = skiaBitmap->config(); - // FIXME: do we need to support more image configurations? - if (skiaConfig == SkBitmap::kARGB_8888_Config) - pixels = skiaBitmap->getPixels(); -#elif PLATFORM(CG) - // FIXME: we should get rid of this temporary copy where possible. - int tempRowBytes = width * 4; - Vector<uint8_t> tempVector; - tempVector.resize(height * tempRowBytes); - // Note we do not zero this vector since we are going to - // completely overwrite its contents with the image below. - // Try to reuse the color space from the image to preserve its colors. - // Some images use a color space (such as indexed) unsupported by the bitmap context. - RetainPtr<CGColorSpaceRef> colorSpaceReleaser; - CGColorSpaceRef colorSpace = CGImageGetColorSpace(nativeImage); - CGColorSpaceModel colorSpaceModel = CGColorSpaceGetModel(colorSpace); - switch (colorSpaceModel) { - case kCGColorSpaceModelMonochrome: - case kCGColorSpaceModelRGB: - case kCGColorSpaceModelCMYK: - case kCGColorSpaceModelLab: - case kCGColorSpaceModelDeviceN: - break; - default: - colorSpaceReleaser.adoptCF(CGColorSpaceCreateDeviceRGB()); - colorSpace = colorSpaceReleaser.get(); - break; - } - RetainPtr<CGContextRef> tempContext(AdoptCF, CGBitmapContextCreate(tempVector.data(), - width, height, 8, tempRowBytes, - colorSpace, - kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Host)); - CGContextSetBlendMode(tempContext.get(), kCGBlendModeCopy); - CGContextDrawImage(tempContext.get(), - CGRectMake(0, 0, static_cast<CGFloat>(width), static_cast<CGFloat>(height)), - nativeImage); - pixels = tempVector.data(); -#else -#error "Need to implement for your platform." -#endif - - if (pixels) - updateTextureRect(pixels, bitmapSize, dirtyRect); + updateTexture(m_decodedImage.pixels(), m_decodedImage.size()); } } diff --git a/Source/WebCore/platform/graphics/chromium/ImageLayerChromium.h b/Source/WebCore/platform/graphics/chromium/ImageLayerChromium.h index a5c1450..cc9064d 100644 --- a/Source/WebCore/platform/graphics/chromium/ImageLayerChromium.h +++ b/Source/WebCore/platform/graphics/chromium/ImageLayerChromium.h @@ -35,6 +35,7 @@ #if USE(ACCELERATED_COMPOSITING) #include "ContentLayerChromium.h" +#include "PlatformImage.h" #if PLATFORM(CG) #include <wtf/RetainPtr.h> @@ -50,13 +51,19 @@ public: static PassRefPtr<ImageLayerChromium> create(GraphicsLayerChromium* owner = 0); virtual void updateContentsIfDirty(); - virtual bool drawsContent() { return m_contents; } + virtual bool drawsContent() const { return m_contents; } void setContents(Image* image); +protected: + virtual const char* layerTypeAsString() const { return "ImageLayer"; } + private: + virtual void updateTextureIfNeeded(); + ImageLayerChromium(GraphicsLayerChromium* owner); + PlatformImage m_decodedImage; RefPtr<Image> m_contents; }; diff --git a/Source/WebCore/platform/graphics/chromium/LayerChromium.cpp b/Source/WebCore/platform/graphics/chromium/LayerChromium.cpp index 8d01d9b..95b7386 100644 --- a/Source/WebCore/platform/graphics/chromium/LayerChromium.cpp +++ b/Source/WebCore/platform/graphics/chromium/LayerChromium.cpp @@ -34,106 +34,24 @@ #include "LayerChromium.h" +#include "cc/CCLayerImpl.h" #include "GraphicsContext3D.h" #include "LayerRendererChromium.h" -#if PLATFORM(SKIA) +#if USE(SKIA) #include "NativeImageSkia.h" #include "PlatformContextSkia.h" #endif #include "RenderLayerBacking.h" +#include "TextStream.h" #include "skia/ext/platform_canvas.h" -#include <wtf/text/WTFString.h> namespace WebCore { using namespace std; -const unsigned LayerChromium::s_positionAttribLocation = 0; -const unsigned LayerChromium::s_texCoordAttribLocation = 1; - -static unsigned loadShader(GraphicsContext3D* context, unsigned type, const char* shaderSource) -{ - unsigned shader = context->createShader(type); - if (!shader) - return 0; - String sourceString(shaderSource); - GLC(context, context->shaderSource(shader, sourceString)); - GLC(context, context->compileShader(shader)); - int compiled = 0; - GLC(context, context->getShaderiv(shader, GraphicsContext3D::COMPILE_STATUS, &compiled)); - if (!compiled) { - GLC(context, context->deleteShader(shader)); - return 0; - } - return shader; -} - -LayerChromium::SharedValues::SharedValues(GraphicsContext3D* context) - : m_context(context) - , m_quadVerticesVbo(0) - , m_quadElementsVbo(0) - , m_maxTextureSize(0) - , m_borderShaderProgram(0) - , m_borderShaderMatrixLocation(-1) - , m_borderShaderColorLocation(-1) - , m_initialized(false) -{ - // Vertex positions and texture coordinates for the 4 corners of a 1x1 quad. - float vertices[] = { -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, - -0.5f, -0.5f, 0.0f, 0.0f, 0.0f, - 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, - 0.5f, 0.5f, 0.0f, 1.0f, 1.0f }; - uint16_t indices[] = { 0, 1, 2, 0, 2, 3, // The two triangles that make up the layer quad. - 0, 1, 2, 3}; // A line path for drawing the layer border. - - GLC(m_context, m_quadVerticesVbo = m_context->createBuffer()); - GLC(m_context, m_quadElementsVbo = m_context->createBuffer()); - GLC(m_context, m_context->bindBuffer(GraphicsContext3D::ARRAY_BUFFER, m_quadVerticesVbo)); - GLC(m_context, m_context->bufferData(GraphicsContext3D::ARRAY_BUFFER, sizeof(vertices), vertices, GraphicsContext3D::STATIC_DRAW)); - GLC(m_context, m_context->bindBuffer(GraphicsContext3D::ELEMENT_ARRAY_BUFFER, m_quadElementsVbo)); - GLC(m_context, m_context->bufferData(GraphicsContext3D::ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GraphicsContext3D::STATIC_DRAW)); - - // Get the max texture size supported by the system. - GLC(m_context, m_context->getIntegerv(GraphicsContext3D::MAX_TEXTURE_SIZE, &m_maxTextureSize)); - - // Shaders for drawing the debug borders around the layers. - char borderVertexShaderString[] = - "attribute vec4 a_position; \n" - "uniform mat4 matrix; \n" - "void main() \n" - "{ \n" - " gl_Position = matrix * a_position; \n" - "} \n"; - char borderFragmentShaderString[] = - "precision mediump float; \n" - "uniform vec4 color; \n" - "void main() \n" - "{ \n" - " gl_FragColor = vec4(color.xyz * color.w, color.w);\n" - "} \n"; - - m_borderShaderProgram = createShaderProgram(m_context, borderVertexShaderString, borderFragmentShaderString); - if (!m_borderShaderProgram) { - LOG_ERROR("ContentLayerChromium: Failed to create shader program"); - return; - } - - m_borderShaderMatrixLocation = m_context->getUniformLocation(m_borderShaderProgram, "matrix"); - m_borderShaderColorLocation = m_context->getUniformLocation(m_borderShaderProgram, "color"); - ASSERT(m_borderShaderMatrixLocation != -1); - ASSERT(m_borderShaderColorLocation != -1); - - m_initialized = true; -} - -LayerChromium::SharedValues::~SharedValues() -{ - GLC(m_context, m_context->deleteBuffer(m_quadVerticesVbo)); - GLC(m_context, m_context->deleteBuffer(m_quadElementsVbo)); - if (m_borderShaderProgram) - GLC(m_context, m_context->deleteProgram(m_borderShaderProgram)); -} - +#ifndef NDEBUG +static int s_nextLayerDebugID = 1; +#endif PassRefPtr<LayerChromium> LayerChromium::create(GraphicsLayerChromium* owner) { @@ -144,25 +62,22 @@ LayerChromium::LayerChromium(GraphicsLayerChromium* owner) : m_owner(owner) , m_contentsDirty(false) , m_maskLayer(0) - , m_targetRenderSurface(0) , m_superlayer(0) +#ifndef NDEBUG + , m_debugID(s_nextLayerDebugID++) +#endif , m_anchorPoint(0.5, 0.5) , m_backgroundColor(0, 0, 0, 0) - , m_borderColor(0, 0, 0, 0) , m_opacity(1.0) , m_zPosition(0.0) , m_anchorPointZ(0) - , m_borderWidth(0) , m_clearsContext(false) - , m_doubleSided(true) , m_hidden(false) , m_masksToBounds(false) , m_opaque(true) , m_geometryFlipped(false) , m_needsDisplayOnBoundsChange(false) - , m_drawDepth(0) - , m_layerRenderer(0) - , m_renderSurface(0) + , m_ccLayerImpl(CCLayerImpl::create(this)) , m_replicaLayer(0) { } @@ -179,8 +94,7 @@ LayerChromium::~LayerChromium() void LayerChromium::cleanupResources() { - if (m_renderSurface) - m_renderSurface->cleanupResources(); + m_ccLayerImpl->cleanupResources(); } void LayerChromium::setLayerRenderer(LayerRendererChromium* renderer) @@ -192,55 +106,7 @@ void LayerChromium::setLayerRenderer(LayerRendererChromium* renderer) setNeedsDisplay(); } - m_layerRenderer = renderer; -} - -RenderSurfaceChromium* LayerChromium::createRenderSurface() -{ - m_renderSurface = new RenderSurfaceChromium(this); - return m_renderSurface.get(); -} - -unsigned LayerChromium::createShaderProgram(GraphicsContext3D* context, const char* vertexShaderSource, const char* fragmentShaderSource) -{ - unsigned vertexShader = loadShader(context, GraphicsContext3D::VERTEX_SHADER, vertexShaderSource); - if (!vertexShader) { - LOG_ERROR("Failed to create vertex shader"); - return 0; - } - - unsigned fragmentShader = loadShader(context, GraphicsContext3D::FRAGMENT_SHADER, fragmentShaderSource); - if (!fragmentShader) { - GLC(context, context->deleteShader(vertexShader)); - LOG_ERROR("Failed to create fragment shader"); - return 0; - } - - unsigned programObject = context->createProgram(); - if (!programObject) { - LOG_ERROR("Failed to create shader program"); - return 0; - } - - GLC(context, context->attachShader(programObject, vertexShader)); - GLC(context, context->attachShader(programObject, fragmentShader)); - - // Bind the common attrib locations. - GLC(context, context->bindAttribLocation(programObject, s_positionAttribLocation, "a_position")); - GLC(context, context->bindAttribLocation(programObject, s_texCoordAttribLocation, "a_texCoord")); - - GLC(context, context->linkProgram(programObject)); - int linked = 0; - GLC(context, context->getProgramiv(programObject, GraphicsContext3D::LINK_STATUS, &linked)); - if (!linked) { - LOG_ERROR("Failed to link shader program"); - GLC(context, context->deleteProgram(programObject)); - return 0; - } - - GLC(context, context->deleteShader(vertexShader)); - GLC(context, context->deleteShader(fragmentShader)); - return programObject; + m_ccLayerImpl->setLayerRenderer(renderer); } void LayerChromium::setNeedsCommit() @@ -317,16 +183,15 @@ int LayerChromium::indexOfSublayer(const LayerChromium* reference) void LayerChromium::setBounds(const IntSize& size) { - if (m_bounds == size) + if (bounds() == size) return; - bool firstResize = !m_bounds.width() && !m_bounds.height() && size.width() && size.height(); + bool firstResize = !bounds().width() && !bounds().height() && size.width() && size.height(); - m_bounds = size; - m_backingStoreSize = size; + m_ccLayerImpl->setBounds(size); if (firstResize) - setNeedsDisplay(FloatRect(0, 0, m_bounds.width(), m_bounds.height())); + setNeedsDisplay(FloatRect(0, 0, bounds().width(), bounds().height())); else setNeedsCommit(); } @@ -337,7 +202,7 @@ void LayerChromium::setFrame(const FloatRect& rect) return; m_frame = rect; - setNeedsDisplay(FloatRect(0, 0, m_bounds.width(), m_bounds.height())); + setNeedsDisplay(FloatRect(0, 0, bounds().width(), bounds().height())); } const LayerChromium* LayerChromium::rootLayer() const @@ -372,6 +237,12 @@ LayerChromium* LayerChromium::superlayer() const return m_superlayer; } +void LayerChromium::setName(const String& name) +{ + m_name = name; + m_ccLayerImpl->setName(name); +} + void LayerChromium::setNeedsDisplay(const FloatRect& dirtyRect) { // Simply mark the contents as dirty. For non-root layers, the call to @@ -386,7 +257,7 @@ void LayerChromium::setNeedsDisplay(const FloatRect& dirtyRect) void LayerChromium::setNeedsDisplay() { m_dirtyRect.setLocation(FloatPoint()); - m_dirtyRect.setSize(m_bounds); + m_dirtyRect.setSize(bounds()); m_contentsDirty = true; setNeedsCommit(); } @@ -445,38 +316,7 @@ void LayerChromium::drawTexturedQuad(GraphicsContext3D* context, const Transform GLC(context, context->drawElements(GraphicsContext3D::TRIANGLES, 6, GraphicsContext3D::UNSIGNED_SHORT, 0)); } -void LayerChromium::drawDebugBorder() -{ - static float glMatrix[16]; - if (!borderColor().alpha()) - return; - - ASSERT(layerRenderer()); - const SharedValues* sv = layerRenderer()->layerSharedValues(); - ASSERT(sv && sv->initialized()); - layerRenderer()->useShader(sv->borderShaderProgram()); - TransformationMatrix renderMatrix = drawTransform(); - renderMatrix.scale3d(bounds().width(), bounds().height(), 1); - toGLMatrix(&glMatrix[0], layerRenderer()->projectionMatrix() * renderMatrix); - GraphicsContext3D* context = layerRendererContext(); - GLC(context, context->uniformMatrix4fv(sv->borderShaderMatrixLocation(), false, &glMatrix[0], 1)); - - GLC(context, context->uniform4f(sv->borderShaderColorLocation(), borderColor().red() / 255.0, borderColor().green() / 255.0, borderColor().blue() / 255.0, 1)); - GLC(context, context->lineWidth(borderWidth())); - - // The indices for the line are stored in the same array as the triangle indices. - GLC(context, context->drawElements(GraphicsContext3D::LINE_LOOP, 4, GraphicsContext3D::UNSIGNED_SHORT, 6 * sizeof(unsigned short))); -} - -const IntRect LayerChromium::getDrawRect() const -{ - // Form the matrix used by the shader to map the corners of the layer's - // bounds into the view space. - FloatRect layerRect(-0.5 * bounds().width(), -0.5 * bounds().height(), bounds().width(), bounds().height()); - IntRect mappedRect = enclosingIntRect(drawTransform().mapRect(layerRect)); - return mappedRect; -} // Returns true if any of the layer's descendants has drawable content. bool LayerChromium::descendantsDrawContent() @@ -501,19 +341,92 @@ bool LayerChromium::descendantsDrawContentRecursive() return false; } -// static -void LayerChromium::prepareForDraw(const SharedValues* sv) +String LayerChromium::layerTreeAsText() const +{ + TextStream ts; + dumpLayer(ts, 0); + return ts.release(); +} + +static void writeIndent(TextStream& ts, int indent) +{ + for (int i = 0; i != indent; ++i) + ts << " "; +} + +void LayerChromium::dumpLayer(TextStream& ts, int indent) const +{ + writeIndent(ts, indent); + ts << layerTypeAsString() << "(" << m_name << ")\n"; + dumpLayerProperties(ts, indent+2); + m_ccLayerImpl->dumpLayerProperties(ts, indent+2); + if (m_replicaLayer) { + writeIndent(ts, indent+2); + ts << "Replica:\n"; + m_replicaLayer->dumpLayer(ts, indent+3); + } + if (m_maskLayer) { + writeIndent(ts, indent+2); + ts << "Mask:\n"; + m_maskLayer->dumpLayer(ts, indent+3); + } + for (size_t i = 0; i < m_sublayers.size(); ++i) + m_sublayers[i]->dumpLayer(ts, indent+1); +} + +void LayerChromium::dumpLayerProperties(TextStream& ts, int indent) const +{ + writeIndent(ts, indent); +#ifndef NDEBUG + ts << "debugID: " << debugID() << ", "; +#else +#endif + ts << "drawsContent: " << drawsContent() << "\n"; + +} + +// Begin calls that forward to the CCLayerImpl. +// ============================================== +// These exists just for debugging (via drawDebugBorder()). +void LayerChromium::setBorderColor(const Color& color) +{ + m_ccLayerImpl->setDebugBorderColor(color); + setNeedsCommit(); +} + +Color LayerChromium::borderColor() const +{ + return m_ccLayerImpl->debugBorderColor(); +} + +void LayerChromium::setBorderWidth(float width) +{ + m_ccLayerImpl->setDebugBorderWidth(width); + setNeedsCommit(); +} + +float LayerChromium::borderWidth() const +{ + return m_ccLayerImpl->debugBorderWidth(); +} + +LayerRendererChromium* LayerChromium::layerRenderer() const +{ + return m_ccLayerImpl->layerRenderer(); +} + +void LayerChromium::setDoubleSided(bool doubleSided) +{ + m_ccLayerImpl->setDoubleSided(doubleSided); + setNeedsCommit(); +} + +const IntSize& LayerChromium::bounds() const { - GraphicsContext3D* context = sv->context(); - GLC(context, context->bindBuffer(GraphicsContext3D::ARRAY_BUFFER, sv->quadVerticesVbo())); - GLC(context, context->bindBuffer(GraphicsContext3D::ELEMENT_ARRAY_BUFFER, sv->quadElementsVbo())); - unsigned offset = 0; - GLC(context, context->vertexAttribPointer(s_positionAttribLocation, 3, GraphicsContext3D::FLOAT, false, 5 * sizeof(float), offset)); - offset += 3 * sizeof(float); - GLC(context, context->vertexAttribPointer(s_texCoordAttribLocation, 2, GraphicsContext3D::FLOAT, false, 5 * sizeof(float), offset)); - GLC(context, context->enableVertexAttribArray(s_positionAttribLocation)); - GLC(context, context->enableVertexAttribArray(s_texCoordAttribLocation)); + return m_ccLayerImpl->bounds(); } +// ============================================== +// End calls that forward to the CCLayerImpl. } #endif // USE(ACCELERATED_COMPOSITING) diff --git a/Source/WebCore/platform/graphics/chromium/LayerChromium.h b/Source/WebCore/platform/graphics/chromium/LayerChromium.h index 5c7e2b1..29a2165 100644 --- a/Source/WebCore/platform/graphics/chromium/LayerChromium.h +++ b/Source/WebCore/platform/graphics/chromium/LayerChromium.h @@ -38,13 +38,17 @@ #include "GraphicsContext.h" #include "GraphicsLayerChromium.h" #include "PlatformString.h" +#include "ProgramBinding.h" #include "RenderSurfaceChromium.h" +#include "ShaderChromium.h" #include "TransformationMatrix.h" + #include <wtf/OwnPtr.h> #include <wtf/PassRefPtr.h> #include <wtf/RefCounted.h> #include <wtf/Vector.h> #include <wtf/text/StringHash.h> +#include <wtf/text/WTFString.h> namespace skia { @@ -53,13 +57,13 @@ class PlatformCanvas; namespace WebCore { +class CCLayerImpl; class GraphicsContext3D; class LayerRendererChromium; // Base class for composited layers. Special layer types are derived from // this class. class LayerChromium : public RefCounted<LayerChromium> { - friend class LayerRendererChromium; friend class LayerTilerChromium; public: static PassRefPtr<LayerChromium> create(GraphicsLayerChromium* owner = 0); @@ -85,21 +89,9 @@ public: void setBackgroundColor(const Color& color) { m_backgroundColor = color; setNeedsCommit(); } Color backgroundColor() const { return m_backgroundColor; } - void setBorderColor(const Color& color) { m_borderColor = color; setNeedsCommit(); } - Color borderColor() const { return m_borderColor; } - - void setBorderWidth(float width) { m_borderWidth = width; setNeedsCommit(); } - float borderWidth() const { return m_borderWidth; } - - void setBounds(const IntSize&); - IntSize bounds() const { return m_bounds; } - void setClearsContext(bool clears) { m_clearsContext = clears; setNeedsCommit(); } bool clearsContext() const { return m_clearsContext; } - void setDoubleSided(bool doubleSided) { m_doubleSided = doubleSided; setNeedsCommit(); } - bool doubleSided() const { return m_doubleSided; } - void setFrame(const FloatRect&); FloatRect frame() const { return m_frame; } @@ -109,10 +101,11 @@ public: void setMasksToBounds(bool masksToBounds) { m_masksToBounds = masksToBounds; } bool masksToBounds() const { return m_masksToBounds; } - void setName(const String& name) { m_name = name; } - String name() const { return m_name; } + void setName(const String&); + const String& name() const { return m_name; } void setMaskLayer(LayerChromium* maskLayer) { m_maskLayer = maskLayer; } + CCLayerImpl* maskDrawLayer() const { return m_maskLayer ? m_maskLayer->ccLayerImpl() : 0; } LayerChromium* maskLayer() const { return m_maskLayer.get(); } void setNeedsDisplay(const FloatRect& dirtyRect); @@ -144,75 +137,60 @@ public: void setGeometryFlipped(bool flipped) { m_geometryFlipped = flipped; setNeedsCommit(); } bool geometryFlipped() const { return m_geometryFlipped; } - const TransformationMatrix& drawTransform() const { return m_drawTransform; } - float drawOpacity() const { return m_drawOpacity; } - bool preserves3D() { return m_owner && m_owner->preserves3D(); } // Derived types must override this method if they need to react to a change // in the LayerRendererChromium. virtual void setLayerRenderer(LayerRendererChromium*); + // Returns true if any of the layer's descendants has content to draw. + bool descendantsDrawContent(); + void setOwner(GraphicsLayerChromium* owner) { m_owner = owner; } void setReplicaLayer(LayerChromium* layer) { m_replicaLayer = layer; } LayerChromium* replicaLayer() { return m_replicaLayer; } - // Returns the rect containtaining this layer in the current view's coordinate system. - const IntRect getDrawRect() const; - // These methods typically need to be overwritten by derived classes. - virtual bool drawsContent() { return false; } + virtual bool drawsContent() const { return false; } virtual void updateContentsIfDirty() { } virtual void unreserveContentsTexture() { } virtual void bindContentsTexture() { } virtual void draw() { } + // These exists just for debugging (via drawDebugBorder()). + void setBorderColor(const Color&); + Color borderColor() const; + +#ifndef NDEBUG + int debugID() const { return m_debugID; } +#endif + void drawDebugBorder(); + String layerTreeAsText() const; + + void setBorderWidth(float); + float borderWidth() const; + + // Everything from here down in the public section will move to CCLayerImpl. - RenderSurfaceChromium* createRenderSurface(); - - // Stores values that are shared between instances of this class that are - // associated with the same LayerRendererChromium (and hence the same GL - // context). - class SharedValues { - public: - explicit SharedValues(GraphicsContext3D*); - ~SharedValues(); - - GraphicsContext3D* context() const { return m_context; } - unsigned quadVerticesVbo() const { return m_quadVerticesVbo; } - unsigned quadElementsVbo() const { return m_quadElementsVbo; } - int maxTextureSize() const { return m_maxTextureSize; } - unsigned borderShaderProgram() const { return m_borderShaderProgram; } - int borderShaderMatrixLocation() const { return m_borderShaderMatrixLocation; } - int borderShaderColorLocation() const { return m_borderShaderColorLocation; } - bool initialized() const { return m_initialized; } - - private: - GraphicsContext3D* m_context; - unsigned m_quadVerticesVbo; - unsigned m_quadElementsVbo; - int m_maxTextureSize; - unsigned m_borderShaderProgram; - int m_borderShaderMatrixLocation; - int m_borderShaderColorLocation; - bool m_initialized; - }; - - static void prepareForDraw(const SharedValues*); - - LayerRendererChromium* layerRenderer() const { return m_layerRenderer.get(); } - - static unsigned createShaderProgram(GraphicsContext3D*, const char* vertexShaderSource, const char* fragmentShaderSource); + CCLayerImpl* ccLayerImpl() const { return m_ccLayerImpl.get(); } static void drawTexturedQuad(GraphicsContext3D*, const TransformationMatrix& projectionMatrix, const TransformationMatrix& layerMatrix, float width, float height, float opacity, int matrixLocation, int alphaLocation); + // Begin calls that forward to the CCLayerImpl. + LayerRendererChromium* layerRenderer() const; + void setDoubleSided(bool); + void setBounds(const IntSize&); + const IntSize& bounds() const; + // End calls that forward to the CCLayerImpl. + + typedef ProgramBinding<VertexShaderPos, FragmentShaderColor> BorderProgram; protected: GraphicsLayerChromium* m_owner; - LayerChromium(GraphicsLayerChromium* owner); + explicit LayerChromium(GraphicsLayerChromium* owner); // This is called to clean up resources being held in the same context as // layerRendererContext(). Subclasses should override this method if they @@ -221,23 +199,18 @@ protected: GraphicsContext3D* layerRendererContext() const; - // Returns true if any of the layer's descendants has content to draw. - bool descendantsDrawContent(); - static void toGLMatrix(float*, const TransformationMatrix&); - IntSize m_bounds; + void dumpLayer(TextStream&, int indent) const; + + virtual const char* layerTypeAsString() const { return "LayerChromium"; } + virtual void dumpLayerProperties(TextStream&, int indent) const; + FloatRect m_dirtyRect; bool m_contentsDirty; RefPtr<LayerChromium> m_maskLayer; - // Render surface this layer draws into. This is a surface that can belong - // either to this layer (if m_targetRenderSurface == m_renderSurface) or - // to an ancestor of this layer. The target render surface determines the - // coordinate system the layer's transforms are relative to. - RenderSurfaceChromium* m_targetRenderSurface; - // All layer shaders share the same attribute locations for the vertex positions // and texture coordinates. This allows switching shaders without rebinding attribute // arrays. @@ -265,48 +238,30 @@ private: Vector<RefPtr<LayerChromium> > m_sublayers; LayerChromium* m_superlayer; +#ifndef NDEBUG + int m_debugID; +#endif + // Layer properties. - IntSize m_backingStoreSize; FloatPoint m_position; FloatPoint m_anchorPoint; Color m_backgroundColor; - Color m_borderColor; float m_opacity; float m_zPosition; float m_anchorPointZ; - float m_borderWidth; - float m_drawOpacity; bool m_clearsContext; - bool m_doubleSided; bool m_hidden; bool m_masksToBounds; bool m_opaque; bool m_geometryFlipped; bool m_needsDisplayOnBoundsChange; - // The global depth value of the center of the layer. This value is used - // to sort layers from back to front. - float m_drawDepth; - - // Points to the layer renderer that updates and draws this layer. - RefPtr<LayerRendererChromium> m_layerRenderer; - - FloatRect m_frame; TransformationMatrix m_transform; TransformationMatrix m_sublayerTransform; - TransformationMatrix m_drawTransform; - - // The scissor rectangle that should be used when this layer is drawn. - // Inherited by the parent layer and further restricted if this layer masks - // to bounds. - IntRect m_scissorRect; - // Render surface associated with this layer. The layer and its descendants - // will render to this surface. - OwnPtr<RenderSurfaceChromium> m_renderSurface; - - // Hierarchical bounding rect containing the layer and its descendants. - IntRect m_drawableContentRect; + FloatRect m_frame; + // For now, the LayerChromium directly owns its CCLayerImpl. + RefPtr<CCLayerImpl> m_ccLayerImpl; // Replica layer used for reflections. LayerChromium* m_replicaLayer; diff --git a/Source/WebCore/platform/graphics/chromium/LayerRendererChromium.cpp b/Source/WebCore/platform/graphics/chromium/LayerRendererChromium.cpp index f5548c9..e7b299f 100644 --- a/Source/WebCore/platform/graphics/chromium/LayerRendererChromium.cpp +++ b/Source/WebCore/platform/graphics/chromium/LayerRendererChromium.cpp @@ -34,14 +34,18 @@ #if USE(ACCELERATED_COMPOSITING) #include "LayerRendererChromium.h" +#include "cc/CCLayerImpl.h" #include "Canvas2DLayerChromium.h" +#include "GeometryBinding.h" #include "GraphicsContext3D.h" #include "LayerChromium.h" #include "LayerTexture.h" #include "NotImplemented.h" +#include "TextStream.h" #include "TextureManager.h" #include "WebGLLayerChromium.h" -#if PLATFORM(SKIA) +#include "cc/CCLayerImpl.h" +#if USE(SKIA) #include "NativeImageSkia.h" #include "PlatformContextSkia.h" #elif PLATFORM(CG) @@ -82,9 +86,9 @@ static bool isScaleOrTranslation(const TransformationMatrix& m) } -bool LayerRendererChromium::compareLayerZ(const LayerChromium* a, const LayerChromium* b) +bool LayerRendererChromium::compareLayerZ(const CCLayerImpl* a, const CCLayerImpl* b) { - return a->m_drawDepth < b->m_drawDepth; + return a->drawDepth() < b->drawDepth(); } PassRefPtr<LayerRendererChromium> LayerRendererChromium::create(PassRefPtr<GraphicsContext3D> context) @@ -100,9 +104,7 @@ PassRefPtr<LayerRendererChromium> LayerRendererChromium::create(PassRefPtr<Graph } LayerRendererChromium::LayerRendererChromium(PassRefPtr<GraphicsContext3D> context) - : m_rootLayerTextureWidth(0) - , m_rootLayerTextureHeight(0) - , m_rootLayer(0) + : m_rootLayer(0) , m_scrollPosition(IntPoint(-1, -1)) , m_currentShader(0) , m_currentRenderSurface(0) @@ -112,12 +114,15 @@ LayerRendererChromium::LayerRendererChromium(PassRefPtr<GraphicsContext3D> conte , m_defaultRenderSurface(0) { m_hardwareCompositing = initializeSharedObjects(); - m_rootLayerTiler = LayerTilerChromium::create(this, IntSize(256, 256)); + m_rootLayerTiler = LayerTilerChromium::create(this, IntSize(256, 256), LayerTilerChromium::NoBorderTexels); ASSERT(m_rootLayerTiler); + + m_headsUpDisplay = CCHeadsUpDisplay::create(this); } LayerRendererChromium::~LayerRendererChromium() { + m_headsUpDisplay.clear(); // Explicitly destroy the HUD before the TextureManager dies. cleanupSharedObjects(); } @@ -172,71 +177,125 @@ void LayerRendererChromium::invalidateRootLayerRect(const IntRect& dirtyRect, co } } -void LayerRendererChromium::updateAndDrawRootLayer(TilePaintInterface& tilePaint, TilePaintInterface& scrollbarPaint, const IntRect& visibleRect, const IntRect& contentRect) +void LayerRendererChromium::updateRootLayerContents(TilePaintInterface& tilePaint, const IntRect& visibleRect) { m_rootLayerTiler->update(tilePaint, visibleRect); - m_rootLayerTiler->draw(visibleRect); +} +void LayerRendererChromium::updateRootLayerScrollbars(TilePaintInterface& scrollbarPaint, const IntRect& visibleRect, const IntRect& contentRect) +{ if (visibleRect.width() > contentRect.width()) { IntRect verticalScrollbar = verticalScrollbarRect(visibleRect, contentRect); IntSize tileSize = verticalScrollbar.size().shrunkTo(IntSize(m_maxTextureSize, m_maxTextureSize)); if (!m_verticalScrollbarTiler) - m_verticalScrollbarTiler = LayerTilerChromium::create(this, tileSize); + m_verticalScrollbarTiler = LayerTilerChromium::create(this, tileSize, LayerTilerChromium::NoBorderTexels); else m_verticalScrollbarTiler->setTileSize(tileSize); m_verticalScrollbarTiler->setLayerPosition(verticalScrollbar.location()); m_verticalScrollbarTiler->update(scrollbarPaint, visibleRect); - m_verticalScrollbarTiler->draw(visibleRect); - } + } else + m_verticalScrollbarTiler.clear(); if (visibleRect.height() > contentRect.height()) { IntRect horizontalScrollbar = horizontalScrollbarRect(visibleRect, contentRect); IntSize tileSize = horizontalScrollbar.size().shrunkTo(IntSize(m_maxTextureSize, m_maxTextureSize)); if (!m_horizontalScrollbarTiler) - m_horizontalScrollbarTiler = LayerTilerChromium::create(this, tileSize); + m_horizontalScrollbarTiler = LayerTilerChromium::create(this, tileSize, LayerTilerChromium::NoBorderTexels); else m_horizontalScrollbarTiler->setTileSize(tileSize); m_horizontalScrollbarTiler->setLayerPosition(horizontalScrollbar.location()); m_horizontalScrollbarTiler->update(scrollbarPaint, visibleRect); - m_horizontalScrollbarTiler->draw(visibleRect); - } + } else + m_horizontalScrollbarTiler.clear(); +} + +void LayerRendererChromium::drawRootLayer() +{ + m_rootLayerTiler->draw(m_visibleRect); + + if (m_verticalScrollbarTiler) + m_verticalScrollbarTiler->draw(m_visibleRect); + + if (m_horizontalScrollbarTiler) + m_horizontalScrollbarTiler->draw(m_visibleRect); } -void LayerRendererChromium::drawLayers(const IntRect& visibleRect, const IntRect& contentRect, - const IntPoint& scrollPosition, TilePaintInterface& tilePaint, - TilePaintInterface& scrollbarPaint) +void LayerRendererChromium::updateAndDrawLayers(const IntRect& visibleRect, const IntRect& contentRect, const IntPoint& scrollPosition, + TilePaintInterface& tilePaint, TilePaintInterface& scrollbarPaint) { ASSERT(m_hardwareCompositing); if (!m_rootLayer) return; - makeContextCurrent(); + updateRootLayerContents(tilePaint, visibleRect); + // Recheck that we still have a root layer. This may become null if + // compositing gets turned off during a paint operation. + if (!m_rootLayer) + return; + + updateRootLayerScrollbars(scrollbarPaint, visibleRect, contentRect); + + Vector<CCLayerImpl*> renderSurfaceLayerList; + updateLayers(visibleRect, contentRect, scrollPosition, renderSurfaceLayerList); + + drawLayers(renderSurfaceLayerList); +} + +void LayerRendererChromium::updateLayers(const IntRect& visibleRect, const IntRect& contentRect, const IntPoint& scrollPosition, + Vector<CCLayerImpl*>& renderSurfaceLayerList) +{ + CCLayerImpl* rootDrawLayer = m_rootLayer->ccLayerImpl(); + + if (!rootDrawLayer->renderSurface()) + rootDrawLayer->createRenderSurface(); + ASSERT(rootDrawLayer->renderSurface()); // If the size of the visible area has changed then allocate a new texture // to store the contents of the root layer and adjust the projection matrix // and viewport. - int visibleRectWidth = visibleRect.width(); - int visibleRectHeight = visibleRect.height(); - - if (!m_rootLayer->m_renderSurface) - m_rootLayer->createRenderSurface(); - m_rootLayer->m_renderSurface->m_contentRect = IntRect(0, 0, visibleRectWidth, visibleRectHeight); - if (visibleRectWidth != m_rootLayerTextureWidth || visibleRectHeight != m_rootLayerTextureHeight) { - m_rootLayerTextureWidth = visibleRectWidth; - m_rootLayerTextureHeight = visibleRectHeight; + rootDrawLayer->renderSurface()->m_contentRect = IntRect(IntPoint(0, 0), visibleRect.size()); + if (visibleRect.size() != m_visibleRect.size()) { // Reset the current render surface to force an update of the viewport and // projection matrix next time useRenderSurface is called. m_currentRenderSurface = 0; } + m_visibleRect = visibleRect; + + m_scrollPosition = scrollPosition; + // Scissor out the scrollbars to avoid rendering on top of them. + IntRect rootScissorRect(contentRect); + // The scissorRect should not include the scroll offset. + rootScissorRect.move(-m_scrollPosition.x(), -m_scrollPosition.y()); + rootDrawLayer->setScissorRect(rootScissorRect); + + m_defaultRenderSurface = rootDrawLayer->renderSurface(); + + renderSurfaceLayerList.append(rootDrawLayer); + + TransformationMatrix identityMatrix; + m_defaultRenderSurface->m_layerList.clear(); + // Unfortunately, updatePropertiesAndRenderSurfaces() currently both updates the layers and updates the draw state + // (transforms, etc). It'd be nicer if operations on the presentation layers happened later, but the draw + // transforms are needed by large layers to determine visibility. Tiling will fix this by eliminating the + // concept of a large content layer. + updatePropertiesAndRenderSurfaces(m_rootLayer.get(), identityMatrix, renderSurfaceLayerList, m_defaultRenderSurface->m_layerList); + + updateContentsRecursive(m_rootLayer.get()); +} + +void LayerRendererChromium::drawLayers(const Vector<CCLayerImpl*>& renderSurfaceLayerList) +{ + CCLayerImpl* rootDrawLayer = m_rootLayer->ccLayerImpl(); + makeContextCurrent(); // The GL viewport covers the entire visible area, including the scrollbars. - GLC(m_context.get(), m_context->viewport(0, 0, visibleRectWidth, visibleRectHeight)); + GLC(m_context.get(), m_context->viewport(0, 0, m_visibleRect.width(), m_visibleRect.height())); // Bind the common vertex attributes used for drawing all the layers. - LayerChromium::prepareForDraw(layerSharedValues()); + m_sharedGeometry->prepareForDraw(); // FIXME: These calls can be made once, when the compositor context is initialized. GLC(m_context.get(), m_context->disable(GraphicsContext3D::DEPTH_TEST)); @@ -245,11 +304,6 @@ void LayerRendererChromium::drawLayers(const IntRect& visibleRect, const IntRect // Blending disabled by default. Root layer alpha channel on Windows is incorrect when Skia uses ClearType. GLC(m_context.get(), m_context->disable(GraphicsContext3D::BLEND)); - m_scrollPosition = scrollPosition; - - ASSERT(m_rootLayer->m_renderSurface); - m_defaultRenderSurface = m_rootLayer->m_renderSurface.get(); - useRenderSurface(m_defaultRenderSurface); // Clear to blue to make it easier to spot unrendered regions. @@ -260,66 +314,49 @@ void LayerRendererChromium::drawLayers(const IntRect& visibleRect, const IntRect // zero alpha values on text glyphs. The root layer is always opaque. m_context->colorMask(true, true, true, false); - updateAndDrawRootLayer(tilePaint, scrollbarPaint, visibleRect, contentRect); + drawRootLayer(); // Re-enable color writes to layers, which may be partially transparent. m_context->colorMask(true, true, true, true); - // Recheck that we still have a root layer. This may become null if - // compositing gets turned off during a paint operation. - if (!m_rootLayer) - return; - - // Set the root visible/content rects --- used by subsequent drawLayers calls. - m_rootVisibleRect = visibleRect; - m_rootContentRect = contentRect; - - // Scissor out the scrollbars to avoid rendering on top of them. - IntRect rootScissorRect(contentRect); - // The scissorRect should not include the scroll offset. - rootScissorRect.move(-m_scrollPosition.x(), -m_scrollPosition.y()); - m_rootLayer->m_scissorRect = rootScissorRect; - - Vector<LayerChromium*> renderSurfaceLayerList; - renderSurfaceLayerList.append(m_rootLayer.get()); - - TransformationMatrix identityMatrix; - m_defaultRenderSurface->m_layerList.clear(); - updateLayersRecursive(m_rootLayer.get(), identityMatrix, renderSurfaceLayerList, m_defaultRenderSurface->m_layerList); - - // The shader used to render layers returns pre-multiplied alpha colors - // so we need to send the blending mode appropriately. GLC(m_context.get(), m_context->enable(GraphicsContext3D::BLEND)); - GLC(m_context.get(), m_context->blendFunc(GraphicsContext3D::ONE, GraphicsContext3D::ONE_MINUS_SRC_ALPHA)); GLC(m_context.get(), m_context->enable(GraphicsContext3D::SCISSOR_TEST)); // Update the contents of the render surfaces. We traverse the array from // back to front to guarantee that nested render surfaces get rendered in the // correct order. for (int surfaceIndex = renderSurfaceLayerList.size() - 1; surfaceIndex >= 0 ; --surfaceIndex) { - LayerChromium* renderSurfaceLayer = renderSurfaceLayerList[surfaceIndex]; - ASSERT(renderSurfaceLayer->m_renderSurface); + CCLayerImpl* renderSurfaceLayer = renderSurfaceLayerList[surfaceIndex]; + ASSERT(renderSurfaceLayer->renderSurface()); // Render surfaces whose drawable area has zero width or height // will have no layers associated with them and should be skipped. - if (!renderSurfaceLayer->m_renderSurface->m_layerList.size()) + if (!renderSurfaceLayer->renderSurface()->m_layerList.size()) continue; - if (useRenderSurface(renderSurfaceLayer->m_renderSurface.get())) { - if (renderSurfaceLayer != m_rootLayer) { + if (useRenderSurface(renderSurfaceLayer->renderSurface())) { + if (renderSurfaceLayer != rootDrawLayer) { GLC(m_context.get(), m_context->disable(GraphicsContext3D::SCISSOR_TEST)); GLC(m_context.get(), m_context->clearColor(0, 0, 0, 0)); GLC(m_context.get(), m_context->clear(GraphicsContext3D::COLOR_BUFFER_BIT)); GLC(m_context.get(), m_context->enable(GraphicsContext3D::SCISSOR_TEST)); } - Vector<LayerChromium*>& layerList = renderSurfaceLayer->m_renderSurface->m_layerList; + Vector<CCLayerImpl*>& layerList = renderSurfaceLayer->renderSurface()->m_layerList; ASSERT(layerList.size()); for (unsigned layerIndex = 0; layerIndex < layerList.size(); ++layerIndex) - drawLayer(layerList[layerIndex], renderSurfaceLayer->m_renderSurface.get()); + drawLayer(layerList[layerIndex], renderSurfaceLayer->renderSurface()); } } + if (m_headsUpDisplay->enabled()) { + GLC(m_context.get(), m_context->enable(GraphicsContext3D::BLEND)); + GLC(m_context.get(), m_context->blendFunc(GraphicsContext3D::ONE, GraphicsContext3D::ONE_MINUS_SRC_ALPHA)); + GLC(m_context.get(), m_context->disable(GraphicsContext3D::SCISSOR_TEST)); + useRenderSurface(m_defaultRenderSurface); + m_headsUpDisplay->draw(); + } + GLC(m_context.get(), m_context->disable(GraphicsContext3D::SCISSOR_TEST)); GLC(m_context.get(), m_context->disable(GraphicsContext3D::BLEND)); } @@ -336,11 +373,15 @@ void LayerRendererChromium::present() // Note that currently this has the same effect as swapBuffers; we should // consider exposing a different entry point on GraphicsContext3D. m_context->prepareTexture(); + + m_headsUpDisplay->onPresent(); } void LayerRendererChromium::setRootLayer(PassRefPtr<LayerChromium> layer) { m_rootLayer = layer; + if (m_rootLayer) + m_rootLayer->setLayerRenderer(this); m_rootLayerTiler->invalidateEntireLayer(); if (m_horizontalScrollbarTiler) m_horizontalScrollbarTiler->invalidateEntireLayer(); @@ -350,8 +391,7 @@ void LayerRendererChromium::setRootLayer(PassRefPtr<LayerChromium> layer) void LayerRendererChromium::getFramebufferPixels(void *pixels, const IntRect& rect) { - ASSERT(rect.maxX() <= rootLayerTextureSize().width() - && rect.maxY() <= rootLayerTextureSize().height()); + ASSERT(rect.maxX() <= visibleRectSize().width() && rect.maxY() <= visibleRectSize().height()); if (!pixels) return; @@ -404,9 +444,10 @@ bool LayerRendererChromium::isLayerVisible(LayerChromium* layer, const Transform // Recursively walks the layer tree starting at the given node and computes all the // necessary transformations, scissor rectangles, render surfaces, etc. -void LayerRendererChromium::updateLayersRecursive(LayerChromium* layer, const TransformationMatrix& parentMatrix, Vector<LayerChromium*>& renderSurfaceLayerList, Vector<LayerChromium*>& layerList) +void LayerRendererChromium::updatePropertiesAndRenderSurfaces(LayerChromium* layer, const TransformationMatrix& parentMatrix, Vector<CCLayerImpl*>& renderSurfaceLayerList, Vector<CCLayerImpl*>& layerList) { layer->setLayerRenderer(this); + CCLayerImpl* drawLayer = layer->ccLayerImpl(); // Compute the new matrix transformation that will be applied to this layer and // all its sublayers. It's important to remember that the layer's position @@ -459,25 +500,26 @@ void LayerRendererChromium::updateLayersRecursive(LayerChromium* layer, const Tr // of their parent. bool useSurfaceForClipping = layer->masksToBounds() && !isScaleOrTranslation(combinedTransform); bool useSurfaceForOpacity = layer->opacity() != 1 && !layer->preserves3D(); - bool useSurfaceForMasking = layer->maskLayer(); + bool useSurfaceForMasking = layer->maskDrawLayer(); bool useSurfaceForReflection = layer->replicaLayer(); if (((useSurfaceForClipping || useSurfaceForOpacity) && layer->descendantsDrawContent()) || useSurfaceForMasking || useSurfaceForReflection) { - RenderSurfaceChromium* renderSurface = layer->m_renderSurface.get(); + RenderSurfaceChromium* renderSurface = drawLayer->renderSurface(); if (!renderSurface) - renderSurface = layer->createRenderSurface(); + renderSurface = drawLayer->createRenderSurface(); // The origin of the new surface is the upper left corner of the layer. - layer->m_drawTransform = TransformationMatrix(); - layer->m_drawTransform.translate3d(0.5 * bounds.width(), 0.5 * bounds.height(), 0); + TransformationMatrix drawTransform; + drawTransform.translate3d(0.5 * bounds.width(), 0.5 * bounds.height(), 0); + drawLayer->setDrawTransform(drawTransform); transformedLayerRect = IntRect(0, 0, bounds.width(), bounds.height()); // Layer's opacity will be applied when drawing the render surface. renderSurface->m_drawOpacity = layer->opacity(); - if (layer->superlayer()->preserves3D()) - renderSurface->m_drawOpacity *= layer->superlayer()->drawOpacity(); - layer->m_drawOpacity = 1; + if (layer->superlayer() && layer->superlayer()->preserves3D()) + renderSurface->m_drawOpacity *= drawLayer->superlayer()->drawOpacity(); + drawLayer->setDrawOpacity(1); TransformationMatrix layerOriginTransform = combinedTransform; layerOriginTransform.translate3d(-0.5 * bounds.width(), -0.5 * bounds.height(), 0); @@ -485,69 +527,72 @@ void LayerRendererChromium::updateLayersRecursive(LayerChromium* layer, const Tr if (layerOriginTransform.isInvertible() && layer->superlayer()) { TransformationMatrix parentToLayer = layerOriginTransform.inverse(); - layer->m_scissorRect = parentToLayer.mapRect(layer->superlayer()->m_scissorRect); + drawLayer->setScissorRect(parentToLayer.mapRect(drawLayer->superlayer()->scissorRect())); } else - layer->m_scissorRect = IntRect(); + drawLayer->setScissorRect(IntRect()); // The render surface scissor rect is the scissor rect that needs to // be applied before drawing the render surface onto its containing // surface and is therefore expressed in the superlayer's coordinate system. - renderSurface->m_scissorRect = layer->superlayer()->m_scissorRect; + renderSurface->m_scissorRect = drawLayer->superlayer() ? drawLayer->superlayer()->scissorRect() : drawLayer->scissorRect(); renderSurface->m_layerList.clear(); - if (layer->maskLayer()) { - renderSurface->m_maskLayer = layer->maskLayer(); - layer->maskLayer()->setLayerRenderer(this); - layer->maskLayer()->m_targetRenderSurface = renderSurface; + if (layer->maskDrawLayer()) { + renderSurface->m_maskLayer = layer->maskDrawLayer(); + layer->maskDrawLayer()->setLayerRenderer(this); + layer->maskDrawLayer()->setTargetRenderSurface(renderSurface); } else renderSurface->m_maskLayer = 0; - if (layer->replicaLayer() && layer->replicaLayer()->maskLayer()) { - layer->replicaLayer()->maskLayer()->setLayerRenderer(this); - layer->replicaLayer()->maskLayer()->m_targetRenderSurface = renderSurface; + if (layer->replicaLayer() && layer->replicaLayer()->maskDrawLayer()) { + layer->replicaLayer()->maskDrawLayer()->setLayerRenderer(this); + layer->replicaLayer()->maskDrawLayer()->setTargetRenderSurface(renderSurface); } - renderSurfaceLayerList.append(layer); + renderSurfaceLayerList.append(drawLayer); } else { // DT = M[p] * LT - layer->m_drawTransform = combinedTransform; - transformedLayerRect = enclosingIntRect(layer->m_drawTransform.mapRect(layerRect)); + drawLayer->setDrawTransform(combinedTransform); + transformedLayerRect = enclosingIntRect(drawLayer->drawTransform().mapRect(layerRect)); - layer->m_drawOpacity = layer->opacity(); + drawLayer->setDrawOpacity(layer->opacity()); if (layer->superlayer()) { if (layer->superlayer()->preserves3D()) - layer->m_drawOpacity *= layer->superlayer()->m_drawOpacity; + drawLayer->setDrawOpacity(drawLayer->drawOpacity() * drawLayer->superlayer()->drawOpacity()); // Layers inherit the scissor rect from their superlayer. - layer->m_scissorRect = layer->superlayer()->m_scissorRect; + drawLayer->setScissorRect(drawLayer->superlayer()->scissorRect()); - layer->m_targetRenderSurface = layer->superlayer()->m_targetRenderSurface; + drawLayer->setTargetRenderSurface(drawLayer->superlayer()->targetRenderSurface()); } if (layer != m_rootLayer) - layer->m_renderSurface = 0; + drawLayer->clearRenderSurface(); - if (layer->masksToBounds()) - layer->m_scissorRect.intersect(transformedLayerRect); + if (layer->masksToBounds()) { + IntRect scissor = drawLayer->scissorRect(); + scissor.intersect(transformedLayerRect); + drawLayer->setScissorRect(scissor); + } } - if (layer->m_renderSurface) - layer->m_targetRenderSurface = layer->m_renderSurface.get(); + if (drawLayer->renderSurface()) + drawLayer->setTargetRenderSurface(drawLayer->renderSurface()); else { ASSERT(layer->superlayer()); - layer->m_targetRenderSurface = layer->superlayer()->m_targetRenderSurface; + drawLayer->setTargetRenderSurface(drawLayer->superlayer()->targetRenderSurface()); } - // m_drawableContentRect is always stored in the coordinate system of the + // drawableContentRect() is always stored in the coordinate system of the // RenderSurface the layer draws into. - if (layer->drawsContent()) - layer->m_drawableContentRect = transformedLayerRect; + if (drawLayer->drawsContent()) + drawLayer->setDrawableContentRect(transformedLayerRect); else - layer->m_drawableContentRect = IntRect(); + drawLayer->setDrawableContentRect(IntRect()); - TransformationMatrix sublayerMatrix = layer->m_drawTransform; + TransformationMatrix sublayerMatrix = drawLayer->drawTransform(); // Flatten to 2D if the layer doesn't preserve 3D. if (!layer->preserves3D()) { @@ -568,37 +613,46 @@ void LayerRendererChromium::updateLayersRecursive(LayerChromium* layer, const Tr // M[s] = M * Tr[-center] sublayerMatrix.translate3d(-bounds.width() * 0.5, -bounds.height() * 0.5, 0); - Vector<LayerChromium*>& descendants = (layer->m_renderSurface ? layer->m_renderSurface->m_layerList : layerList); - descendants.append(layer); + Vector<CCLayerImpl*>& descendants = (drawLayer->renderSurface() ? drawLayer->renderSurface()->m_layerList : layerList); + descendants.append(drawLayer); unsigned thisLayerIndex = descendants.size() - 1; const Vector<RefPtr<LayerChromium> >& sublayers = layer->getSublayers(); for (size_t i = 0; i < sublayers.size(); ++i) { - LayerChromium* sublayer = sublayers[i].get(); - updateLayersRecursive(sublayer, sublayerMatrix, renderSurfaceLayerList, descendants); - - if (sublayer->m_renderSurface) { - RenderSurfaceChromium* sublayerRenderSurface = sublayer->m_renderSurface.get(); - layer->m_drawableContentRect.unite(enclosingIntRect(sublayerRenderSurface->drawableContentRect())); + CCLayerImpl* sublayer = sublayers[i]->ccLayerImpl(); + updatePropertiesAndRenderSurfaces(sublayers[i].get(), sublayerMatrix, renderSurfaceLayerList, descendants); + + if (sublayer->renderSurface()) { + RenderSurfaceChromium* sublayerRenderSurface = sublayer->renderSurface(); + IntRect drawableContentRect = drawLayer->drawableContentRect(); + drawableContentRect.unite(enclosingIntRect(sublayerRenderSurface->drawableContentRect())); + drawLayer->setDrawableContentRect(drawableContentRect); descendants.append(sublayer); - } else - layer->m_drawableContentRect.unite(sublayer->m_drawableContentRect); + } else { + IntRect drawableContentRect = drawLayer->drawableContentRect(); + drawableContentRect.unite(sublayer->drawableContentRect()); + drawLayer->setDrawableContentRect(drawableContentRect); + } } - if (layer->masksToBounds() || useSurfaceForMasking) - layer->m_drawableContentRect.intersect(transformedLayerRect); + if (layer->masksToBounds() || useSurfaceForMasking) { + IntRect drawableContentRect = drawLayer->drawableContentRect(); + drawableContentRect.intersect(transformedLayerRect); + drawLayer->setDrawableContentRect(drawableContentRect); + } - if (layer->m_renderSurface && layer != m_rootLayer) { - RenderSurfaceChromium* renderSurface = layer->m_renderSurface.get(); - renderSurface->m_contentRect = layer->m_drawableContentRect; + if (drawLayer->renderSurface() && layer != m_rootLayer) { + RenderSurfaceChromium* renderSurface = drawLayer->renderSurface(); + renderSurface->m_contentRect = drawLayer->drawableContentRect(); FloatPoint surfaceCenter = renderSurface->contentRectCenter(); // Restrict the RenderSurface size to the portion that's visible. FloatSize centerOffsetDueToClipping; + // Don't clip if the layer is reflected as the reflection shouldn't be // clipped. if (!layer->replicaLayer()) { - renderSurface->m_contentRect.intersect(layer->m_scissorRect); + renderSurface->m_contentRect.intersect(drawLayer->scissorRect()); FloatPoint clippedSurfaceCenter = renderSurface->contentRectCenter(); centerOffsetDueToClipping = clippedSurfaceCenter - surfaceCenter; } @@ -613,7 +667,7 @@ void LayerRendererChromium::updateLayersRecursive(LayerChromium* layer, const Tr // Since the layer starts a new render surface we need to adjust its // scissor rect to be expressed in the new surface's coordinate system. - layer->m_scissorRect = layer->m_drawableContentRect; + drawLayer->setScissorRect(drawLayer->drawableContentRect()); // Adjust the origin of the transform to be the center of the render surface. renderSurface->m_drawTransform = renderSurface->m_originTransform; @@ -631,14 +685,14 @@ void LayerRendererChromium::updateLayersRecursive(LayerChromium* layer, const Tr // Compute the depth value of the center of the layer which will be used when // sorting the layers for the preserves-3d property. - TransformationMatrix& layerDrawMatrix = layer->m_renderSurface ? layer->m_renderSurface->m_drawTransform : layer->m_drawTransform; + const TransformationMatrix& layerDrawMatrix = drawLayer->renderSurface() ? drawLayer->renderSurface()->m_drawTransform : drawLayer->drawTransform(); if (layer->superlayer()) { if (!layer->superlayer()->preserves3D()) - layer->m_drawDepth = layer->superlayer()->m_drawDepth; + drawLayer->setDrawDepth(drawLayer->superlayer()->drawDepth()); else - layer->m_drawDepth = layerDrawMatrix.m43(); + drawLayer->setDrawDepth(layerDrawMatrix.m43()); } else - layer->m_drawDepth = 0; + drawLayer->setDrawDepth(0); // If preserves-3d then sort all the descendants by the Z coordinate of their // center. If the preserves-3d property is also set on the superlayer then @@ -647,21 +701,50 @@ void LayerRendererChromium::updateLayersRecursive(LayerChromium* layer, const Tr std::stable_sort(&descendants.at(thisLayerIndex), descendants.end(), compareLayerZ); } +void LayerRendererChromium::updateContentsRecursive(LayerChromium* layer) +{ + const Vector<RefPtr<LayerChromium> >& sublayers = layer->getSublayers(); + for (size_t i = 0; i < sublayers.size(); ++i) + updateContentsRecursive(sublayers[i].get()); + + if (layer->drawsContent()) + layer->updateContentsIfDirty(); + if (layer->maskLayer() && layer->maskLayer()->drawsContent()) + layer->maskLayer()->updateContentsIfDirty(); + if (layer->replicaLayer() && layer->replicaLayer()->drawsContent()) + layer->replicaLayer()->updateContentsIfDirty(); + if (layer->replicaLayer() && layer->replicaLayer()->maskLayer() && layer->replicaLayer()->maskLayer()->drawsContent()) + layer->replicaLayer()->maskLayer()->updateContentsIfDirty(); +} + void LayerRendererChromium::setCompositeOffscreen(bool compositeOffscreen) { + if (m_compositeOffscreen == compositeOffscreen) + return; + m_compositeOffscreen = compositeOffscreen; - if (!m_rootLayer) { - m_compositeOffscreen = false; - return; - } + if (!m_compositeOffscreen && m_rootLayer) + m_rootLayer->ccLayerImpl()->clearRenderSurface(); +} + +LayerTexture* LayerRendererChromium::getOffscreenLayerTexture() +{ + return m_compositeOffscreen ? m_rootLayer->ccLayerImpl()->renderSurface()->m_contentsTexture.get() : 0; +} +void LayerRendererChromium::copyOffscreenTextureToDisplay() +{ if (m_compositeOffscreen) { - // Need to explicitly set a LayerRendererChromium for the layer with the offscreen texture, - // or else the call to prepareContentsTexture() in useRenderSurface() will fail. - m_rootLayer->setLayerRenderer(this); - } else - m_rootLayer->m_renderSurface.clear(); + makeContextCurrent(); + + useRenderSurface(0); + m_defaultRenderSurface->m_drawTransform.makeIdentity(); + m_defaultRenderSurface->m_drawTransform.translate3d(0.5 * m_defaultRenderSurface->m_contentRect.width(), + 0.5 * m_defaultRenderSurface->m_contentRect.height(), 0); + m_defaultRenderSurface->m_drawOpacity = 1; + m_defaultRenderSurface->draw(); + } } bool LayerRendererChromium::useRenderSurface(RenderSurfaceChromium* renderSurface) @@ -671,9 +754,12 @@ bool LayerRendererChromium::useRenderSurface(RenderSurfaceChromium* renderSurfac m_currentRenderSurface = renderSurface; - if (renderSurface == m_defaultRenderSurface && !m_compositeOffscreen) { + if ((renderSurface == m_defaultRenderSurface && !m_compositeOffscreen) || (!renderSurface && m_compositeOffscreen)) { GLC(m_context.get(), m_context->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, 0)); - setDrawViewportRect(renderSurface->m_contentRect, true); + if (renderSurface) + setDrawViewportRect(renderSurface->m_contentRect, true); + else + setDrawViewportRect(m_defaultRenderSurface->m_contentRect, true); return true; } @@ -695,36 +781,32 @@ bool LayerRendererChromium::useRenderSurface(RenderSurfaceChromium* renderSurfac return true; } -void LayerRendererChromium::drawLayer(LayerChromium* layer, RenderSurfaceChromium* targetSurface) +void LayerRendererChromium::drawLayer(CCLayerImpl* layer, RenderSurfaceChromium* targetSurface) { - if (layer->m_renderSurface && layer->m_renderSurface != targetSurface) { - layer->m_renderSurface->draw(); + if (layer->renderSurface() && layer->renderSurface() != targetSurface) { + layer->renderSurface()->draw(); return; } - if (layer->m_bounds.isEmpty()) + if (layer->bounds().isEmpty()) return; - setScissorToRect(layer->m_scissorRect); + setScissorToRect(layer->scissorRect()); // Check if the layer falls within the visible bounds of the page. IntRect layerRect = layer->getDrawRect(); - bool isLayerVisible = layer->m_scissorRect.intersects(layerRect); + bool isLayerVisible = layer->scissorRect().intersects(layerRect); if (!isLayerVisible) return; // FIXME: Need to take into account the commulative render surface transforms all the way from // the default render surface in order to determine visibility. - TransformationMatrix combinedDrawMatrix = (layer->m_renderSurface ? layer->m_renderSurface->drawTransform().multiply(layer->m_drawTransform) : layer->m_drawTransform); + TransformationMatrix combinedDrawMatrix = (layer->renderSurface() ? layer->renderSurface()->drawTransform().multiply(layer->drawTransform()) : layer->drawTransform()); if (!layer->doubleSided() && combinedDrawMatrix.m33() < 0) return; - if (layer->drawsContent()) { - // Update the contents of the layer if necessary. - layer->updateContentsIfDirty(); - m_context->makeContextCurrent(); + if (layer->drawsContent()) layer->draw(); - } // Draw the debug border if there is one. layer->drawDebugBorder(); @@ -734,9 +816,11 @@ void LayerRendererChromium::drawLayer(LayerChromium* layer, RenderSurfaceChromiu // scissorRect has its origin at the top left corner of the current visible rect. void LayerRendererChromium::setScissorToRect(const IntRect& scissorRect) { + IntRect contentRect = (m_currentRenderSurface ? m_currentRenderSurface->m_contentRect : m_defaultRenderSurface->m_contentRect); + // The scissor coordinates must be supplied in viewport space so we need to offset // by the relative position of the top left corner of the current render surface. - int scissorX = scissorRect.x() - m_currentRenderSurface->m_contentRect.x(); + int scissorX = scissorRect.x() - contentRect.x(); // When rendering to the default render surface we're rendering upside down so the top // of the GL scissor is the bottom of our layer. // But, if rendering to offscreen texture, we reverse our sense of 'upside down'. @@ -744,7 +828,7 @@ void LayerRendererChromium::setScissorToRect(const IntRect& scissorRect) if (m_currentRenderSurface == m_defaultRenderSurface && !m_compositeOffscreen) scissorY = m_currentRenderSurface->m_contentRect.height() - (scissorRect.maxY() - m_currentRenderSurface->m_contentRect.y()); else - scissorY = scissorRect.y() - m_currentRenderSurface->m_contentRect.y(); + scissorY = scissorRect.y() - contentRect.y(); GLC(m_context.get(), m_context->scissor(scissorX, scissorY, scissorRect.width(), scissorRect.height())); } @@ -793,15 +877,23 @@ bool LayerRendererChromium::initializeSharedObjects() // Create an FBO for doing offscreen rendering. GLC(m_context.get(), m_offscreenFramebufferId = m_context->createFramebuffer()); - m_layerSharedValues = adoptPtr(new LayerChromium::SharedValues(m_context.get())); - m_contentLayerSharedValues = adoptPtr(new ContentLayerChromium::SharedValues(m_context.get())); - m_canvasLayerSharedValues = adoptPtr(new CanvasLayerChromium::SharedValues(m_context.get())); - m_videoLayerSharedValues = adoptPtr(new VideoLayerChromium::SharedValues(m_context.get())); - m_pluginLayerSharedValues = adoptPtr(new PluginLayerChromium::SharedValues(m_context.get())); - m_renderSurfaceSharedValues = adoptPtr(new RenderSurfaceChromium::SharedValues(m_context.get())); - - if (!m_layerSharedValues->initialized() || !m_contentLayerSharedValues->initialized() || !m_canvasLayerSharedValues->initialized() - || !m_videoLayerSharedValues->initialized() || !m_pluginLayerSharedValues->initialized() || !m_renderSurfaceSharedValues->initialized()) { + m_sharedGeometry = adoptPtr(new GeometryBinding(m_context.get())); + m_borderProgram = adoptPtr(new LayerChromium::BorderProgram(m_context.get())); + m_contentLayerProgram = adoptPtr(new ContentLayerChromium::Program(m_context.get())); + m_canvasLayerProgram = adoptPtr(new CanvasLayerChromium::Program(m_context.get())); + m_videoLayerRGBAProgram = adoptPtr(new VideoLayerChromium::RGBAProgram(m_context.get())); + m_videoLayerYUVProgram = adoptPtr(new VideoLayerChromium::YUVProgram(m_context.get())); + m_pluginLayerProgram = adoptPtr(new PluginLayerChromium::Program(m_context.get())); + m_renderSurfaceProgram = adoptPtr(new RenderSurfaceChromium::Program(m_context.get())); + m_renderSurfaceMaskProgram = adoptPtr(new RenderSurfaceChromium::MaskProgram(m_context.get())); + m_tilerProgram = adoptPtr(new LayerTilerChromium::Program(m_context.get())); + + if (!m_sharedGeometry->initialized() || !m_borderProgram->initialized() + || !m_contentLayerProgram->initialized() || !m_canvasLayerProgram->initialized() + || !m_videoLayerRGBAProgram->initialized() || !m_videoLayerYUVProgram->initialized() + || !m_pluginLayerProgram->initialized() || !m_renderSurfaceProgram->initialized() + || !m_renderSurfaceMaskProgram->initialized() || !m_tilerProgram->initialized()) { + LOG_ERROR("Compositor failed to initialize shaders. Falling back to software."); cleanupSharedObjects(); return false; } @@ -814,12 +906,16 @@ void LayerRendererChromium::cleanupSharedObjects() { makeContextCurrent(); - m_layerSharedValues.clear(); - m_contentLayerSharedValues.clear(); - m_canvasLayerSharedValues.clear(); - m_videoLayerSharedValues.clear(); - m_pluginLayerSharedValues.clear(); - m_renderSurfaceSharedValues.clear(); + m_sharedGeometry.clear(); + m_borderProgram.clear(); + m_contentLayerProgram.clear(); + m_canvasLayerProgram.clear(); + m_videoLayerRGBAProgram.clear(); + m_videoLayerYUVProgram.clear(); + m_pluginLayerProgram.clear(); + m_renderSurfaceProgram.clear(); + m_renderSurfaceMaskProgram.clear(); + m_tilerProgram.clear(); if (m_offscreenFramebufferId) GLC(m_context.get(), m_context->deleteFramebuffer(m_offscreenFramebufferId)); @@ -831,6 +927,26 @@ void LayerRendererChromium::cleanupSharedObjects() m_textureManager.clear(); } +String LayerRendererChromium::layerTreeAsText() const +{ + TextStream ts; + if (m_rootLayer.get()) { + ts << m_rootLayer->layerTreeAsText(); + ts << "RenderSurfaces:\n"; + dumpRenderSurfaces(ts, 1, m_rootLayer.get()); + } + return ts.release(); +} + +void LayerRendererChromium::dumpRenderSurfaces(TextStream& ts, int indent, LayerChromium* layer) const +{ + if (layer->ccLayerImpl()->renderSurface()) + layer->ccLayerImpl()->renderSurface()->dumpSurface(ts, indent); + + for (size_t i = 0; i < layer->getSublayers().size(); ++i) + dumpRenderSurfaces(ts, indent, layer->getSublayers()[i].get()); +} + } // namespace WebCore #endif // USE(ACCELERATED_COMPOSITING) diff --git a/Source/WebCore/platform/graphics/chromium/LayerRendererChromium.h b/Source/WebCore/platform/graphics/chromium/LayerRendererChromium.h index 3d3e784..7e8850a 100644 --- a/Source/WebCore/platform/graphics/chromium/LayerRendererChromium.h +++ b/Source/WebCore/platform/graphics/chromium/LayerRendererChromium.h @@ -43,6 +43,7 @@ #include "RenderSurfaceChromium.h" #include "SkBitmap.h" #include "VideoLayerChromium.h" +#include "cc/CCHeadsUpDisplay.h" #include <wtf/HashMap.h> #include <wtf/Noncopyable.h> #include <wtf/PassOwnPtr.h> @@ -57,7 +58,10 @@ namespace WebCore { +class CCLayerImpl; +class GeometryBinding; class GraphicsContext3D; +class CCHeadsUpDisplay; // Class that handles drawing of composited render layers using GL. class LayerRendererChromium : public RefCounted<LayerRendererChromium> { @@ -71,9 +75,8 @@ public: void invalidateRootLayerRect(const IntRect& dirtyRect, const IntRect& visibleRect, const IntRect& contentRect); // updates and draws the current layers onto the backbuffer - void drawLayers(const IntRect& visibleRect, const IntRect& contentRect, - const IntPoint& scrollPosition, TilePaintInterface& tilePaint, - TilePaintInterface& scrollbarPaint); + void updateAndDrawLayers(const IntRect& visibleRect, const IntRect& contentRect, const IntPoint& scrollPosition, + TilePaintInterface&, TilePaintInterface& scrollbarPaint); // waits for rendering to finish void finish(); @@ -81,6 +84,8 @@ public: // puts backbuffer onscreen void present(); + IntSize visibleRectSize() const { return m_visibleRect.size(); } + void setRootLayer(PassRefPtr<LayerChromium> layer); LayerChromium* rootLayer() { return m_rootLayer.get(); } void transferRootLayer(LayerRendererChromium* other) { other->m_rootLayer = m_rootLayer.release(); } @@ -88,12 +93,9 @@ public: bool hardwareCompositing() const { return m_hardwareCompositing; } void setCompositeOffscreen(bool); - bool isCompositingOffscreen() { return m_compositeOffscreen; } - LayerTexture* getOffscreenLayerTexture() { return m_compositeOffscreen ? m_rootLayer->m_renderSurface->m_contentsTexture.get() : 0; } - - void setRootLayerCanvasSize(const IntSize&); - - GraphicsContext* rootLayerGraphicsContext() const { return m_rootLayerGraphicsContext.get(); } + bool isCompositingOffscreen() const { return m_compositeOffscreen; } + LayerTexture* getOffscreenLayerTexture(); + void copyOffscreenTextureToDisplay(); unsigned createLayerTexture(); void deleteLayerTexture(unsigned); @@ -106,30 +108,43 @@ public: bool checkTextureSize(const IntSize&); - const LayerChromium::SharedValues* layerSharedValues() const { return m_layerSharedValues.get(); } - const ContentLayerChromium::SharedValues* contentLayerSharedValues() const { return m_contentLayerSharedValues.get(); } - const CanvasLayerChromium::SharedValues* canvasLayerSharedValues() const { return m_canvasLayerSharedValues.get(); } - const VideoLayerChromium::SharedValues* videoLayerSharedValues() const { return m_videoLayerSharedValues.get(); } - const PluginLayerChromium::SharedValues* pluginLayerSharedValues() const { return m_pluginLayerSharedValues.get(); } - const RenderSurfaceChromium::SharedValues* renderSurfaceSharedValues() const { return m_renderSurfaceSharedValues.get(); } + const GeometryBinding* sharedGeometry() const { return m_sharedGeometry.get(); } + const LayerChromium::BorderProgram* borderProgram() const { return m_borderProgram.get(); } + const ContentLayerChromium::Program* contentLayerProgram() const { return m_contentLayerProgram.get(); } + const CanvasLayerChromium::Program* canvasLayerProgram() const { return m_canvasLayerProgram.get(); } + const VideoLayerChromium::RGBAProgram* videoLayerRGBAProgram() const { return m_videoLayerRGBAProgram.get(); } + const VideoLayerChromium::YUVProgram* videoLayerYUVProgram() const { return m_videoLayerYUVProgram.get(); } + const PluginLayerChromium::Program* pluginLayerProgram() const { return m_pluginLayerProgram.get(); } + const RenderSurfaceChromium::Program* renderSurfaceProgram() const { return m_renderSurfaceProgram.get(); } + const RenderSurfaceChromium::MaskProgram* renderSurfaceMaskProgram() const { return m_renderSurfaceMaskProgram.get(); } + const LayerTilerChromium::Program* tilerProgram() const { return m_tilerProgram.get(); } void resizeOnscreenContent(const IntSize&); - IntSize rootLayerTextureSize() const { return IntSize(m_rootLayerTextureWidth, m_rootLayerTextureHeight); } - IntRect rootLayerContentRect() const { return m_rootContentRect; } void getFramebufferPixels(void *pixels, const IntRect& rect); TextureManager* textureManager() const { return m_textureManager.get(); } + CCHeadsUpDisplay* headsUpDisplay() { return m_headsUpDisplay.get(); } + void setScissorToRect(const IntRect&); + String layerTreeAsText() const; + private: explicit LayerRendererChromium(PassRefPtr<GraphicsContext3D> graphicsContext3D); - void updateLayersRecursive(LayerChromium* layer, const TransformationMatrix& parentMatrix, Vector<LayerChromium*>& renderSurfaceLayerList, Vector<LayerChromium*>& layerList); - void drawLayer(LayerChromium*, RenderSurfaceChromium*); + void updateLayers(const IntRect& visibleRect, const IntRect& contentRect, const IntPoint& scrollPosition, + Vector<CCLayerImpl*>& renderSurfaceLayerList); + void updateRootLayerContents(TilePaintInterface&, const IntRect& visibleRect); + void updateRootLayerScrollbars(TilePaintInterface& scrollbarPaint, const IntRect& visibleRect, const IntRect& contentRect); + void updatePropertiesAndRenderSurfaces(LayerChromium*, const TransformationMatrix& parentMatrix, Vector<CCLayerImpl*>& renderSurfaceLayerList, Vector<CCLayerImpl*>& layerList); + void updateContentsRecursive(LayerChromium*); - void updateAndDrawRootLayer(TilePaintInterface& tilePaint, TilePaintInterface& scrollbarPaint, const IntRect& visibleRect, const IntRect& contentRect); + void drawLayers(const Vector<CCLayerImpl*>& renderSurfaceLayerList); + void drawLayer(CCLayerImpl*, RenderSurfaceChromium*); + + void drawRootLayer(); bool isLayerVisible(LayerChromium*, const TransformationMatrix&, const IntRect& visibleRect); @@ -139,7 +154,9 @@ private: bool makeContextCurrent(); - static bool compareLayerZ(const LayerChromium*, const LayerChromium*); + static bool compareLayerZ(const CCLayerImpl*, const CCLayerImpl*); + + void dumpRenderSurfaces(TextStream&, int indent, LayerChromium*) const; bool initializeSharedObjects(); void cleanupSharedObjects(); @@ -147,8 +164,7 @@ private: static IntRect verticalScrollbarRect(const IntRect& visibleRect, const IntRect& contentRect); static IntRect horizontalScrollbarRect(const IntRect& visibleRect, const IntRect& contentRect); - int m_rootLayerTextureWidth; - int m_rootLayerTextureHeight; + IntRect m_visibleRect; TransformationMatrix m_projectionMatrix; @@ -166,7 +182,7 @@ private: unsigned m_offscreenFramebufferId; bool m_compositeOffscreen; -#if PLATFORM(SKIA) +#if USE(SKIA) OwnPtr<skia::PlatformCanvas> m_rootLayerCanvas; OwnPtr<PlatformContextSkia> m_rootLayerSkiaContext; OwnPtr<GraphicsContext> m_rootLayerGraphicsContext; @@ -176,11 +192,6 @@ private: OwnPtr<GraphicsContext> m_rootLayerGraphicsContext; #endif - IntSize m_rootLayerCanvasSize; - - IntRect m_rootVisibleRect; - IntRect m_rootContentRect; - // Maximum texture dimensions supported. int m_maxTextureSize; @@ -188,15 +199,21 @@ private: // associated with this instance of the compositor. Since there can be // multiple instances of the compositor running in the same renderer process // we cannot store these values in static variables. - OwnPtr<LayerChromium::SharedValues> m_layerSharedValues; - OwnPtr<ContentLayerChromium::SharedValues> m_contentLayerSharedValues; - OwnPtr<CanvasLayerChromium::SharedValues> m_canvasLayerSharedValues; - OwnPtr<VideoLayerChromium::SharedValues> m_videoLayerSharedValues; - OwnPtr<PluginLayerChromium::SharedValues> m_pluginLayerSharedValues; - OwnPtr<RenderSurfaceChromium::SharedValues> m_renderSurfaceSharedValues; + OwnPtr<GeometryBinding> m_sharedGeometry; + OwnPtr<LayerChromium::BorderProgram> m_borderProgram; + OwnPtr<ContentLayerChromium::Program> m_contentLayerProgram; + OwnPtr<CanvasLayerChromium::Program> m_canvasLayerProgram; + OwnPtr<VideoLayerChromium::RGBAProgram> m_videoLayerRGBAProgram; + OwnPtr<VideoLayerChromium::YUVProgram> m_videoLayerYUVProgram; + OwnPtr<PluginLayerChromium::Program> m_pluginLayerProgram; + OwnPtr<RenderSurfaceChromium::Program> m_renderSurfaceProgram; + OwnPtr<RenderSurfaceChromium::MaskProgram> m_renderSurfaceMaskProgram; + OwnPtr<LayerTilerChromium::Program> m_tilerProgram; OwnPtr<TextureManager> m_textureManager; + OwnPtr<CCHeadsUpDisplay> m_headsUpDisplay; + RefPtr<GraphicsContext3D> m_context; RenderSurfaceChromium* m_defaultRenderSurface; diff --git a/Source/WebCore/platform/graphics/chromium/LayerTilerChromium.cpp b/Source/WebCore/platform/graphics/chromium/LayerTilerChromium.cpp index e28c084..86592a6 100644 --- a/Source/WebCore/platform/graphics/chromium/LayerTilerChromium.cpp +++ b/Source/WebCore/platform/graphics/chromium/LayerTilerChromium.cpp @@ -35,27 +35,23 @@ #include "LayerRendererChromium.h" #include "LayerTexture.h" -#if PLATFORM(SKIA) -#include "NativeImageSkia.h" -#include "PlatformContextSkia.h" -#elif PLATFORM(CG) -#include <CoreGraphics/CGBitmapContext.h> -#endif - #include <wtf/PassOwnArrayPtr.h> +using namespace std; + namespace WebCore { -PassOwnPtr<LayerTilerChromium> LayerTilerChromium::create(LayerRendererChromium* layerRenderer, const IntSize& tileSize) +PassOwnPtr<LayerTilerChromium> LayerTilerChromium::create(LayerRendererChromium* layerRenderer, const IntSize& tileSize, BorderTexelOption border) { if (!layerRenderer || tileSize.isEmpty()) return 0; - return adoptPtr(new LayerTilerChromium(layerRenderer, tileSize)); + return adoptPtr(new LayerTilerChromium(layerRenderer, tileSize, border)); } -LayerTilerChromium::LayerTilerChromium(LayerRendererChromium* layerRenderer, const IntSize& tileSize) +LayerTilerChromium::LayerTilerChromium(LayerRendererChromium* layerRenderer, const IntSize& tileSize, BorderTexelOption border) : m_skipsDraw(false) + , m_tilingData(max(tileSize.width(), tileSize.height()), 0, 0, border == HasBorderTexels) , m_layerRenderer(layerRenderer) { setTileSize(tileSize); @@ -81,6 +77,7 @@ void LayerTilerChromium::setTileSize(const IntSize& size) m_tileSize = size; m_tilePixels = adoptArrayPtr(new uint8_t[m_tileSize.width() * m_tileSize.height() * 4]); + m_tilingData.setMaxTextureSize(max(size.width(), size.height())); } void LayerTilerChromium::reset() @@ -88,8 +85,7 @@ void LayerTilerChromium::reset() m_tiles.clear(); m_unusedTiles.clear(); - m_layerSize = IntSize(); - m_layerTileSize = IntSize(); + m_tilingData.setTotalSize(0, 0); m_lastUpdateLayerRect = IntRect(); } @@ -143,10 +139,10 @@ void LayerTilerChromium::contentRectToTileIndices(const IntRect& contentRect, in { const IntRect layerRect = contentRectToLayerRect(contentRect); - left = layerRect.x() / m_tileSize.width(); - top = layerRect.y() / m_tileSize.height(); - right = (layerRect.maxX() - 1) / m_tileSize.width(); - bottom = (layerRect.maxY() - 1) / m_tileSize.height(); + left = m_tilingData.tileXIndexFromSrcCoord(layerRect.x()); + top = m_tilingData.tileYIndexFromSrcCoord(layerRect.y()); + right = m_tilingData.tileXIndexFromSrcCoord(layerRect.maxX() - 1); + bottom = m_tilingData.tileYIndexFromSrcCoord(layerRect.maxY() - 1); } IntRect LayerTilerChromium::contentRectToLayerRect(const IntRect& contentRect) const @@ -169,22 +165,32 @@ IntRect LayerTilerChromium::layerRectToContentRect(const IntRect& layerRect) con int LayerTilerChromium::tileIndex(int i, int j) const { - ASSERT(i >= 0 && j >= 0 && i < m_layerTileSize.width() && j < m_layerTileSize.height()); - return i + j * m_layerTileSize.width(); + return m_tilingData.tileIndex(i, j); } IntRect LayerTilerChromium::tileContentRect(int i, int j) const { - IntPoint anchor(m_layerPosition.x() + i * m_tileSize.width(), m_layerPosition.y() + j * m_tileSize.height()); - IntRect tile(anchor, m_tileSize); - return tile; + IntRect contentRect = tileLayerRect(i, j); + contentRect.move(m_layerPosition.x(), m_layerPosition.y()); + return contentRect; } IntRect LayerTilerChromium::tileLayerRect(int i, int j) const { - IntPoint anchor(i * m_tileSize.width(), j * m_tileSize.height()); - IntRect tile(anchor, m_tileSize); - return tile; + const int index = m_tilingData.tileIndex(i, j); + IntRect layerRect = m_tilingData.tileBoundsWithBorder(index); + layerRect.setSize(m_tileSize); + return layerRect; +} + +IntSize LayerTilerChromium::layerSize() const +{ + return IntSize(m_tilingData.totalSizeX(), m_tilingData.totalSizeY()); +} + +IntSize LayerTilerChromium::layerTileSize() const +{ + return IntSize(m_tilingData.numTilesX(), m_tilingData.numTilesY()); } void LayerTilerChromium::invalidateRect(const IntRect& contentRect) @@ -220,8 +226,7 @@ void LayerTilerChromium::invalidateEntireLayer() } m_tiles.clear(); - m_layerSize = IntSize(); - m_layerTileSize = IntSize(); + m_tilingData.setTotalSize(0, 0); m_lastUpdateLayerRect = IntRect(); } @@ -258,55 +263,26 @@ void LayerTilerChromium::update(TilePaintInterface& painter, const IntRect& cont return; const IntRect paintRect = layerRectToContentRect(dirtyLayerRect); - GraphicsContext3D* context = layerRendererContext(); -#if PLATFORM(SKIA) - OwnPtr<skia::PlatformCanvas> canvas(new skia::PlatformCanvas(paintRect.width(), paintRect.height(), false)); - OwnPtr<PlatformContextSkia> skiaContext(new PlatformContextSkia(canvas.get())); - OwnPtr<GraphicsContext> graphicsContext(new GraphicsContext(reinterpret_cast<PlatformGraphicsContext*>(skiaContext.get()))); - - // Bring the canvas into the coordinate system of the paint rect. - canvas->translate(static_cast<SkScalar>(-paintRect.x()), static_cast<SkScalar>(-paintRect.y())); - painter.paint(*graphicsContext, paintRect); + m_canvas.resize(paintRect.size()); + PlatformCanvas::Painter canvasPainter(&m_canvas); + canvasPainter.context()->translate(-paintRect.x(), -paintRect.y()); + painter.paint(*canvasPainter.context(), paintRect); - // Get the contents of the updated rect. - const SkBitmap& bitmap = canvas->getDevice()->accessBitmap(false); - ASSERT(bitmap.width() == paintRect.width() && bitmap.height() == paintRect.height()); - if (bitmap.width() != paintRect.width() || bitmap.height() != paintRect.height()) - CRASH(); - uint8_t* paintPixels = static_cast<uint8_t*>(bitmap.getPixels()); - if (!paintPixels) - CRASH(); -#elif PLATFORM(CG) - Vector<uint8_t> canvasPixels; - int rowBytes = 4 * paintRect.width(); - canvasPixels.resize(rowBytes * paintRect.height()); - memset(canvasPixels.data(), 0, canvasPixels.size()); - RetainPtr<CGColorSpaceRef> colorSpace(AdoptCF, CGColorSpaceCreateDeviceRGB()); - RetainPtr<CGContextRef> m_cgContext; - m_cgContext.adoptCF(CGBitmapContextCreate(canvasPixels.data(), - paintRect.width(), paintRect.height(), 8, rowBytes, - colorSpace.get(), - kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Host)); - CGContextTranslateCTM(m_cgContext.get(), 0, paintRect.height()); - CGContextScaleCTM(m_cgContext.get(), 1, -1); - OwnPtr<GraphicsContext> m_graphicsContext(new GraphicsContext(m_cgContext.get())); - - // Bring the CoreGraphics context into the coordinate system of the paint rect. - CGContextTranslateCTM(m_cgContext.get(), -paintRect.x(), -paintRect.y()); - painter.paint(*m_graphicsContext, paintRect); - - // Get the contents of the updated rect. - ASSERT(static_cast<int>(CGBitmapContextGetWidth(m_cgContext.get())) == paintRect.width() && static_cast<int>(CGBitmapContextGetHeight(m_cgContext.get())) == paintRect.height()); - uint8_t* paintPixels = static_cast<uint8_t*>(canvasPixels.data()); -#else -#error "Need to implement for your platform." -#endif + PlatformCanvas::AutoLocker locker(&m_canvas); + updateFromPixels(paintRect, locker.pixels()); +} +void LayerTilerChromium::updateFromPixels(const IntRect& paintRect, const uint8_t* paintPixels) +{ // Painting could cause compositing to get turned off, which may cause the tiler to become invalidated mid-update. if (!m_tiles.size()) return; + GraphicsContext3D* context = layerRendererContext(); + + int left, top, right, bottom; + contentRectToTileIndices(paintRect, left, top, right, bottom); for (int j = top; j <= bottom; ++j) { for (int i = left; i <= right; ++i) { Tile* tile = m_tiles[tileIndex(i, j)].get(); @@ -346,7 +322,7 @@ void LayerTilerChromium::update(TilePaintInterface& painter, const IntRect& cont if (paintOffset.y() + destRect.height() > paintRect.height()) CRASH(); - uint8_t* pixelSource; + const uint8_t* pixelSource; if (paintRect.width() == sourceRect.width() && !paintOffset.x()) pixelSource = &paintPixels[4 * paintOffset.y() * paintRect.width()]; else { @@ -361,6 +337,9 @@ void LayerTilerChromium::update(TilePaintInterface& painter, const IntRect& cont } tile->texture()->bindTexture(); + GLC(context, context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_MIN_FILTER, GraphicsContext3D::NEAREST)); + GLC(context, context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_MAG_FILTER, GraphicsContext3D::NEAREST)); + GLC(context, context->texSubImage2D(GraphicsContext3D::TEXTURE_2D, 0, destRect.x(), destRect.y(), destRect.width(), destRect.height(), GraphicsContext3D::RGBA, GraphicsContext3D::UNSIGNED_BYTE, pixelSource)); tile->clearDirty(); @@ -378,26 +357,38 @@ void LayerTilerChromium::draw(const IntRect& contentRect) if (m_skipsDraw || !m_tiles.size()) return; - // We reuse the shader program used by ContentLayerChromium. GraphicsContext3D* context = layerRendererContext(); - const ContentLayerChromium::SharedValues* contentLayerValues = layerRenderer()->contentLayerSharedValues(); - layerRenderer()->useShader(contentLayerValues->contentShaderProgram()); - GLC(context, context->uniform1i(contentLayerValues->shaderSamplerLocation(), 0)); + const LayerTilerChromium::Program* program = layerRenderer()->tilerProgram(); + layerRenderer()->useShader(program->program()); + GLC(context, context->uniform1i(program->fragmentShader().samplerLocation(), 0)); int left, top, right, bottom; contentRectToTileIndices(contentRect, left, top, right, bottom); for (int j = top; j <= bottom; ++j) { for (int i = left; i <= right; ++i) { - Tile* tile = m_tiles[tileIndex(i, j)].get(); + const int index = tileIndex(i, j); + Tile* tile = m_tiles[index].get(); ASSERT(tile); tile->texture()->bindTexture(); TransformationMatrix tileMatrix; - IntRect tileRect = tileContentRect(i, j); + + // Don't use tileContentRect here, as that contains the full + // rect with border texels which shouldn't be drawn. + IntRect tileRect = m_tilingData.tileBounds(index); + tileRect.move(m_layerPosition.x(), m_layerPosition.y()); tileMatrix.translate3d(tileRect.x() - contentRect.x() + tileRect.width() / 2.0, tileRect.y() - contentRect.y() + tileRect.height() / 2.0, 0); - LayerChromium::drawTexturedQuad(context, layerRenderer()->projectionMatrix(), tileMatrix, m_tileSize.width(), m_tileSize.height(), 1, contentLayerValues->shaderMatrixLocation(), contentLayerValues->shaderAlphaLocation()); + IntPoint texOffset = m_tilingData.textureOffset(i, j); + float tileWidth = static_cast<float>(m_tileSize.width()); + float tileHeight = static_cast<float>(m_tileSize.height()); + float texTranslateX = texOffset.x() / tileWidth; + float texTranslateY = texOffset.y() / tileHeight; + float texScaleX = tileRect.width() / tileWidth; + float texScaleY = tileRect.height() / tileHeight; + + drawTexturedQuad(context, layerRenderer()->projectionMatrix(), tileMatrix, tileRect.width(), tileRect.height(), 1, texTranslateX, texTranslateY, texScaleX, texScaleY, program); tile->texture()->unreserve(); } @@ -406,36 +397,63 @@ void LayerTilerChromium::draw(const IntRect& contentRect) void LayerTilerChromium::resizeLayer(const IntSize& size) { - if (m_layerSize == size) + if (layerSize() == size) return; - int width = (size.width() + m_tileSize.width() - 1) / m_tileSize.width(); - int height = (size.height() + m_tileSize.height() - 1) / m_tileSize.height(); + const IntSize oldTileSize = layerTileSize(); + m_tilingData.setTotalSize(size.width(), size.height()); + const IntSize newTileSize = layerTileSize(); + + if (oldTileSize == newTileSize) + return; - if (height && (width > INT_MAX / height)) + if (newTileSize.height() && (newTileSize.width() > INT_MAX / newTileSize.height())) CRASH(); Vector<OwnPtr<Tile> > newTiles; - newTiles.resize(width * height); - for (int j = 0; j < m_layerTileSize.height(); ++j) - for (int i = 0; i < m_layerTileSize.width(); ++i) - newTiles[i + j * width].swap(m_tiles[i + j * m_layerTileSize.width()]); - + newTiles.resize(newTileSize.width() * newTileSize.height()); + for (int j = 0; j < oldTileSize.height(); ++j) + for (int i = 0; i < oldTileSize.width(); ++i) + newTiles[i + j * newTileSize.width()].swap(m_tiles[i + j * oldTileSize.width()]); m_tiles.swap(newTiles); - m_layerSize = size; - m_layerTileSize = IntSize(width, height); } void LayerTilerChromium::growLayerToContain(const IntRect& contentRect) { // Grow the tile array to contain this content rect. IntRect layerRect = contentRectToLayerRect(contentRect); - IntSize layerSize = IntSize(layerRect.maxX(), layerRect.maxY()); + IntSize rectSize = IntSize(layerRect.maxX(), layerRect.maxY()); - IntSize newSize = layerSize.expandedTo(m_layerSize); + IntSize newSize = rectSize.expandedTo(layerSize()); resizeLayer(newSize); } +void LayerTilerChromium::drawTexturedQuad(GraphicsContext3D* context, const TransformationMatrix& projectionMatrix, const TransformationMatrix& drawMatrix, + float width, float height, float opacity, + float texTranslateX, float texTranslateY, + float texScaleX, float texScaleY, + const LayerTilerChromium::Program* program) +{ + static float glMatrix[16]; + + TransformationMatrix renderMatrix = drawMatrix; + + // Apply a scaling factor to size the quad from 1x1 to its intended size. + renderMatrix.scale3d(width, height, 1); + + // Apply the projection matrix before sending the transform over to the shader. + LayerChromium::toGLMatrix(&glMatrix[0], projectionMatrix * renderMatrix); + + GLC(context, context->uniformMatrix4fv(program->vertexShader().matrixLocation(), false, &glMatrix[0], 1)); + + GLC(context, context->uniform1f(program->fragmentShader().alphaLocation(), opacity)); + + GLC(context, context->uniform4f(program->vertexShader().texTransformLocation(), + texTranslateX, texTranslateY, texScaleX, texScaleY)); + + GLC(context, context->drawElements(GraphicsContext3D::TRIANGLES, 6, GraphicsContext3D::UNSIGNED_SHORT, 0)); +} + } // namespace WebCore #endif // USE(ACCELERATED_COMPOSITING) diff --git a/Source/WebCore/platform/graphics/chromium/LayerTilerChromium.h b/Source/WebCore/platform/graphics/chromium/LayerTilerChromium.h index e09693d..bdb35a5 100644 --- a/Source/WebCore/platform/graphics/chromium/LayerTilerChromium.h +++ b/Source/WebCore/platform/graphics/chromium/LayerTilerChromium.h @@ -31,6 +31,8 @@ #include "LayerChromium.h" #include "LayerTexture.h" +#include "PlatformCanvas.h" +#include "TilingData.h" #include <wtf/OwnArrayPtr.h> namespace WebCore { @@ -46,13 +48,16 @@ public: class LayerTilerChromium { WTF_MAKE_NONCOPYABLE(LayerTilerChromium); public: - static PassOwnPtr<LayerTilerChromium> create(LayerRendererChromium* layerRenderer, const IntSize& tileSize); + enum BorderTexelOption { HasBorderTexels, NoBorderTexels }; + + static PassOwnPtr<LayerTilerChromium> create(LayerRendererChromium*, const IntSize& tileSize, BorderTexelOption); ~LayerTilerChromium(); void invalidateRect(const IntRect& contentRect); void invalidateEntireLayer(); void update(TilePaintInterface& painter, const IntRect& contentRect); + void updateFromPixels(const IntRect& paintRect, const uint8_t* pixels); void draw(const IntRect& contentRect); // Set position of this tiled layer in content space. @@ -60,8 +65,10 @@ public: // Change the tile size. This may invalidate all the existing tiles. void setTileSize(const IntSize& size); + typedef ProgramBinding<VertexShaderPosTexTransform, FragmentShaderTexAlpha> Program; + private: - LayerTilerChromium(LayerRendererChromium* layerRenderer, const IntSize& tileSize); + LayerTilerChromium(LayerRendererChromium*, const IntSize& tileSize, BorderTexelOption); class Tile { WTF_MAKE_NONCOPYABLE(Tile); @@ -79,6 +86,12 @@ private: OwnPtr<LayerTexture> m_tex; }; + void drawTexturedQuad(GraphicsContext3D*, const TransformationMatrix& projectionMatrix, const TransformationMatrix& drawMatrix, + float width, float height, float opacity, + float texTranslateX, float texTranslateY, + float texScaleX, float texScaleY, + const LayerTilerChromium::Program*); + void resizeLayer(const IntSize& size); // Grow layer size to contain this rectangle. void growLayerToContain(const IntRect& contentRect); @@ -100,9 +113,10 @@ private: // Returns the bounds in layer space for a given tile location. IntRect tileLayerRect(int i, int j) const; + IntSize layerSize() const; + IntSize layerTileSize() const; + IntSize m_tileSize; - IntSize m_layerSize; - IntSize m_layerTileSize; IntRect m_lastUpdateLayerRect; IntPoint m_layerPosition; @@ -113,9 +127,13 @@ private: // Linear array of unused tiles. Vector<OwnPtr<Tile> > m_unusedTiles; + PlatformCanvas m_canvas; + // Cache a tile-sized pixel buffer to draw into. OwnArrayPtr<uint8_t> m_tilePixels; + TilingData m_tilingData; + LayerRendererChromium* m_layerRenderer; }; diff --git a/Source/WebCore/platform/graphics/chromium/PlatformCanvas.cpp b/Source/WebCore/platform/graphics/chromium/PlatformCanvas.cpp new file mode 100644 index 0000000..29589f4 --- /dev/null +++ b/Source/WebCore/platform/graphics/chromium/PlatformCanvas.cpp @@ -0,0 +1,116 @@ +/* + * Copyright (C) 2011 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" + +#include "PlatformCanvas.h" + +#include "GraphicsContext.h" + +#if USE(SKIA) +#include "NativeImageSkia.h" +#include "PlatformContextSkia.h" +#include "SkColorPriv.h" +#include "skia/ext/platform_canvas.h" +#elif PLATFORM(CG) +#include <CoreGraphics/CGBitmapContext.h> +#endif + +namespace WebCore { + +PlatformCanvas::PlatformCanvas() +{ +} + +PlatformCanvas::~PlatformCanvas() +{ +} + +void PlatformCanvas::resize(const IntSize& size) +{ + m_size = size; +#if USE(SKIA) + m_skiaCanvas = new skia::PlatformCanvas(size.width(), size.height(), false); +#elif PLATFORM(CG) + size_t bufferSize = size.width() * size.height() * 4; + m_pixelData = adoptArrayPtr(new uint8_t[bufferSize]); + memset(m_pixelData.get(), 0, bufferSize); +#endif +} + +PlatformCanvas::AutoLocker::AutoLocker(PlatformCanvas* canvas) + : m_canvas(canvas) + , m_pixels(0) +{ +#if USE(SKIA) + if (m_canvas->m_skiaCanvas) { + m_bitmap = &m_canvas->m_skiaCanvas->getDevice()->accessBitmap(false); + m_bitmap->lockPixels(); + + if (m_bitmap->config() == SkBitmap::kARGB_8888_Config) + m_pixels = static_cast<uint8_t*>(m_bitmap->getPixels()); + } else + m_bitmap = 0; +#elif PLATFORM(CG) + m_pixels = &canvas->m_pixelData[0]; +#endif +} + +PlatformCanvas::AutoLocker::~AutoLocker() +{ +#if USE(SKIA) + if (m_bitmap) + m_bitmap->unlockPixels(); +#endif +} + +PlatformCanvas::Painter::Painter(PlatformCanvas* canvas) +{ +#if USE(SKIA) + m_skiaContext = adoptPtr(new PlatformContextSkia(canvas->m_skiaCanvas.get())); + + // This is needed to get text to show up correctly. + m_skiaContext->setDrawingToImageBuffer(true); + + m_context = adoptPtr(new GraphicsContext(reinterpret_cast<PlatformGraphicsContext*>(m_skiaContext.get()))); +#elif PLATFORM(CG) + + m_colorSpace = CGColorSpaceCreateDeviceRGB(); + size_t rowBytes = canvas->size().width() * 4; + m_contextCG = CGBitmapContextCreate(canvas->m_pixelData.get(), + canvas->size().width(), canvas->size().height(), 8, rowBytes, + m_colorSpace.get(), + kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Host); + CGContextTranslateCTM(m_contextCG.get(), 0, canvas->size().height()); + CGContextScaleCTM(m_contextCG.get(), 1, -1); + m_context = adoptPtr(new GraphicsContext(m_contextCG.get())); +#endif +} + +PlatformCanvas::Painter::~Painter() +{ +} + +} // namespace WebCore diff --git a/Source/WebCore/platform/graphics/chromium/PlatformCanvas.h b/Source/WebCore/platform/graphics/chromium/PlatformCanvas.h new file mode 100644 index 0000000..262fdd0 --- /dev/null +++ b/Source/WebCore/platform/graphics/chromium/PlatformCanvas.h @@ -0,0 +1,109 @@ +/* + * Copyright (C) 2011 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef PlatformCanvas_h +#define PlatformCanvas_h + +#include "IntSize.h" +#include <stdint.h> +#include <wtf/Noncopyable.h> +#include <wtf/OwnPtr.h> + +#if PLATFORM(CG) +#include <CoreGraphics/CGColorSpace.h> +#include <CoreGraphics/CGContext.h> +#include <wtf/OwnArrayPtr.h> +#include <wtf/RetainPtr.h> +#endif + +#if USE(SKIA) +namespace skia { class PlatformCanvas; } +class SkBitmap; +#endif + +namespace WebCore { + +class GraphicsContext; + +#if USE(SKIA) +class PlatformContextSkia; +#endif + +// A 2D buffer of pixels with an associated GraphicsContext. +class PlatformCanvas { + WTF_MAKE_NONCOPYABLE(PlatformCanvas); +public: + PlatformCanvas(); + ~PlatformCanvas(); + + // Scoped lock class to get temporary access to this canvas's pixels. + class AutoLocker { + WTF_MAKE_NONCOPYABLE(AutoLocker); + public: + explicit AutoLocker(PlatformCanvas*); + ~AutoLocker(); + + const uint8_t* pixels() const { return m_pixels; } + private: + PlatformCanvas* m_canvas; +#if USE(SKIA) + const SkBitmap* m_bitmap; +#endif + uint8_t* m_pixels; + }; + + // Scoped lock class to get temporary access to paint into this canvas. + class Painter { + WTF_MAKE_NONCOPYABLE(Painter); + public: + explicit Painter(PlatformCanvas*); + ~Painter(); + + GraphicsContext* context() const { return m_context.get(); } + private: + OwnPtr<GraphicsContext> m_context; +#if USE(SKIA) + OwnPtr<PlatformContextSkia> m_skiaContext; +#elif PLATFORM(CG) + RetainPtr<CGColorSpaceRef> m_colorSpace; + RetainPtr<CGContextRef> m_contextCG; +#endif + }; + + void resize(const IntSize&); + IntSize size() const { return m_size; } + +private: +#if USE(SKIA) + OwnPtr<skia::PlatformCanvas> m_skiaCanvas; +#elif PLATFORM(CG) + OwnArrayPtr<uint8_t> m_pixelData; +#endif + IntSize m_size; +}; + +} // namespace WebCore + +#endif diff --git a/Source/WebCore/platform/graphics/chromium/PlatformImage.cpp b/Source/WebCore/platform/graphics/chromium/PlatformImage.cpp new file mode 100644 index 0000000..62cf4f8 --- /dev/null +++ b/Source/WebCore/platform/graphics/chromium/PlatformImage.cpp @@ -0,0 +1,111 @@ +/* + * Copyright (C) 2011 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" + +#include "PlatformImage.h" + +#if USE(SKIA) +#include "NativeImageSkia.h" +#include "PlatformContextSkia.h" +#elif PLATFORM(CG) +#include <CoreGraphics/CGBitmapContext.h> +#include <CoreGraphics/CGContext.h> +#include <CoreGraphics/CGImage.h> +#include <wtf/RetainPtr.h> +#else +#error "Need to implement for your platform" +#endif + +namespace WebCore { + +PlatformImage::PlatformImage() +{ +} + +void PlatformImage::updateFromImage(NativeImagePtr nativeImage) +{ +#if USE(SKIA) + // The layer contains an Image. + NativeImageSkia* skiaImage = static_cast<NativeImageSkia*>(nativeImage); + const SkBitmap* skiaBitmap = skiaImage; + + IntSize bitmapSize(skiaBitmap->width(), skiaBitmap->height()); + ASSERT(skiaBitmap); +#elif PLATFORM(CG) + // NativeImagePtr is a CGImageRef on Mac OS X. + int width = CGImageGetWidth(nativeImage); + int height = CGImageGetHeight(nativeImage); + IntSize bitmapSize(width, height); +#endif + + size_t bufferSize = bitmapSize.width() * bitmapSize.height() * 4; + if (m_size != bitmapSize) { + m_pixelData = adoptArrayPtr(new uint8_t[bufferSize]); + memset(m_pixelData.get(), 0, bufferSize); + m_size = bitmapSize; + } + +#if USE(SKIA) + SkAutoLockPixels lock(*skiaBitmap); + // FIXME: do we need to support more image configurations? + ASSERT(skiaBitmap->config()== SkBitmap::kARGB_8888_Config); + skiaBitmap->copyPixelsTo(m_pixelData.get(), bufferSize); +#elif PLATFORM(CG) + // FIXME: we should get rid of this temporary copy where possible. + int tempRowBytes = width * 4; + // Note we do not zero this vector since we are going to + // completely overwrite its contents with the image below. + // Try to reuse the color space from the image to preserve its colors. + // Some images use a color space (such as indexed) unsupported by the bitmap context. + RetainPtr<CGColorSpaceRef> colorSpaceReleaser; + CGColorSpaceRef colorSpace = CGImageGetColorSpace(nativeImage); + CGColorSpaceModel colorSpaceModel = CGColorSpaceGetModel(colorSpace); + switch (colorSpaceModel) { + case kCGColorSpaceModelMonochrome: + case kCGColorSpaceModelRGB: + case kCGColorSpaceModelCMYK: + case kCGColorSpaceModelLab: + case kCGColorSpaceModelDeviceN: + break; + default: + colorSpaceReleaser.adoptCF(CGColorSpaceCreateDeviceRGB()); + colorSpace = colorSpaceReleaser.get(); + break; + } + RetainPtr<CGContextRef> tempContext(AdoptCF, CGBitmapContextCreate(m_pixelData.get(), + width, height, 8, tempRowBytes, + colorSpace, + kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Host)); + CGContextSetBlendMode(tempContext.get(), kCGBlendModeCopy); + CGContextDrawImage(tempContext.get(), + CGRectMake(0, 0, static_cast<CGFloat>(width), static_cast<CGFloat>(height)), + nativeImage); +#else +#error "Need to implement for your platform." +#endif +} + +} // namespace WebCore diff --git a/Source/WebCore/platform/graphics/chromium/PlatformImage.h b/Source/WebCore/platform/graphics/chromium/PlatformImage.h new file mode 100644 index 0000000..12f77b6 --- /dev/null +++ b/Source/WebCore/platform/graphics/chromium/PlatformImage.h @@ -0,0 +1,53 @@ +/* + * Copyright (C) 2011 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef PlatformImage_h +#define PlatformImage_h + +#include "ImageSource.h" +#include "IntSize.h" +#include <stdint.h> +#include <wtf/Noncopyable.h> +#include <wtf/OwnArrayPtr.h> + +namespace WebCore { + +class PlatformImage { + WTF_MAKE_NONCOPYABLE(PlatformImage); +public: + PlatformImage(); + + void updateFromImage(NativeImagePtr); + const uint8_t* pixels() const { return m_pixelData ? &m_pixelData[0] : 0; } + IntSize size() const { return m_size; } + +private: + OwnArrayPtr<uint8_t> m_pixelData; + IntSize m_size; +}; + +} // namespace WebCore + +#endif diff --git a/Source/WebCore/platform/graphics/chromium/PluginLayerChromium.cpp b/Source/WebCore/platform/graphics/chromium/PluginLayerChromium.cpp index 878c142..5d595ad 100644 --- a/Source/WebCore/platform/graphics/chromium/PluginLayerChromium.cpp +++ b/Source/WebCore/platform/graphics/chromium/PluginLayerChromium.cpp @@ -29,64 +29,13 @@ #include "PluginLayerChromium.h" +#include "cc/CCLayerImpl.h" #include "GraphicsContext3D.h" #include "LayerRendererChromium.h" #include <GLES2/gl2.h> namespace WebCore { -PluginLayerChromium::SharedValues::SharedValues(GraphicsContext3D* context) - : m_context(context) - , m_shaderProgram(0) - , m_shaderSamplerLocation(-1) - , m_shaderMatrixLocation(-1) - , m_shaderAlphaLocation(-1) - , m_initialized(false) -{ - char vertexShaderString[] = - "attribute vec4 a_position; \n" - "attribute vec2 a_texCoord; \n" - "uniform mat4 matrix; \n" - "varying vec2 v_texCoord; \n" - "void main() \n" - "{ \n" - " gl_Position = matrix * a_position; \n" - " v_texCoord = a_texCoord; \n" - "} \n"; - - char fragmentShaderString[] = - "precision mediump float; \n" - "varying vec2 v_texCoord; \n" - "uniform sampler2D s_texture; \n" - "uniform float alpha; \n" - "void main() \n" - "{ \n" - " vec4 texColor = texture2D(s_texture, vec2(v_texCoord.x, v_texCoord.y)); \n" - " gl_FragColor = vec4(texColor.x, texColor.y, texColor.z, texColor.w) * alpha; \n" - "} \n"; - - m_shaderProgram = createShaderProgram(m_context, vertexShaderString, fragmentShaderString); - if (!m_shaderProgram) { - LOG_ERROR("PluginLayerChromium: Failed to create shader program"); - return; - } - - m_shaderSamplerLocation = m_context->getUniformLocation(m_shaderProgram, "s_texture"); - m_shaderMatrixLocation = m_context->getUniformLocation(m_shaderProgram, "matrix"); - m_shaderAlphaLocation = m_context->getUniformLocation(m_shaderProgram, "alpha"); - ASSERT(m_shaderSamplerLocation != -1); - ASSERT(m_shaderMatrixLocation != -1); - ASSERT(m_shaderAlphaLocation != -1); - - m_initialized = true; -} - -PluginLayerChromium::SharedValues::~SharedValues() -{ - if (m_shaderProgram) - GLC(m_context, m_context->deleteProgram(m_shaderProgram)); -} - PassRefPtr<PluginLayerChromium> PluginLayerChromium::create(GraphicsLayerChromium* owner) { return adoptRef(new PluginLayerChromium(owner)); @@ -109,8 +58,8 @@ void PluginLayerChromium::updateContentsIfDirty() void PluginLayerChromium::draw() { ASSERT(layerRenderer()); - const PluginLayerChromium::SharedValues* sv = layerRenderer()->pluginLayerSharedValues(); - ASSERT(sv && sv->initialized()); + const PluginLayerChromium::Program* program = layerRenderer()->pluginLayerProgram(); + ASSERT(program && program->initialized()); GraphicsContext3D* context = layerRendererContext(); GLC(context, context->activeTexture(GL_TEXTURE0)); GLC(context, context->bindTexture(GL_TEXTURE_2D, m_textureId)); @@ -122,11 +71,12 @@ void PluginLayerChromium::draw() GLC(context, context->texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE)); GLC(context, context->texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE)); - layerRenderer()->useShader(sv->shaderProgram()); - GLC(context, context->uniform1i(sv->shaderSamplerLocation(), 0)); - drawTexturedQuad(context, layerRenderer()->projectionMatrix(), drawTransform(), - bounds().width(), bounds().height(), drawOpacity(), - sv->shaderMatrixLocation(), sv->shaderAlphaLocation()); + layerRenderer()->useShader(program->program()); + 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()); } } diff --git a/Source/WebCore/platform/graphics/chromium/PluginLayerChromium.h b/Source/WebCore/platform/graphics/chromium/PluginLayerChromium.h index 853b328..8d66f5f 100644 --- a/Source/WebCore/platform/graphics/chromium/PluginLayerChromium.h +++ b/Source/WebCore/platform/graphics/chromium/PluginLayerChromium.h @@ -37,31 +37,16 @@ namespace WebCore { class PluginLayerChromium : public LayerChromium { public: static PassRefPtr<PluginLayerChromium> create(GraphicsLayerChromium* owner = 0); - virtual bool drawsContent() { return true; } + virtual bool drawsContent() const { return true; } virtual void updateContentsIfDirty(); virtual void draw(); void setTextureId(unsigned textureId); - class SharedValues { - public: - SharedValues(GraphicsContext3D* context); - ~SharedValues(); + typedef ProgramBinding<VertexShaderPosTex, FragmentShaderRGBATexFlipAlpha> Program; - unsigned shaderProgram() const { return m_shaderProgram; } - int shaderSamplerLocation() const { return m_shaderSamplerLocation; } - int shaderMatrixLocation() const { return m_shaderMatrixLocation; } - int shaderAlphaLocation() const { return m_shaderAlphaLocation; } - bool initialized() const { return m_initialized; } - - private: - GraphicsContext3D* m_context; - unsigned m_shaderProgram; - int m_shaderSamplerLocation; - int m_shaderMatrixLocation; - int m_shaderAlphaLocation; - bool m_initialized; - }; +protected: + virtual const char* layerTypeAsString() const { return "PluginLayer"; } private: PluginLayerChromium(GraphicsLayerChromium* owner); diff --git a/Source/WebCore/platform/graphics/chromium/ProgramBinding.cpp b/Source/WebCore/platform/graphics/chromium/ProgramBinding.cpp new file mode 100644 index 0000000..6be00ef --- /dev/null +++ b/Source/WebCore/platform/graphics/chromium/ProgramBinding.cpp @@ -0,0 +1,123 @@ +/* + * Copyright (C) 2011 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" + +#if USE(ACCELERATED_COMPOSITING) + +#include "ProgramBinding.h" + +#include "GeometryBinding.h" +#include "GraphicsContext.h" +#include "GraphicsContext3D.h" +#include "LayerRendererChromium.h" + +namespace WebCore { + +ProgramBindingBase::ProgramBindingBase(GraphicsContext3D* context) + : m_context(context) + , m_program(0) + , m_initialized(false) +{ +} + +ProgramBindingBase::~ProgramBindingBase() +{ + if (m_program) + GLC(m_context, m_context->deleteProgram(m_program)); +} + +bool ProgramBindingBase::init(const String& vertexShader, const String& fragmentShader) +{ + m_program = createShaderProgram(vertexShader, fragmentShader); + if (!m_program) { + LOG_ERROR("Failed to create shader program"); + return false; + } + return true; +} + +unsigned ProgramBindingBase::loadShader(unsigned type, const String& shaderSource) +{ + unsigned shader = m_context->createShader(type); + if (!shader) + return 0; + String sourceString(shaderSource); + GLC(m_context, m_context->shaderSource(shader, sourceString)); + GLC(m_context, m_context->compileShader(shader)); + int compiled = 0; + GLC(m_context, m_context->getShaderiv(shader, GraphicsContext3D::COMPILE_STATUS, &compiled)); + if (!compiled) { + GLC(m_context, m_context->deleteShader(shader)); + return 0; + } + return shader; +} + +unsigned ProgramBindingBase::createShaderProgram(const String& vertexShaderSource, const String& fragmentShaderSource) +{ + unsigned vertexShader = loadShader(GraphicsContext3D::VERTEX_SHADER, vertexShaderSource); + if (!vertexShader) { + LOG_ERROR("Failed to create vertex shader"); + return 0; + } + + unsigned fragmentShader = loadShader(GraphicsContext3D::FRAGMENT_SHADER, fragmentShaderSource); + if (!fragmentShader) { + GLC(m_context, m_context->deleteShader(vertexShader)); + LOG_ERROR("Failed to create fragment shader"); + return 0; + } + + unsigned programObject = m_context->createProgram(); + if (!programObject) { + LOG_ERROR("Failed to create shader program"); + return 0; + } + + GLC(m_context, m_context->attachShader(programObject, vertexShader)); + GLC(m_context, m_context->attachShader(programObject, fragmentShader)); + + // Bind the common attrib locations. + GLC(m_context, m_context->bindAttribLocation(programObject, GeometryBinding::positionAttribLocation(), "a_position")); + GLC(m_context, m_context->bindAttribLocation(programObject, GeometryBinding::texCoordAttribLocation(), "a_texCoord")); + + GLC(m_context, m_context->linkProgram(programObject)); + int linked = 0; + GLC(m_context, m_context->getProgramiv(programObject, GraphicsContext3D::LINK_STATUS, &linked)); + if (!linked) { + LOG_ERROR("Failed to link shader program"); + GLC(m_context, m_context->deleteProgram(programObject)); + return 0; + } + + GLC(m_context, m_context->deleteShader(vertexShader)); + GLC(m_context, m_context->deleteShader(fragmentShader)); + return programObject; +} + +} // namespace WebCore + +#endif // USE(ACCELERATED_COMPOSITING) diff --git a/Source/WebCore/platform/graphics/chromium/ProgramBinding.h b/Source/WebCore/platform/graphics/chromium/ProgramBinding.h new file mode 100644 index 0000000..c6bf605 --- /dev/null +++ b/Source/WebCore/platform/graphics/chromium/ProgramBinding.h @@ -0,0 +1,85 @@ +/* + * Copyright (C) 2011 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef ProgramBinding_h +#define ProgramBinding_h + +#if USE(ACCELERATED_COMPOSITING) + +#include "PlatformString.h" + +namespace WebCore { + +class GraphicsContext3D; + +class ProgramBindingBase { +public: + explicit ProgramBindingBase(GraphicsContext3D*); + ~ProgramBindingBase(); + + bool init(const String& vertexShader, const String& fragmentShader); + + unsigned program() const { return m_program; } + bool initialized() const { return m_initialized; } + +protected: + + unsigned loadShader(unsigned type, const String& shaderSource); + unsigned createShaderProgram(const String& vertexShaderSource, const String& fragmentShaderSource); + + GraphicsContext3D* m_context; + unsigned m_program; + bool m_initialized; +}; + +template<class VertexShader, class FragmentShader> +class ProgramBinding : public ProgramBindingBase { +public: + explicit ProgramBinding(GraphicsContext3D* context) + : ProgramBindingBase(context) + { + if (!ProgramBindingBase::init(m_vertexShader.getShaderString(), m_fragmentShader.getShaderString())) + return; + if (!m_vertexShader.init(m_context, m_program)) + return; + if (!m_fragmentShader.init(m_context, m_program)) + return; + m_initialized = true; + } + + const VertexShader& vertexShader() const { return m_vertexShader; } + const FragmentShader& fragmentShader() const { return m_fragmentShader; } + +private: + + VertexShader m_vertexShader; + FragmentShader m_fragmentShader; +}; + +} // namespace WebCore + +#endif // USE(ACCELERATED_COMPOSITING) + +#endif diff --git a/Source/WebCore/platform/graphics/chromium/RenderSurfaceChromium.cpp b/Source/WebCore/platform/graphics/chromium/RenderSurfaceChromium.cpp index b3ce9d7..ca42d0b 100644 --- a/Source/WebCore/platform/graphics/chromium/RenderSurfaceChromium.cpp +++ b/Source/WebCore/platform/graphics/chromium/RenderSurfaceChromium.cpp @@ -29,98 +29,17 @@ #include "RenderSurfaceChromium.h" +#include "cc/CCLayerImpl.h" #include "GraphicsContext3D.h" +#include "LayerChromium.h" #include "LayerRendererChromium.h" #include "LayerTexture.h" +#include "TextStream.h" +#include <wtf/text/CString.h> namespace WebCore { -RenderSurfaceChromium::SharedValues::SharedValues(GraphicsContext3D* context) - : m_context(context) - , m_shaderProgram(0) - , m_maskShaderProgram(0) - , m_shaderSamplerLocation(-1) - , m_shaderMatrixLocation(-1) - , m_shaderAlphaLocation(-1) - , m_maskShaderSamplerLocation(-1) - , m_maskShaderMaskSamplerLocation(-1) - , m_maskShaderMatrixLocation(-1) - , m_maskShaderAlphaLocation(-1) - , m_initialized(false) -{ - char vertexShaderString[] = - "attribute vec4 a_position; \n" - "attribute vec2 a_texCoord; \n" - "uniform mat4 matrix; \n" - "varying vec2 v_texCoord; \n" - "void main() \n" - "{ \n" - " gl_Position = matrix * a_position; \n" - " v_texCoord = a_texCoord; \n" - "} \n"; - char fragmentShaderString[] = - "precision mediump float; \n" - "varying vec2 v_texCoord; \n" - "uniform sampler2D s_texture; \n" - "uniform float alpha; \n" - "void main() \n" - "{ \n" - " vec4 texColor = texture2D(s_texture, v_texCoord); \n" - " gl_FragColor = vec4(texColor.x, texColor.y, texColor.z, texColor.w) * alpha; \n" - "} \n"; - char fragmentShaderWithMaskString[] = - "precision mediump float; \n" - "varying vec2 v_texCoord; \n" - "uniform sampler2D s_texture; \n" - "uniform sampler2D s_mask; \n" - "uniform float alpha; \n" - "void main() \n" - "{ \n" - " vec4 texColor = texture2D(s_texture, v_texCoord); \n" - " vec4 maskColor = texture2D(s_mask, v_texCoord); \n" - " gl_FragColor = vec4(texColor.x, texColor.y, texColor.z, texColor.w) * alpha * maskColor.w; \n" - "} \n"; - - m_shaderProgram = LayerChromium::createShaderProgram(m_context, vertexShaderString, fragmentShaderString); - m_maskShaderProgram = LayerChromium::createShaderProgram(m_context, vertexShaderString, fragmentShaderWithMaskString); - if (!m_shaderProgram || !m_maskShaderProgram) { - LOG_ERROR("RenderSurfaceChromium: Failed to create shader program"); - return; - } - - GLC(m_context, m_shaderSamplerLocation = m_context->getUniformLocation(m_shaderProgram, "s_texture")); - GLC(m_context, m_shaderMatrixLocation = m_context->getUniformLocation(m_shaderProgram, "matrix")); - GLC(m_context, m_shaderAlphaLocation = m_context->getUniformLocation(m_shaderProgram, "alpha")); - - GLC(m_context, m_maskShaderSamplerLocation = m_context->getUniformLocation(m_maskShaderProgram, "s_texture")); - GLC(m_context, m_maskShaderMaskSamplerLocation = m_context->getUniformLocation(m_maskShaderProgram, "s_mask")); - GLC(m_context, m_maskShaderMatrixLocation = m_context->getUniformLocation(m_maskShaderProgram, "matrix")); - GLC(m_context, m_maskShaderAlphaLocation = m_context->getUniformLocation(m_maskShaderProgram, "alpha")); - - if (m_shaderSamplerLocation == -1 || m_shaderMatrixLocation == -1 || m_shaderAlphaLocation == -1 - || m_maskShaderSamplerLocation == -1 || m_maskShaderMaskSamplerLocation == -1 || m_maskShaderMatrixLocation == -1 || m_maskShaderAlphaLocation == -1) { - LOG_ERROR("Failed to initialize render surface shaders."); - return; - } - - GLC(m_context, m_context->useProgram(m_shaderProgram)); - GLC(m_context, m_context->uniform1i(m_shaderSamplerLocation, 0)); - GLC(m_context, m_context->useProgram(m_maskShaderProgram)); - GLC(m_context, m_context->uniform1i(m_maskShaderSamplerLocation, 0)); - GLC(m_context, m_context->uniform1i(m_maskShaderMaskSamplerLocation, 1)); - GLC(m_context, m_context->useProgram(0)); - m_initialized = true; -} - -RenderSurfaceChromium::SharedValues::~SharedValues() -{ - if (m_shaderProgram) - GLC(m_context, m_context->deleteProgram(m_shaderProgram)); - if (m_maskShaderProgram) - GLC(m_context, m_context->deleteProgram(m_maskShaderProgram)); -} - -RenderSurfaceChromium::RenderSurfaceChromium(LayerChromium* owningLayer) +RenderSurfaceChromium::RenderSurfaceChromium(CCLayerImpl* owningLayer) : m_owningLayer(owningLayer) , m_maskLayer(0) , m_skipsDraw(false) @@ -179,36 +98,39 @@ bool RenderSurfaceChromium::prepareContentsTexture() return true; } -void RenderSurfaceChromium::drawSurface(LayerChromium* maskLayer, const TransformationMatrix& drawTransform) +void RenderSurfaceChromium::drawSurface(CCLayerImpl* maskLayer, const TransformationMatrix& drawTransform) { GraphicsContext3D* context3D = layerRenderer()->context(); int shaderMatrixLocation = -1; int shaderAlphaLocation = -1; - const RenderSurfaceChromium::SharedValues* sv = layerRenderer()->renderSurfaceSharedValues(); - ASSERT(sv && sv->initialized()); + const RenderSurfaceChromium::Program* program = layerRenderer()->renderSurfaceProgram(); + const RenderSurfaceChromium::MaskProgram* maskProgram = layerRenderer()->renderSurfaceMaskProgram(); + ASSERT(program && program->initialized()); bool useMask = false; if (maskLayer && maskLayer->drawsContent()) { - maskLayer->updateContentsIfDirty(); if (!maskLayer->bounds().isEmpty()) { context3D->makeContextCurrent(); - layerRenderer()->useShader(sv->maskShaderProgram()); + layerRenderer()->useShader(maskProgram->program()); GLC(context3D, context3D->activeTexture(GraphicsContext3D::TEXTURE0)); + GLC(context3D, context3D->uniform1i(maskProgram->fragmentShader().samplerLocation(), 0)); m_contentsTexture->bindTexture(); GLC(context3D, context3D->activeTexture(GraphicsContext3D::TEXTURE1)); + GLC(context3D, context3D->uniform1i(maskProgram->fragmentShader().maskSamplerLocation(), 1)); maskLayer->bindContentsTexture(); GLC(context3D, context3D->activeTexture(GraphicsContext3D::TEXTURE0)); - shaderMatrixLocation = sv->maskShaderMatrixLocation(); - shaderAlphaLocation = sv->maskShaderAlphaLocation(); + shaderMatrixLocation = maskProgram->vertexShader().matrixLocation(); + shaderAlphaLocation = maskProgram->fragmentShader().alphaLocation(); useMask = true; } } if (!useMask) { - layerRenderer()->useShader(sv->shaderProgram()); + layerRenderer()->useShader(program->program()); m_contentsTexture->bindTexture(); - shaderMatrixLocation = sv->shaderMatrixLocation(); - shaderAlphaLocation = sv->shaderAlphaLocation(); + GLC(context3D, context3D->uniform1i(program->fragmentShader().samplerLocation(), 0)); + shaderMatrixLocation = program->vertexShader().matrixLocation(); + shaderAlphaLocation = program->fragmentShader().alphaLocation(); } LayerChromium::drawTexturedQuad(layerRenderer()->context(), layerRenderer()->projectionMatrix(), drawTransform, @@ -231,7 +153,7 @@ void RenderSurfaceChromium::draw() // both the layer and its reflection). The solution is to introduce yet another RenderSurface // to draw the layer and its reflection in. For now we only apply a separate reflection // mask if the contents don't have a mask of their own. - LayerChromium* replicaMaskLayer = m_maskLayer; + CCLayerImpl* replicaMaskLayer = m_maskLayer; if (!m_maskLayer && m_owningLayer->replicaLayer()) replicaMaskLayer = m_owningLayer->replicaLayer()->maskLayer(); @@ -244,5 +166,29 @@ void RenderSurfaceChromium::draw() drawSurface(m_maskLayer, m_drawTransform); } +String RenderSurfaceChromium::name() const +{ +#ifndef NDEBUG + return String::format("RenderSurface(id=%i,owner=%s)", m_owningLayer->debugID(), m_owningLayer->name().utf8().data()); +#else + return String::format("RenderSurface(owner=%s)", m_owningLayer->name().utf8().data()); +#endif +} + +static void writeIndent(TextStream& ts, int indent) +{ + for (int i = 0; i != indent; ++i) + ts << " "; +} + +void RenderSurfaceChromium::dumpSurface(TextStream& ts, int indent) const +{ + writeIndent(ts, indent); + ts << name() << "\n"; + + writeIndent(ts, indent+1); + ts << "contentRect: (" << m_contentRect.x() << ", " << m_contentRect.y() << ", " << m_contentRect.width() << ", " << m_contentRect.height() << "\n"; +} + } #endif // USE(ACCELERATED_COMPOSITING) diff --git a/Source/WebCore/platform/graphics/chromium/RenderSurfaceChromium.h b/Source/WebCore/platform/graphics/chromium/RenderSurfaceChromium.h index b1f6a5c..6400c63 100644 --- a/Source/WebCore/platform/graphics/chromium/RenderSurfaceChromium.h +++ b/Source/WebCore/platform/graphics/chromium/RenderSurfaceChromium.h @@ -31,13 +31,15 @@ #include "FloatRect.h" #include "IntRect.h" +#include "ProgramBinding.h" +#include "ShaderChromium.h" #include "TextureManager.h" #include "TransformationMatrix.h" #include <wtf/Noncopyable.h> namespace WebCore { -class LayerChromium; +class CCLayerImpl; class LayerRendererChromium; class LayerTexture; @@ -45,13 +47,16 @@ class RenderSurfaceChromium { WTF_MAKE_NONCOPYABLE(RenderSurfaceChromium); friend class LayerRendererChromium; public: - explicit RenderSurfaceChromium(LayerChromium*); + explicit RenderSurfaceChromium(CCLayerImpl*); ~RenderSurfaceChromium(); bool prepareContentsTexture(); void cleanupResources(); void draw(); + String name() const; + void dumpSurface(TextStream&, int indent) const; + FloatPoint contentRectCenter() const { return FloatRect(m_contentRect).center(); } IntRect contentRect() const { return m_contentRect; } @@ -60,56 +65,26 @@ public: TransformationMatrix drawTransform() const { return m_drawTransform; } - // Stores values that are shared between instances of this class that are - // associated with the same LayerRendererChromium (and hence the same GL - // context). - class SharedValues { - public: - explicit SharedValues(GraphicsContext3D*); - ~SharedValues(); - - unsigned shaderProgram() const { return m_shaderProgram; } - unsigned maskShaderProgram() const { return m_maskShaderProgram; } - int shaderSamplerLocation() const { return m_shaderSamplerLocation; } - int shaderMatrixLocation() const { return m_shaderMatrixLocation; } - int shaderAlphaLocation() const { return m_shaderAlphaLocation; } - int maskShaderSamplerLocation() const { return m_maskShaderSamplerLocation; } - int maskShaderMaskSamplerLocation() const { return m_maskShaderMaskSamplerLocation; } - int maskShaderMatrixLocation() const { return m_maskShaderMatrixLocation; } - int maskShaderAlphaLocation() const { return m_maskShaderAlphaLocation; } - bool initialized() const { return m_initialized; } - - private: - GraphicsContext3D* m_context; - - unsigned m_shaderProgram; - unsigned m_maskShaderProgram; - int m_shaderSamplerLocation; - int m_shaderMatrixLocation; - int m_shaderAlphaLocation; - int m_maskShaderSamplerLocation; - int m_maskShaderMaskSamplerLocation; - int m_maskShaderMatrixLocation; - int m_maskShaderAlphaLocation; - bool m_initialized; - }; + typedef ProgramBinding<VertexShaderPosTex, FragmentShaderRGBATexAlpha> Program; + typedef ProgramBinding<VertexShaderPosTex, FragmentShaderRGBATexAlphaMask> MaskProgram; private: LayerRendererChromium* layerRenderer(); - void drawSurface(LayerChromium* maskLayer, const TransformationMatrix& drawTransform); + void drawSurface(CCLayerImpl* maskLayer, const TransformationMatrix& drawTransform); - LayerChromium* m_owningLayer; - LayerChromium* m_maskLayer; + CCLayerImpl* m_owningLayer; + CCLayerImpl* m_maskLayer; IntRect m_contentRect; bool m_skipsDraw; + OwnPtr<LayerTexture> m_contentsTexture; float m_drawOpacity; TransformationMatrix m_drawTransform; TransformationMatrix m_replicaDrawTransform; TransformationMatrix m_originTransform; IntRect m_scissorRect; - Vector<LayerChromium*> m_layerList; + Vector<CCLayerImpl*> m_layerList; }; } diff --git a/Source/WebCore/platform/graphics/chromium/ShaderChromium.cpp b/Source/WebCore/platform/graphics/chromium/ShaderChromium.cpp new file mode 100644 index 0000000..49b3462 --- /dev/null +++ b/Source/WebCore/platform/graphics/chromium/ShaderChromium.cpp @@ -0,0 +1,317 @@ +/* + * Copyright (C) 2011 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" + +#if USE(ACCELERATED_COMPOSITING) + +#include "ShaderChromium.h" + +#include "GraphicsContext.h" +#include "GraphicsContext3D.h" + +#define SHADER0(Src) #Src +#define SHADER(Src) SHADER0(Src) + +namespace WebCore { + +VertexShaderPosTex::VertexShaderPosTex() + : m_matrixLocation(-1) +{ +} + +bool VertexShaderPosTex::init(GraphicsContext3D* context, unsigned program) +{ + m_matrixLocation = context->getUniformLocation(program, "matrix"); + return m_matrixLocation != -1; +} + +String VertexShaderPosTex::getShaderString() const +{ + return SHADER( + attribute vec4 a_position; + attribute vec2 a_texCoord; + uniform mat4 matrix; + varying vec2 v_texCoord; + void main() + { + gl_Position = matrix * a_position; + v_texCoord = a_texCoord; + } + ); +} + +VertexShaderPosTexYUVStretch::VertexShaderPosTexYUVStretch() + : m_matrixLocation(-1) + , m_yWidthScaleFactorLocation(-1) + , m_uvWidthScaleFactorLocation(-1) +{ +} + +bool VertexShaderPosTexYUVStretch::init(GraphicsContext3D* context, unsigned program) +{ + m_matrixLocation = context->getUniformLocation(program, "matrix"); + m_yWidthScaleFactorLocation = context->getUniformLocation(program, "y_widthScaleFactor"); + m_uvWidthScaleFactorLocation = context->getUniformLocation(program, "uv_widthScaleFactor"); + return m_matrixLocation != -1 && m_yWidthScaleFactorLocation != -1 && m_uvWidthScaleFactorLocation != -1; +} + +String VertexShaderPosTexYUVStretch::getShaderString() const +{ + return SHADER( + precision mediump float; + attribute vec4 a_position; + attribute vec2 a_texCoord; + uniform mat4 matrix; + varying vec2 y_texCoord; + varying vec2 uv_texCoord; + uniform float y_widthScaleFactor; + uniform float uv_widthScaleFactor; + void main() + { + gl_Position = matrix * a_position; + y_texCoord = vec2(y_widthScaleFactor * a_texCoord.x, a_texCoord.y); + uv_texCoord = vec2(uv_widthScaleFactor * a_texCoord.x, a_texCoord.y); + } + ); +} + +VertexShaderPos::VertexShaderPos() + : m_matrixLocation(-1) +{ +} + +bool VertexShaderPos::init(GraphicsContext3D* context, unsigned program) +{ + m_matrixLocation = context->getUniformLocation(program, "matrix"); + return m_matrixLocation != -1; +} + +String VertexShaderPos::getShaderString() const +{ + return SHADER( + attribute vec4 a_position; + uniform mat4 matrix; + void main() + { + gl_Position = matrix * a_position; + } + ); +} + +VertexShaderPosTexTransform::VertexShaderPosTexTransform() + : m_matrixLocation(-1) + , m_texTransformLocation(-1) +{ +} + +bool VertexShaderPosTexTransform::init(GraphicsContext3D* context, unsigned program) +{ + m_matrixLocation = context->getUniformLocation(program, "matrix"); + m_texTransformLocation = context->getUniformLocation(program, "texTransform"); + return m_matrixLocation != -1 && m_texTransformLocation != -1; +} + +String VertexShaderPosTexTransform::getShaderString() const +{ + return SHADER( + attribute vec4 a_position; + attribute vec2 a_texCoord; + uniform mat4 matrix; + uniform vec4 texTransform; + varying vec2 v_texCoord; + void main() + { + gl_Position = matrix * a_position; + v_texCoord = a_texCoord * texTransform.zw + texTransform.xy; + } + ); +} + +FragmentTexAlphaBinding::FragmentTexAlphaBinding() + : m_samplerLocation(-1) + , m_alphaLocation(-1) +{ +} + +bool FragmentTexAlphaBinding::init(GraphicsContext3D* context, unsigned program) +{ + m_samplerLocation = context->getUniformLocation(program, "s_texture"); + m_alphaLocation = context->getUniformLocation(program, "alpha"); + + return m_samplerLocation != -1 && m_alphaLocation != -1; +} + +String FragmentShaderRGBATexFlipAlpha::getShaderString() const +{ + return SHADER( + precision mediump float; + varying vec2 v_texCoord; + uniform sampler2D s_texture; + uniform float alpha; + void main() + { + vec4 texColor = texture2D(s_texture, vec2(v_texCoord.x, 1.0 - v_texCoord.y)); + gl_FragColor = vec4(texColor.x, texColor.y, texColor.z, texColor.w) * alpha; + } + ); +} + +String FragmentShaderRGBATexAlpha::getShaderString() const +{ + return SHADER( + precision mediump float; + varying vec2 v_texCoord; + uniform sampler2D s_texture; + uniform float alpha; + void main() + { + vec4 texColor = texture2D(s_texture, v_texCoord); + gl_FragColor = texColor * alpha; + } + ); +} + +String FragmentShaderBGRATexAlpha::getShaderString() const +{ + return SHADER( + precision mediump float; + varying vec2 v_texCoord; + uniform sampler2D s_texture; + uniform float alpha; + void main() + { + vec4 texColor = texture2D(s_texture, v_texCoord); + gl_FragColor = vec4(texColor.z, texColor.y, texColor.x, texColor.w) * alpha; + } + ); +} + +FragmentShaderRGBATexAlphaMask::FragmentShaderRGBATexAlphaMask() + : m_samplerLocation(-1) + , m_maskSamplerLocation(-1) + , m_alphaLocation(-1) +{ +} + +bool FragmentShaderRGBATexAlphaMask::init(GraphicsContext3D* context, unsigned program) +{ + m_samplerLocation = context->getUniformLocation(program, "s_texture"); + m_maskSamplerLocation = context->getUniformLocation(program, "s_mask"); + m_alphaLocation = context->getUniformLocation(program, "alpha"); + + return m_samplerLocation != -1 && m_maskSamplerLocation != -1 && m_alphaLocation != -1; +} + +String FragmentShaderRGBATexAlphaMask::getShaderString() const +{ + return SHADER( + precision mediump float; + varying vec2 v_texCoord; + uniform sampler2D s_texture; + uniform sampler2D s_mask; + uniform float alpha; + void main() + { + vec4 texColor = texture2D(s_texture, v_texCoord); + vec4 maskColor = texture2D(s_mask, v_texCoord); + gl_FragColor = vec4(texColor.x, texColor.y, texColor.z, texColor.w) * alpha * maskColor.w; + } + ); +} + +FragmentShaderYUVVideo::FragmentShaderYUVVideo() + : m_yTextureLocation(-1) + , m_uTextureLocation(-1) + , m_vTextureLocation(-1) + , m_alphaLocation(-1) + , m_ccMatrixLocation(-1) + , m_signAdjLocation(-1) +{ +} + +bool FragmentShaderYUVVideo::init(GraphicsContext3D* context, unsigned program) +{ + m_yTextureLocation = context->getUniformLocation(program, "y_texture"); + m_uTextureLocation = context->getUniformLocation(program, "u_texture"); + m_vTextureLocation = context->getUniformLocation(program, "v_texture"); + m_alphaLocation = context->getUniformLocation(program, "alpha"); + m_ccMatrixLocation = context->getUniformLocation(program, "cc_matrix"); + m_signAdjLocation = context->getUniformLocation(program, "adj"); + + return m_yTextureLocation != -1 && m_uTextureLocation != -1 && m_vTextureLocation != -1 + && m_alphaLocation != -1 && m_ccMatrixLocation != -1 && m_signAdjLocation != -1; +} + +String FragmentShaderYUVVideo::getShaderString() const +{ + return SHADER( + precision mediump float; + precision mediump int; + varying vec2 y_texCoord; + varying vec2 uv_texCoord; + uniform sampler2D y_texture; + uniform sampler2D u_texture; + uniform sampler2D v_texture; + uniform float alpha; + uniform float adj; + uniform mat3 cc_matrix; + void main() + { + float y = texture2D(y_texture, y_texCoord).x; + float u = texture2D(u_texture, uv_texCoord).x - adj; + float v = texture2D(v_texture, uv_texCoord).x - adj; + vec3 rgb = cc_matrix * vec3(y, u, v); + gl_FragColor = vec4(rgb, float(1)) * alpha; + } + ); +} + +FragmentShaderColor::FragmentShaderColor() + : m_colorLocation(-1) +{ +} + +bool FragmentShaderColor::init(GraphicsContext3D* context, unsigned program) +{ + m_colorLocation = context->getUniformLocation(program, "color"); + return m_colorLocation != -1; +} + +String FragmentShaderColor::getShaderString() const +{ + return SHADER( + precision mediump float; + uniform vec4 color; + void main() + { + gl_FragColor = vec4(color.xyz * color.w, color.w); + } + ); +} + +} // namespace WebCore + +#endif // USE(ACCELERATED_COMPOSITING) diff --git a/Source/WebCore/platform/graphics/chromium/ShaderChromium.h b/Source/WebCore/platform/graphics/chromium/ShaderChromium.h new file mode 100644 index 0000000..758c62b --- /dev/null +++ b/Source/WebCore/platform/graphics/chromium/ShaderChromium.h @@ -0,0 +1,188 @@ +/* + * Copyright (C) 2011 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef ShaderChromium_h +#define ShaderChromium_h + +#if USE(ACCELERATED_COMPOSITING) + +#include "PlatformString.h" + +#if USE(SKIA) +#include "SkColorPriv.h" +#endif + +namespace WebCore { + +class GraphicsContext3D; + +class VertexShaderPosTex { +public: + VertexShaderPosTex(); + + bool init(GraphicsContext3D*, unsigned program); + String getShaderString() const; + + int matrixLocation() const { return m_matrixLocation; } + +private: + int m_matrixLocation; +}; + +class VertexShaderPosTexYUVStretch { +public: + VertexShaderPosTexYUVStretch(); + + bool init(GraphicsContext3D*, unsigned program); + String getShaderString() const; + + int matrixLocation() const { return m_matrixLocation; } + int yWidthScaleFactorLocation() const { return m_yWidthScaleFactorLocation; } + int uvWidthScaleFactorLocation() const { return m_uvWidthScaleFactorLocation; } + +private: + int m_matrixLocation; + int m_yWidthScaleFactorLocation; + int m_uvWidthScaleFactorLocation; +}; + +class VertexShaderPos { +public: + VertexShaderPos(); + + bool init(GraphicsContext3D*, unsigned program); + String getShaderString() const; + + int matrixLocation() const { return m_matrixLocation; } + +private: + int m_matrixLocation; +}; + +class VertexShaderPosTexTransform { +public: + VertexShaderPosTexTransform(); + + bool init(GraphicsContext3D*, unsigned program); + String getShaderString() const; + + int matrixLocation() const { return m_matrixLocation; } + int texTransformLocation() const { return m_texTransformLocation; } + +private: + int m_matrixLocation; + int m_texTransformLocation; +}; + +class FragmentTexAlphaBinding { +public: + FragmentTexAlphaBinding(); + + bool init(GraphicsContext3D*, unsigned program); + int alphaLocation() const { return m_alphaLocation; } + int samplerLocation() const { return m_samplerLocation; } + +private: + int m_samplerLocation; + int m_alphaLocation; +}; + +class FragmentShaderRGBATexFlipAlpha : public FragmentTexAlphaBinding { +public: + String getShaderString() const; +}; + +class FragmentShaderRGBATexAlpha : public FragmentTexAlphaBinding { +public: + String getShaderString() const; +}; + +class FragmentShaderBGRATexAlpha : public FragmentTexAlphaBinding { +public: + String getShaderString() const; +}; + +class FragmentShaderRGBATexAlphaMask { +public: + FragmentShaderRGBATexAlphaMask(); + String getShaderString() const; + + bool init(GraphicsContext3D*, unsigned program); + int alphaLocation() const { return m_alphaLocation; } + int samplerLocation() const { return m_samplerLocation; } + int maskSamplerLocation() const { return m_maskSamplerLocation; } + +private: + int m_samplerLocation; + int m_maskSamplerLocation; + int m_alphaLocation; +}; + +#if USE(SKIA) && SK_B32_SHIFT +typedef FragmentShaderRGBATexAlpha FragmentShaderTexAlpha; +#else +typedef FragmentShaderBGRATexAlpha FragmentShaderTexAlpha; +#endif + +class FragmentShaderYUVVideo { +public: + FragmentShaderYUVVideo(); + String getShaderString() const; + + bool init(GraphicsContext3D*, unsigned program); + + int yTextureLocation() const { return m_yTextureLocation; } + int uTextureLocation() const { return m_uTextureLocation; } + int vTextureLocation() const { return m_vTextureLocation; } + int alphaLocation() const { return m_alphaLocation; } + int ccMatrixLocation() const { return m_ccMatrixLocation; } + int signAdjLocation() const { return m_signAdjLocation; } + +private: + int m_yTextureLocation; + int m_uTextureLocation; + int m_vTextureLocation; + int m_alphaLocation; + int m_ccMatrixLocation; + int m_signAdjLocation; +}; + +class FragmentShaderColor { +public: + FragmentShaderColor(); + String getShaderString() const; + + bool init(GraphicsContext3D*, unsigned program); + int colorLocation() const { return m_colorLocation; } + +private: + int m_colorLocation; +}; + +} // namespace WebCore + +#endif // USE(ACCELERATED_COMPOSITING) + +#endif diff --git a/Source/WebCore/platform/graphics/chromium/TextureManager.cpp b/Source/WebCore/platform/graphics/chromium/TextureManager.cpp index c4ad958..13cdb89 100644 --- a/Source/WebCore/platform/graphics/chromium/TextureManager.cpp +++ b/Source/WebCore/platform/graphics/chromium/TextureManager.cpp @@ -152,7 +152,7 @@ unsigned TextureManager::requestTexture(TextureToken token, IntSize size, unsign if (memoryRequiredBytes > m_memoryLimitBytes || !reduceMemoryToLimit(m_memoryLimitBytes - memoryRequiredBytes)) return 0; - unsigned textureId = m_context->createTexture(); + unsigned textureId; GLC(m_context.get(), textureId = m_context->createTexture()); GLC(m_context.get(), m_context->bindTexture(GraphicsContext3D::TEXTURE_2D, textureId)); // Do basic linear filtering on resize. diff --git a/Source/WebCore/platform/graphics/chromium/VideoFrameChromium.h b/Source/WebCore/platform/graphics/chromium/VideoFrameChromium.h index e176b0c..ab669d1 100644 --- a/Source/WebCore/platform/graphics/chromium/VideoFrameChromium.h +++ b/Source/WebCore/platform/graphics/chromium/VideoFrameChromium.h @@ -69,12 +69,15 @@ public: virtual SurfaceType surfaceType() const = 0; virtual Format format() const = 0; virtual unsigned width() const = 0; + virtual unsigned width(unsigned plane) const = 0; virtual unsigned height() const = 0; + virtual unsigned height(unsigned plane) const = 0; virtual unsigned planes() const = 0; virtual int stride(unsigned plane) const = 0; virtual const void* data(unsigned plane) const = 0; virtual unsigned texture(unsigned plane) const = 0; virtual const IntSize requiredTextureSize(unsigned plane) const = 0; + virtual bool hasPaddingBytes(unsigned plane) const = 0; }; } // namespace WebCore diff --git a/Source/WebCore/platform/graphics/chromium/VideoLayerChromium.cpp b/Source/WebCore/platform/graphics/chromium/VideoLayerChromium.cpp index 41cd180..5d7a6e7 100644 --- a/Source/WebCore/platform/graphics/chromium/VideoLayerChromium.cpp +++ b/Source/WebCore/platform/graphics/chromium/VideoLayerChromium.cpp @@ -33,6 +33,7 @@ #if USE(ACCELERATED_COMPOSITING) #include "VideoLayerChromium.h" +#include "cc/CCLayerImpl.h" #include "Extensions3DChromium.h" #include "GraphicsContext3D.h" #include "LayerRendererChromium.h" @@ -51,125 +52,6 @@ const float VideoLayerChromium::yuv2RGB[9] = { 1.403f, -.714f, 0.f, }; -VideoLayerChromium::SharedValues::SharedValues(GraphicsContext3D* context) - : m_context(context) - , m_yuvShaderProgram(0) - , m_rgbaShaderProgram(0) - , m_yuvShaderMatrixLocation(0) - , m_yuvWidthScaleFactorLocation(0) - , m_rgbaShaderMatrixLocation(0) - , m_rgbaWidthScaleFactorLocation(0) - , m_ccMatrixLocation(0) - , m_signAdjLocation(0) - , m_yTextureLocation(0) - , m_uTextureLocation(0) - , m_vTextureLocation(0) - , m_rgbaTextureLocation(0) - , m_yuvAlphaLocation(0) - , m_rgbaAlphaLocation(0) - , m_initialized(false) -{ - // Frame textures are allocated based on stride width, not visible frame - // width, such that there is a guarantee that the frame rows line up - // properly and are not shifted by (stride - width) pixels. To hide the - // "padding" pixels between the edge of the visible frame width and the end - // of the stride, we give the shader a widthScaleFactor (<=1.0) of how much - // of the width of the texture should be shown when drawing the texture onto - // the vertices. - char vertexShaderString[] = - "precision mediump float; \n" - "attribute vec4 a_position; \n" - "attribute vec2 a_texCoord; \n" - "uniform mat4 matrix; \n" - "varying vec2 v_texCoord; \n" - "uniform float widthScaleFactor; \n" - "void main() \n" - "{ \n" - " gl_Position = matrix * a_position; \n" - " v_texCoord = vec2(widthScaleFactor * a_texCoord.x, a_texCoord.y); \n" - "} \n"; - - char yuvFragmentShaderString[] = - "precision mediump float; \n" - "precision mediump int; \n" - "varying vec2 v_texCoord; \n" - "uniform sampler2D y_texture; \n" - "uniform sampler2D u_texture; \n" - "uniform sampler2D v_texture; \n" - "uniform float alpha; \n" - "uniform float adj; \n" - "uniform mat3 cc_matrix; \n" - "void main() \n" - "{ \n" - " float y = texture2D(y_texture, v_texCoord).x; \n" - " float u = texture2D(u_texture, v_texCoord).x - adj; \n" - " float v = texture2D(v_texture, v_texCoord).x - adj; \n" - " vec3 rgb = cc_matrix * vec3(y, u, v); \n" - " gl_FragColor = vec4(rgb, float(1)) * alpha; \n" - "} \n"; - - char rgbaFragmentShaderString[] = - "precision mediump float; \n" - "varying vec2 v_texCoord; \n" - "uniform sampler2D rgba_texture; \n" - "uniform float alpha; \n" - "void main() \n" - "{ \n" - " vec4 texColor = texture2D(rgba_texture, vec2(v_texCoord.x, float(1) - v_texCoord.y)); \n" - " gl_FragColor = vec4(texColor.x, texColor.y, texColor.z, texColor.w) * alpha; \n" - "} \n"; - - m_rgbaShaderProgram = createShaderProgram(m_context, vertexShaderString, rgbaFragmentShaderString); - if (!m_rgbaShaderProgram) { - LOG_ERROR("VideoLayerChromium: Failed to create rgba shader program"); - return; - } - - m_yuvShaderProgram = createShaderProgram(m_context, vertexShaderString, yuvFragmentShaderString); - if (!m_yuvShaderProgram) { - LOG_ERROR("VideoLayerChromium: Failed to create yuv shader program"); - return; - } - - m_yuvShaderMatrixLocation = m_context->getUniformLocation(m_yuvShaderProgram, "matrix"); - m_yuvWidthScaleFactorLocation = m_context->getUniformLocation(m_yuvShaderProgram, "widthScaleFactor"); - m_yTextureLocation = m_context->getUniformLocation(m_yuvShaderProgram, "y_texture"); - m_uTextureLocation = m_context->getUniformLocation(m_yuvShaderProgram, "u_texture"); - m_vTextureLocation = m_context->getUniformLocation(m_yuvShaderProgram, "v_texture"); - m_ccMatrixLocation = m_context->getUniformLocation(m_yuvShaderProgram, "cc_matrix"); - m_signAdjLocation = m_context->getUniformLocation(m_yuvShaderProgram, "adj"); - m_yuvAlphaLocation = m_context->getUniformLocation(m_yuvShaderProgram, "alpha"); - - ASSERT(m_yuvShaderMatrixLocation != -1); - ASSERT(m_yuvWidthScaleFactorLocation != -1); - ASSERT(m_yTextureLocation != -1); - ASSERT(m_uTextureLocation != -1); - ASSERT(m_vTextureLocation != -1); - ASSERT(m_ccMatrixLocation != -1); - ASSERT(m_signAdjLocation != -1); - ASSERT(m_yuvAlphaLocation != -1); - - m_rgbaShaderMatrixLocation = m_context->getUniformLocation(m_rgbaShaderProgram, "matrix"); - m_rgbaTextureLocation = m_context->getUniformLocation(m_rgbaShaderProgram, "rgba_texture"); - m_rgbaWidthScaleFactorLocation = m_context->getUniformLocation(m_rgbaShaderProgram, "widthScaleFactor"); - m_rgbaAlphaLocation = m_context->getUniformLocation(m_rgbaShaderProgram, "alpha"); - - ASSERT(m_rgbaShaderMatrixLocation != -1); - ASSERT(m_rgbaTextureLocation != -1); - ASSERT(m_rgbaWidthScaleFactorLocation != -1); - ASSERT(m_rgbaAlphaLocation != -1); - - m_initialized = true; -} - -VideoLayerChromium::SharedValues::~SharedValues() -{ - if (m_yuvShaderProgram) - GLC(m_context, m_context->deleteProgram(m_yuvShaderProgram)); - if (m_rgbaShaderProgram) - GLC(m_context, m_context->deleteProgram(m_rgbaShaderProgram)); -} - PassRefPtr<VideoLayerChromium> VideoLayerChromium::create(GraphicsLayerChromium* owner, VideoFrameProvider* provider) { @@ -297,9 +179,27 @@ bool VideoLayerChromium::allocateTexturesIfNeeded(GraphicsContext3D* context, Vi if (!planeTextureSize.isZero() && planeTextureSize != m_textureSizes[plane]) { allocateTexture(context, m_textures[plane], planeTextureSize, textureFormat); m_textureSizes[plane] = planeTextureSize; - m_frameSizes[plane] = IntSize(frame->width(), frame->height()); + 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); } } + + // 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); + } + return true; } @@ -318,9 +218,10 @@ void VideoLayerChromium::updateTexture(GraphicsContext3D* context, unsigned text memcpy(mem, data, dimensions.width() * dimensions.height()); GLC(context, static_cast<Extensions3DChromium*>(context->getExtensions())->unmapTexSubImage2DCHROMIUM(mem)); } else { - // FIXME: We should have some sort of code to handle the case when - // mapTexSubImage2D fails. - m_skipsDraw = true; + // If mapTexSubImage2DCHROMIUM fails, then do the slower texSubImage2D + // upload. This does twice the copies as mapTexSubImage2DCHROMIUM, one + // in the command buffer and another to the texture. + GLC(context, context->texSubImage2D(GraphicsContext3D::TEXTURE_2D, 0, 0, 0, dimensions.width(), dimensions.height(), format, GraphicsContext3D::UNSIGNED_BYTE, data)); } } @@ -330,16 +231,18 @@ void VideoLayerChromium::draw() return; ASSERT(layerRenderer()); - const VideoLayerChromium::SharedValues* sv = layerRenderer()->videoLayerSharedValues(); - ASSERT(sv && sv->initialized()); + 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(sv); + drawYUV(yuvProgram); break; case VideoFrameChromium::RGBA: - drawRGBA(sv); + drawRGBA(rgbaProgram); break; default: // FIXME: Implement other paths. @@ -359,7 +262,7 @@ void VideoLayerChromium::releaseCurrentFrame() resetFrameParameters(); } -void VideoLayerChromium::drawYUV(const SharedValues* sv) +void VideoLayerChromium::drawYUV(const VideoLayerChromium::YUVProgram* program) { GraphicsContext3D* context = layerRendererContext(); GLC(context, context->activeTexture(GraphicsContext3D::TEXTURE1)); @@ -369,49 +272,57 @@ void VideoLayerChromium::drawYUV(const SharedValues* sv) GLC(context, context->activeTexture(GraphicsContext3D::TEXTURE3)); GLC(context, context->bindTexture(GraphicsContext3D::TEXTURE_2D, m_textures[VideoFrameChromium::vPlane])); - layerRenderer()->useShader(sv->yuvShaderProgram()); - unsigned frameWidth = m_frameSizes[VideoFrameChromium::yPlane].width(); - unsigned textureWidth = m_textureSizes[VideoFrameChromium::yPlane].width(); - float widthScaleFactor = static_cast<float>(frameWidth) / textureWidth; - GLC(context, context->uniform1f(sv->yuvWidthScaleFactorLocation(), widthScaleFactor)); + 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(sv->yTextureLocation(), 1)); - GLC(context, context->uniform1i(sv->uTextureLocation(), 2)); - GLC(context, context->uniform1i(sv->vTextureLocation(), 3)); + 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(sv->signAdjLocation(), 0.5)); + GLC(context, context->uniform1f(program->fragmentShader().signAdjLocation(), 0.5)); - GLC(context, context->uniformMatrix3fv(sv->ccMatrixLocation(), 0, const_cast<float*>(yuv2RGB), 1)); + GLC(context, context->uniformMatrix3fv(program->fragmentShader().ccMatrixLocation(), 0, const_cast<float*>(yuv2RGB), 1)); - drawTexturedQuad(context, layerRenderer()->projectionMatrix(), drawTransform(), - bounds().width(), bounds().height(), drawOpacity(), - sv->yuvShaderMatrixLocation(), sv->yuvAlphaLocation()); + 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 SharedValues* sv) +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(sv->rgbaShaderProgram()); + 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->uniform1f(sv->rgbaWidthScaleFactorLocation(), widthScaleFactor)); + GLC(context, context->uniform4f(program->vertexShader().texTransformLocation(), 0, 0, widthScaleFactor, 1)); - GLC(context, context->uniform1i(sv->rgbaTextureLocation(), 0)); + GLC(context, context->uniform1i(program->fragmentShader().samplerLocation(), 0)); - drawTexturedQuad(context, layerRenderer()->projectionMatrix(), drawTransform(), - bounds().width(), bounds().height(), drawOpacity(), - sv->rgbaShaderMatrixLocation(), sv->rgbaAlphaLocation()); + drawTexturedQuad(context, layerRenderer()->projectionMatrix(), ccLayerImpl()->drawTransform(), + bounds().width(), bounds().height(), ccLayerImpl()->drawOpacity(), + program->vertexShader().matrixLocation(), + program->fragmentShader().alphaLocation()); } void VideoLayerChromium::resetFrameParameters() diff --git a/Source/WebCore/platform/graphics/chromium/VideoLayerChromium.h b/Source/WebCore/platform/graphics/chromium/VideoLayerChromium.h index ac3bca9..2170e13 100644 --- a/Source/WebCore/platform/graphics/chromium/VideoLayerChromium.h +++ b/Source/WebCore/platform/graphics/chromium/VideoLayerChromium.h @@ -46,53 +46,19 @@ public: VideoFrameProvider* = 0); virtual ~VideoLayerChromium(); virtual void updateContentsIfDirty(); - virtual bool drawsContent() { return true; } + virtual bool drawsContent() const { return true; } virtual void draw(); // This function is called by VideoFrameProvider. When this method is called // putCurrentFrame() must be called to return the frame currently held. void releaseCurrentFrame(); - class SharedValues { - public: - explicit SharedValues(GraphicsContext3D*); - ~SharedValues(); - unsigned yuvShaderProgram() const { return m_yuvShaderProgram; } - unsigned rgbaShaderProgram() const { return m_rgbaShaderProgram; } - int yuvShaderMatrixLocation() const { return m_yuvShaderMatrixLocation; } - int rgbaShaderMatrixLocation() const { return m_rgbaShaderMatrixLocation; } - int yuvWidthScaleFactorLocation() const { return m_yuvWidthScaleFactorLocation; } - int rgbaWidthScaleFactorLocation() const { return m_rgbaWidthScaleFactorLocation; } - int yTextureLocation() const { return m_yTextureLocation; } - int uTextureLocation() const { return m_uTextureLocation; } - int vTextureLocation() const { return m_vTextureLocation; } - int yuvAlphaLocation() const { return m_yuvAlphaLocation; } - int rgbaAlphaLocation() const { return m_rgbaAlphaLocation; } - int rgbaTextureLocation() const { return m_rgbaTextureLocation; } - int ccMatrixLocation() const { return m_ccMatrixLocation; } - int signAdjLocation() const { return m_signAdjLocation; } - bool initialized() const { return m_initialized; } - private: - GraphicsContext3D* m_context; - unsigned m_yuvShaderProgram; - unsigned m_rgbaShaderProgram; - int m_yuvShaderMatrixLocation; - int m_yuvWidthScaleFactorLocation; - int m_rgbaShaderMatrixLocation; - int m_rgbaWidthScaleFactorLocation; - int m_ccMatrixLocation; - int m_signAdjLocation; - int m_yTextureLocation; - int m_uTextureLocation; - int m_vTextureLocation; - int m_rgbaTextureLocation; - int m_yuvAlphaLocation; - int m_rgbaAlphaLocation; - bool m_initialized; - }; + typedef ProgramBinding<VertexShaderPosTexTransform, FragmentShaderRGBATexFlipAlpha> RGBAProgram; + typedef ProgramBinding<VertexShaderPosTexYUVStretch, FragmentShaderYUVVideo> YUVProgram; protected: virtual void cleanupResources(); + virtual const char* layerTypeAsString() const { return "VideoLayer"; } private: VideoLayerChromium(GraphicsLayerChromium* owner, VideoFrameProvider*); @@ -103,8 +69,8 @@ private: void updateRGBAContents(GraphicsContext3D*, const VideoFrameChromium*); void allocateTexture(GraphicsContext3D*, unsigned textureId, const IntSize& dimensions, unsigned textureFormat); void updateTexture(GraphicsContext3D*, unsigned textureId, const IntSize& dimensions, unsigned textureFormat, const void* data); - void drawYUV(const SharedValues*); - void drawRGBA(const SharedValues*); + void drawYUV(const YUVProgram*); + void drawRGBA(const RGBAProgram*); void resetFrameParameters(); void saveCurrentFrame(VideoFrameChromium*); diff --git a/Source/WebCore/platform/graphics/chromium/WebGLLayerChromium.cpp b/Source/WebCore/platform/graphics/chromium/WebGLLayerChromium.cpp index 5b34bb9..e83d045 100644 --- a/Source/WebCore/platform/graphics/chromium/WebGLLayerChromium.cpp +++ b/Source/WebCore/platform/graphics/chromium/WebGLLayerChromium.cpp @@ -82,6 +82,7 @@ void WebGLLayerChromium::setContext(const GraphicsContext3D* context) if (textureId != m_textureId) m_textureChanged = true; m_textureId = textureId; + m_premultipliedAlpha = m_context->getContextAttributes().premultipliedAlpha; } } diff --git a/Source/WebCore/platform/graphics/chromium/WebGLLayerChromium.h b/Source/WebCore/platform/graphics/chromium/WebGLLayerChromium.h index c67cc2c..70be876 100644 --- a/Source/WebCore/platform/graphics/chromium/WebGLLayerChromium.h +++ b/Source/WebCore/platform/graphics/chromium/WebGLLayerChromium.h @@ -44,11 +44,14 @@ class GraphicsContext3D; class WebGLLayerChromium : public CanvasLayerChromium { public: static PassRefPtr<WebGLLayerChromium> create(GraphicsLayerChromium* owner = 0); - virtual bool drawsContent() { return m_context; } + virtual bool drawsContent() const { return m_context; } virtual void updateContentsIfDirty(); void setContext(const GraphicsContext3D* context); +protected: + virtual const char* layerTypeAsString() const { return "WebGLLayer"; } + private: explicit WebGLLayerChromium(GraphicsLayerChromium* owner); GraphicsContext3D* m_context; diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCHeadsUpDisplay.cpp b/Source/WebCore/platform/graphics/chromium/cc/CCHeadsUpDisplay.cpp new file mode 100644 index 0000000..604ef61 --- /dev/null +++ b/Source/WebCore/platform/graphics/chromium/cc/CCHeadsUpDisplay.cpp @@ -0,0 +1,172 @@ +/* + * Copyright (C) 2011 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" + +#if USE(ACCELERATED_COMPOSITING) +#include "CCHeadsUpDisplay.h" + +#include "CurrentTime.h" +#include "Font.h" +#include "FontDescription.h" +#include "GraphicsContext3D.h" +#include "LayerChromium.h" +#include "LayerTexture.h" +#include "TextRun.h" +#include "TextStream.h" +#include "TextureManager.h" +#include <wtf/text/CString.h> +#include <wtf/text/WTFString.h> + +namespace WebCore { + +using namespace std; + +CCHeadsUpDisplay::CCHeadsUpDisplay(LayerRendererChromium* owner) + : m_currentFrameNumber(0) + , m_layerRenderer(owner) + , m_showFPSCounter(false) + , m_showPlatformLayerTree(false) +{ + m_presentTimeHistoryInSec[0] = currentTime(); + m_presentTimeHistoryInSec[1] = m_presentTimeHistoryInSec[0]; +} + +CCHeadsUpDisplay::~CCHeadsUpDisplay() +{ +} + +void CCHeadsUpDisplay::draw() +{ + GraphicsContext3D* context = m_layerRenderer->context(); + if (!m_hudTexture) + m_hudTexture = LayerTexture::create(context, m_layerRenderer->textureManager()); + + // Use a fullscreen texture only if we need to... + IntSize hudSize; + if (m_showPlatformLayerTree) { + hudSize.setWidth(min(2048, m_layerRenderer->visibleRectSize().width())); + hudSize.setHeight(min(2048, m_layerRenderer->visibleRectSize().height())); + } else { + hudSize.setWidth(512); + hudSize.setHeight(128); + } + + m_hudTexture->reserve(hudSize, GraphicsContext3D::RGBA); + + // Render pixels into the texture. + PlatformCanvas canvas; + canvas.resize(hudSize); + { + PlatformCanvas::Painter painter(&canvas); + drawHudContents(painter.context(), hudSize); + } + + // Upload to GL. + { + PlatformCanvas::AutoLocker locker(&canvas); + + m_hudTexture->bindTexture(); + GLC(context.get(), context->texImage2D(GraphicsContext3D::TEXTURE_2D, 0, GraphicsContext3D::RGBA, canvas.size().width(), canvas.size().height(), 0, GraphicsContext3D::RGBA, GraphicsContext3D::UNSIGNED_BYTE, locker.pixels())); + } + + // Draw the HUD onto the default render surface. + const ContentLayerChromium::Program* program = m_layerRenderer->contentLayerProgram(); + ASSERT(program && program->initialized()); + GLC(context, context->activeTexture(GraphicsContext3D::TEXTURE0)); + m_hudTexture->bindTexture(); + m_layerRenderer->useShader(program->program()); + GLC(context, context->uniform1i(program->fragmentShader().samplerLocation(), 0)); + + TransformationMatrix matrix; + matrix.translate3d(hudSize.width() * 0.5, hudSize.height() * 0.5, 0); + LayerChromium::drawTexturedQuad(context, m_layerRenderer->projectionMatrix(), + matrix, hudSize.width(), hudSize.height(), + 1.0f, program->vertexShader().matrixLocation(), + program->fragmentShader().alphaLocation()); + + m_hudTexture->unreserve(); +} + +void CCHeadsUpDisplay::drawHudContents(GraphicsContext* ctx, const IntSize& hudSize) +{ + FontDescription mediumFontDesc; + mediumFontDesc.setGenericFamily(FontDescription::MonospaceFamily); + mediumFontDesc.setComputedSize(12); + Font mediumFont(mediumFontDesc, 0, 0); + mediumFont.update(0); + + FontDescription smallFontDesc; + smallFontDesc.setGenericFamily(FontDescription::MonospaceFamily); + smallFontDesc.setComputedSize(10); + Font smallFont(smallFontDesc, 0, 0); + smallFont.update(0); + + // We haven't finished rendering yet, so we don't now the "current" present time. + // So, consider the *last two* present times and use those as our present time. + double secForLastFrame = m_presentTimeHistoryInSec[(m_currentFrameNumber - 1) % 2] - m_presentTimeHistoryInSec[m_currentFrameNumber % 2]; + + int y = 14; + + if (m_showPlatformLayerTree) { + ctx->setFillColor(Color(0, 0, 0, 192), ColorSpaceDeviceRGB); + ctx->fillRect(FloatRect(0, 0, hudSize.width(), hudSize.height())); + } + + // Draw fps. + String topLine = ""; + if (secForLastFrame > 0 && m_showFPSCounter) { + double fps = 1.0 / secForLastFrame; + topLine += String::format("FPS: %3.1f", fps); + } + if (topLine.length()) { + ctx->setFillColor(Color(0, 0, 0, 255), ColorSpaceDeviceRGB); + TextRun run(topLine); + ctx->fillRect(FloatRect(2, 2, mediumFont.width(run) + 2.0f, 15)); + ctx->setFillColor(Color(255, 0, 0), ColorSpaceDeviceRGB); + ctx->drawText(mediumFont, run, IntPoint(3, y)); + y = 26; + } + + // Draw layer tree, if enabled. + if (m_showPlatformLayerTree) { + ctx->setFillColor(Color(255, 0, 0), ColorSpaceDeviceRGB); + Vector<String> lines; + m_layerRenderer->layerTreeAsText().split('\n', lines); + for (size_t i = 0; i < lines.size(); ++i) { + ctx->drawText(smallFont, TextRun(lines[i]), IntPoint(2, y)); + y += 12; + } + } +} + +void CCHeadsUpDisplay::onPresent() +{ + m_presentTimeHistoryInSec[m_currentFrameNumber % 2] = currentTime(); + m_currentFrameNumber += 1; +} + +} + +#endif // USE(ACCELERATED_COMPOSITING) diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCHeadsUpDisplay.h b/Source/WebCore/platform/graphics/chromium/cc/CCHeadsUpDisplay.h new file mode 100644 index 0000000..dbac22a --- /dev/null +++ b/Source/WebCore/platform/graphics/chromium/cc/CCHeadsUpDisplay.h @@ -0,0 +1,79 @@ +/* + * Copyright (C) 2011 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef CCHeadsUpDisplay_h +#define CCHeadsUpDisplay_h + +#if USE(ACCELERATED_COMPOSITING) + +#include "LayerRendererChromium.h" + +namespace WebCore { + +class GeometryBinding; +class GraphicsContext3D; + +// Class that handles drawing of composited render layers using GL. +class CCHeadsUpDisplay { + WTF_MAKE_NONCOPYABLE(CCHeadsUpDisplay); +public: + static PassOwnPtr<CCHeadsUpDisplay> create(LayerRendererChromium* owner) + { + return adoptPtr(new CCHeadsUpDisplay(owner)); + } + + ~CCHeadsUpDisplay(); + + void onPresent(); + + void setShowFPSCounter(bool enable) { m_showFPSCounter = enable; } + bool showFPSCounter() const { return m_showFPSCounter; } + + void setShowPlatformLayerTree(bool enable) { m_showPlatformLayerTree = enable; } + bool showPlatformLayerTree() const { return m_showPlatformLayerTree; } + + bool enabled() const { return true || m_showPlatformLayerTree || m_showFPSCounter; } + void draw(); + +private: + explicit CCHeadsUpDisplay(LayerRendererChromium* owner); + void drawHudContents(GraphicsContext*, const IntSize& hudSize); + + int m_currentFrameNumber; + + OwnPtr<LayerTexture> m_hudTexture; + + LayerRendererChromium* m_layerRenderer; + + double m_presentTimeHistoryInSec[2]; + + bool m_showFPSCounter; + bool m_showPlatformLayerTree; +}; + +} + +#endif // USE(ACCELERATED_COMPOSITING) + +#endif diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCLayerImpl.cpp b/Source/WebCore/platform/graphics/chromium/cc/CCLayerImpl.cpp new file mode 100644 index 0000000..a0ad0fb --- /dev/null +++ b/Source/WebCore/platform/graphics/chromium/cc/CCLayerImpl.cpp @@ -0,0 +1,197 @@ +/* + * Copyright (C) 2011 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" + +#if USE(ACCELERATED_COMPOSITING) + +#include "cc/CCLayerImpl.h" + +#include "GraphicsContext3D.h" +#include "LayerChromium.h" // FIXME: temporary and bad +#include "LayerRendererChromium.h" +#include "RenderSurfaceChromium.h" +#include <wtf/text/WTFString.h> + +namespace { +void toGLMatrix(float* flattened, const WebCore::TransformationMatrix& m) +{ + flattened[0] = m.m11(); + flattened[1] = m.m12(); + flattened[2] = m.m13(); + flattened[3] = m.m14(); + flattened[4] = m.m21(); + flattened[5] = m.m22(); + flattened[6] = m.m23(); + flattened[7] = m.m24(); + flattened[8] = m.m31(); + flattened[9] = m.m32(); + flattened[10] = m.m33(); + flattened[11] = m.m34(); + flattened[12] = m.m41(); + flattened[13] = m.m42(); + flattened[14] = m.m43(); + flattened[15] = m.m44(); +} +} + + +namespace WebCore { + +CCLayerImpl::CCLayerImpl(LayerChromium* owner) + : m_owner(owner) +#ifndef NDEBUG + , m_debugID(owner->debugID()) +#endif + , m_targetRenderSurface(0) + , m_drawDepth(0) + , m_drawOpacity(0) + , m_doubleSided(true) + , m_debugBorderColor(0, 0, 0, 0) + , m_debugBorderWidth(0) + , m_renderSurface(0) + , m_layerRenderer(0) +{ +} + +CCLayerImpl::~CCLayerImpl() +{ +} + +// These are pseudo-structural hacks until we get real tree syncing up in this piece. +CCLayerImpl* CCLayerImpl::superlayer() const +{ + return m_owner->superlayer() ? m_owner->superlayer()->ccLayerImpl() : 0; +} + +CCLayerImpl* CCLayerImpl::maskLayer() const +{ + return m_owner->maskLayer() ? m_owner->maskLayer()->ccLayerImpl() : 0; +} + +CCLayerImpl* CCLayerImpl::replicaLayer() const +{ + return m_owner->replicaLayer() ? m_owner->replicaLayer()->ccLayerImpl() : 0; +} + +void CCLayerImpl::setLayerRenderer(LayerRendererChromium* renderer) +{ + m_layerRenderer = renderer; +} + +RenderSurfaceChromium* CCLayerImpl::createRenderSurface() +{ + m_renderSurface = new RenderSurfaceChromium(this); + return m_renderSurface.get(); +} + +// These belong on CCLayerImpl, but should be subclased by each type and not defer to the LayerChromium subtypes. +bool CCLayerImpl::drawsContent() const +{ + return m_owner->drawsContent(); +} + +void CCLayerImpl::draw() +{ + return m_owner->draw(); +} + +void CCLayerImpl::unreserveContentsTexture() +{ + m_owner->unreserveContentsTexture(); +} + +void CCLayerImpl::bindContentsTexture() +{ + m_owner->bindContentsTexture(); +} + +void CCLayerImpl::cleanupResources() +{ + if (renderSurface()) + renderSurface()->cleanupResources(); +} + +const IntRect CCLayerImpl::getDrawRect() const +{ + // Form the matrix used by the shader to map the corners of the layer's + // bounds into the view space. + FloatRect layerRect(-0.5 * bounds().width(), -0.5 * bounds().height(), bounds().width(), bounds().height()); + IntRect mappedRect = enclosingIntRect(drawTransform().mapRect(layerRect)); + return mappedRect; +} + +void CCLayerImpl::drawDebugBorder() +{ + static float glMatrix[16]; + if (!debugBorderColor().alpha()) + return; + + ASSERT(layerRenderer()); + const LayerChromium::BorderProgram* program = layerRenderer()->borderProgram(); + ASSERT(program && program->initialized()); + layerRenderer()->useShader(program->program()); + TransformationMatrix renderMatrix = drawTransform(); + renderMatrix.scale3d(bounds().width(), bounds().height(), 1); + toGLMatrix(&glMatrix[0], layerRenderer()->projectionMatrix() * renderMatrix); + GraphicsContext3D* context = layerRenderer()->context(); + GLC(context, context->uniformMatrix4fv(program->vertexShader().matrixLocation(), false, &glMatrix[0], 1)); + + GLC(context, context->uniform4f(program->fragmentShader().colorLocation(), debugBorderColor().red() / 255.0, debugBorderColor().green() / 255.0, debugBorderColor().blue() / 255.0, 1)); + + GLC(context, context->lineWidth(debugBorderWidth())); + + // The indices for the line are stored in the same array as the triangle indices. + GLC(context, context->drawElements(GraphicsContext3D::LINE_LOOP, 4, GraphicsContext3D::UNSIGNED_SHORT, 6 * sizeof(unsigned short))); +} + +static void writeIndent(TextStream& ts, int indent) +{ + for (int i = 0; i != indent; ++i) + ts << " "; +} + +void CCLayerImpl::dumpLayerProperties(TextStream& ts, int indent) const +{ + writeIndent(ts, indent); + ts << "bounds: " << bounds().width() << ", " << bounds().height() << "\n"; + + if (m_targetRenderSurface) { + writeIndent(ts, indent); + ts << "targetRenderSurface: " << m_targetRenderSurface->name() << "\n"; + } + + writeIndent(ts, indent); + ts << "drawTransform: "; + ts << m_drawTransform.m11() << ", " << m_drawTransform.m12() << ", " << m_drawTransform.m13() << ", " << m_drawTransform.m14() << ", "; + ts << m_drawTransform.m21() << ", " << m_drawTransform.m22() << ", " << m_drawTransform.m23() << ", " << m_drawTransform.m24() << ", "; + ts << m_drawTransform.m31() << ", " << m_drawTransform.m32() << ", " << m_drawTransform.m33() << ", " << m_drawTransform.m34() << ", "; + ts << m_drawTransform.m41() << ", " << m_drawTransform.m42() << ", " << m_drawTransform.m43() << ", " << m_drawTransform.m44() << "\n"; +} + +} + +#endif // USE(ACCELERATED_COMPOSITING) + diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCLayerImpl.h b/Source/WebCore/platform/graphics/chromium/cc/CCLayerImpl.h new file mode 100644 index 0000000..6892976 --- /dev/null +++ b/Source/WebCore/platform/graphics/chromium/cc/CCLayerImpl.h @@ -0,0 +1,164 @@ +/* + * Copyright (C) 2011 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef CCLayerImpl_h +#define CCLayerImpl_h + +#include "Color.h" +#include "FloatRect.h" +#include "IntRect.h" +#include "TextStream.h" +#include "TransformationMatrix.h" +#include <wtf/OwnPtr.h> +#include <wtf/PassRefPtr.h> +#include <wtf/RefCounted.h> +#include <wtf/text/WTFString.h> + +namespace WebCore { + +class LayerChromium; +class LayerRendererChromium; +class RenderSurfaceChromium; + +class CCLayerImpl : public RefCounted<CCLayerImpl> { +public: + static PassRefPtr<CCLayerImpl> create(LayerChromium* owner) + { + return adoptRef(new CCLayerImpl(owner)); + } + // When this class gets subclasses, remember to add 'virtual' here. + ~CCLayerImpl(); + +#ifndef NDEBUG + int debugID() const { return m_debugID; } +#endif + + CCLayerImpl* superlayer() const; + CCLayerImpl* maskLayer() const; + CCLayerImpl* replicaLayer() const; + + void draw(); + bool drawsContent() const; + void unreserveContentsTexture(); + void bindContentsTexture(); + + void cleanupResources(); + + void setName(const String& name) { m_name = name; } + const String& name() const { return m_name; } + + // Debug layer border - visual effect only, do not change geometry/clipping/etc. + void setDebugBorderColor(Color c) { m_debugBorderColor = c; } + Color debugBorderColor() const { return m_debugBorderColor; } + void setDebugBorderWidth(float width) { m_debugBorderWidth = width; } + float debugBorderWidth() const { return m_debugBorderWidth; } + + void drawDebugBorder(); + + void setLayerRenderer(LayerRendererChromium*); + LayerRendererChromium* layerRenderer() const { return m_layerRenderer.get(); } + + RenderSurfaceChromium* createRenderSurface(); + + RenderSurfaceChromium* renderSurface() const { return m_renderSurface.get(); } + void clearRenderSurface() { m_renderSurface.clear(); } + float drawDepth() const { return m_drawDepth; } + void setDrawDepth(float depth) { m_drawDepth = depth; } + float drawOpacity() const { return m_drawOpacity; } + void setDrawOpacity(float opacity) { m_drawOpacity = opacity; } + const IntRect& scissorRect() const { return m_scissorRect; } + void setScissorRect(const IntRect& rect) { m_scissorRect = rect; } + RenderSurfaceChromium* targetRenderSurface() const { return m_targetRenderSurface; } + void setTargetRenderSurface(RenderSurfaceChromium* surface) { m_targetRenderSurface = surface; } + + bool doubleSided() const { return m_doubleSided; } + void setDoubleSided(bool doubleSided) { m_doubleSided = doubleSided; } + const IntSize& bounds() const { return m_bounds; } + void setBounds(const IntSize& bounds) { m_bounds = bounds; } + + // Returns the rect containtaining this layer in the current view's coordinate system. + const IntRect getDrawRect() const; + + const TransformationMatrix& drawTransform() const { return m_drawTransform; } + void setDrawTransform(const TransformationMatrix& matrix) { m_drawTransform = matrix; } + const IntRect& drawableContentRect() const { return m_drawableContentRect; } + void setDrawableContentRect(const IntRect& rect) { m_drawableContentRect = rect; } + + virtual void dumpLayerProperties(TextStream&, int indent) const; + +private: + // For now, CCLayers are owned directly by a LayerChromium. + LayerChromium* m_owner; + explicit CCLayerImpl(LayerChromium*); + + // Debugging. +#ifndef NDEBUG + int m_debugID; +#endif + + String m_name; + + // Render surface this layer draws into. This is a surface that can belong + // either to this layer (if m_targetRenderSurface == m_renderSurface) or + // to an ancestor of this layer. The target render surface determines the + // coordinate system the layer's transforms are relative to. + RenderSurfaceChromium* m_targetRenderSurface; + + // The global depth value of the center of the layer. This value is used + // to sort layers from back to front. + float m_drawDepth; + float m_drawOpacity; + + // Whether the "back" of this layer should draw. + bool m_doubleSided; + + // Debug borders. + Color m_debugBorderColor; + float m_debugBorderWidth; + + TransformationMatrix m_drawTransform; + + IntSize m_bounds; + + // The scissor rectangle that should be used when this layer is drawn. + // Inherited by the parent layer and further restricted if this layer masks + // to bounds. + IntRect m_scissorRect; + + // Render surface associated with this layer. The layer and its descendants + // will render to this surface. + OwnPtr<RenderSurfaceChromium> m_renderSurface; + + // Hierarchical bounding rect containing the layer and its descendants. + IntRect m_drawableContentRect; + + // Points to the layer renderer that updates and draws this layer. + RefPtr<LayerRendererChromium> m_layerRenderer; +}; + +} + +#endif // CCLayerImpl_h + |