diff options
author | Leon Clarke <leonclarke@google.com> | 2010-06-03 14:33:32 +0100 |
---|---|---|
committer | Leon Clarke <leonclarke@google.com> | 2010-06-08 12:24:51 +0100 |
commit | 5af96e2c7b73ebc627c6894727826a7576d31758 (patch) | |
tree | f9d5e6f6175ccd7e3d14de9b290f08937a0d17ba /WebCore/platform/graphics | |
parent | 8cc4fcf4f6adcbc0e0aebfc24fbad9a4cddf2cfb (diff) | |
download | external_webkit-5af96e2c7b73ebc627c6894727826a7576d31758.zip external_webkit-5af96e2c7b73ebc627c6894727826a7576d31758.tar.gz external_webkit-5af96e2c7b73ebc627c6894727826a7576d31758.tar.bz2 |
Merge webkit.org at r60469 : Initial merge by git.
Change-Id: I66a0047aa2af802f66bb0c7f2a8b02247a596234
Diffstat (limited to 'WebCore/platform/graphics')
47 files changed, 1113 insertions, 315 deletions
diff --git a/WebCore/platform/graphics/BitmapImage.cpp b/WebCore/platform/graphics/BitmapImage.cpp index e3db752..62f29cf 100644 --- a/WebCore/platform/graphics/BitmapImage.cpp +++ b/WebCore/platform/graphics/BitmapImage.cpp @@ -408,7 +408,9 @@ bool BitmapImage::internalAdvanceAnimation(bool skippingFrames) // Get the repetition count again. If we weren't able to get a // repetition count before, we should have decoded the whole image by // now, so it should now be available. - if (repetitionCount(true) && m_repetitionsComplete >= m_repetitionCount) { + // Note that we don't need to special-case cAnimationLoopOnce here + // because it is 0 (see comments on its declaration in ImageSource.h). + if (repetitionCount(true) != cAnimationLoopInfinite && m_repetitionsComplete > m_repetitionCount) { m_animationFinished = true; m_desiredFrameStartTime = 0; --m_currentFrame; diff --git a/WebCore/platform/graphics/FloatSize.h b/WebCore/platform/graphics/FloatSize.h index 53a0071..ff3d4de 100644 --- a/WebCore/platform/graphics/FloatSize.h +++ b/WebCore/platform/graphics/FloatSize.h @@ -63,6 +63,14 @@ public: bool isEmpty() const { return m_width <= 0 || m_height <= 0; } + float aspectRatio() const { return m_width / m_height; } + + void scale(float scale) + { + m_width *= scale; + m_height *= scale; + } + FloatSize expandedTo(const FloatSize& other) const { return FloatSize(m_width > other.m_width ? m_width : other.m_width, diff --git a/WebCore/platform/graphics/ImageBuffer.h b/WebCore/platform/graphics/ImageBuffer.h index 7821288..9163523 100644 --- a/WebCore/platform/graphics/ImageBuffer.h +++ b/WebCore/platform/graphics/ImageBuffer.h @@ -1,6 +1,7 @@ /* * Copyright (C) 2006 Nikolas Zimmermann <zimmermann@kde.org> * Copyright (C) 2007, 2008, 2009 Apple Inc. All rights reserved. + * Copyright (C) 2010 Torch Mobile (Beijing) Co. Ltd. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -82,7 +83,7 @@ namespace WebCore { void putUnmultipliedImageData(ImageData*, const IntRect& sourceRect, const IntPoint& destPoint); void putPremultipliedImageData(ImageData*, const IntRect& sourceRect, const IntPoint& destPoint); - String toDataURL(const String& mimeType) const; + String toDataURL(const String& mimeType, double quality = 1.0) const; #if !PLATFORM(CG) AffineTransform baseTransform() const { return AffineTransform(); } void transformColorSpace(ImageColorSpace srcColorSpace, ImageColorSpace dstColorSpace); diff --git a/WebCore/platform/graphics/ImageSource.h b/WebCore/platform/graphics/ImageSource.h index 5c6d75e..d9bfa25 100644 --- a/WebCore/platform/graphics/ImageSource.h +++ b/WebCore/platform/graphics/ImageSource.h @@ -115,7 +115,22 @@ typedef RefPtr<SharedBitmap> NativeImagePtr; #endif #endif -const int cAnimationLoopOnce = -1; +// Right now GIFs are the only recognized image format that supports animation. +// The animation system and the constants below are designed with this in mind. +// GIFs have an optional 16-bit unsigned loop count that describes how an +// animated GIF should be cycled. If the loop count is absent, the animation +// cycles once; if it is 0, the animation cycles infinitely; otherwise the +// animation plays n + 1 cycles (where n is the specified loop count). If the +// GIF decoder defaults to cAnimationLoopOnce in the absence of any loop count +// and translates an explicit "0" loop count to cAnimationLoopInfinite, then we +// get a couple of nice side effects: +// * By making cAnimationLoopOnce be 0, we allow the animation cycling code in +// BitmapImage.cpp to avoid special-casing it, and simply treat all +// non-negative loop counts identically. +// * By making the other two constants negative, we avoid conflicts with any +// real loop count values. +const int cAnimationLoopOnce = 0; +const int cAnimationLoopInfinite = -1; const int cAnimationNone = -2; class ImageSource : public Noncopyable { diff --git a/WebCore/platform/graphics/IntSize.h b/WebCore/platform/graphics/IntSize.h index b60338c..9ecf389 100644 --- a/WebCore/platform/graphics/IntSize.h +++ b/WebCore/platform/graphics/IntSize.h @@ -72,6 +72,8 @@ public: bool isEmpty() const { return m_width <= 0 || m_height <= 0; } bool isZero() const { return !m_width && !m_height; } + + float aspectRatio() const { return static_cast<float>(m_width) / static_cast<float>(m_height); } void expand(int width, int height) { diff --git a/WebCore/platform/graphics/TiledBackingStore.cpp b/WebCore/platform/graphics/TiledBackingStore.cpp index 0250061..1d6f237 100644 --- a/WebCore/platform/graphics/TiledBackingStore.cpp +++ b/WebCore/platform/graphics/TiledBackingStore.cpp @@ -35,6 +35,9 @@ TiledBackingStore::TiledBackingStore(TiledBackingStoreClient* client) , m_tileBufferUpdateTimer(new TileTimer(this, &TiledBackingStore::tileBufferUpdateTimerFired)) , m_tileCreationTimer(new TileTimer(this, &TiledBackingStore::tileCreationTimerFired)) , m_tileSize(defaultTileWidth, defaultTileHeight) + , m_tileCreationDelay(0.01) + , m_keepAreaMultiplier(2.f, 3.5f) + , m_coverAreaMultiplier(1.5f, 2.5f) , m_contentsScale(1.f) , m_pendingScale(0) , m_contentsFrozen(false) @@ -46,6 +49,25 @@ TiledBackingStore::~TiledBackingStore() delete m_tileBufferUpdateTimer; delete m_tileCreationTimer; } + +void TiledBackingStore::setTileSize(const IntSize& size) +{ + m_tileSize = size; + m_tiles.clear(); + startTileCreationTimer(); +} + +void TiledBackingStore::setTileCreationDelay(double delay) +{ + m_tileCreationDelay = delay; +} + +void TiledBackingStore::setKeepAndCoverAreaMultipliers(const FloatSize& keepMultiplier, const FloatSize& coverMultiplier) +{ + m_keepAreaMultiplier = keepMultiplier; + m_coverAreaMultiplier = coverMultiplier; + startTileCreationTimer(); +} void TiledBackingStore::invalidate(const IntRect& contentsDirtyRect) { @@ -188,17 +210,16 @@ void TiledBackingStore::createTiles() // Remove tiles that extend outside the current contents rect. dropOverhangingTiles(); - // FIXME: Make configurable/adapt to memory. IntRect keepRect = visibleRect; - keepRect.inflateX(visibleRect.width()); - keepRect.inflateY(3 * visibleRect.height()); + keepRect.inflateX(visibleRect.width() * (m_keepAreaMultiplier.width() - 1.f)); + keepRect.inflateY(visibleRect.height() * (m_keepAreaMultiplier.height() - 1.f)); keepRect.intersect(contentsRect()); dropTilesOutsideRect(keepRect); IntRect coverRect = visibleRect; - coverRect.inflateX(visibleRect.width() / 2); - coverRect.inflateY(2 * visibleRect.height()); + coverRect.inflateX(visibleRect.width() * (m_coverAreaMultiplier.width() - 1.f)); + coverRect.inflateY(visibleRect.height() * (m_coverAreaMultiplier.height() - 1.f)); coverRect.intersect(contentsRect()); // Search for the tile position closest to the viewport center that does not yet contain a tile. @@ -240,7 +261,7 @@ void TiledBackingStore::createTiles() // Keep creating tiles until the whole coverRect is covered. if (requiredTileCount) - m_tileCreationTimer->startOneShot(0); + m_tileCreationTimer->startOneShot(m_tileCreationDelay); } void TiledBackingStore::dropOverhangingTiles() diff --git a/WebCore/platform/graphics/TiledBackingStore.h b/WebCore/platform/graphics/TiledBackingStore.h index d12f191..58477db 100644 --- a/WebCore/platform/graphics/TiledBackingStore.h +++ b/WebCore/platform/graphics/TiledBackingStore.h @@ -51,6 +51,20 @@ public: void invalidate(const IntRect& dirtyRect); void paint(GraphicsContext*, const IntRect&); + + IntSize tileSize() { return m_tileSize; } + void setTileSize(const IntSize&); + + double tileCreationDelay() const { return m_tileCreationDelay; } + void setTileCreationDelay(double delay); + + // Tiled are dropped outside the keep area, and created for cover area. The values a relative to the viewport size. + void getKeepAndCoverAreaMultipliers(FloatSize& keepMultiplier, FloatSize& coverMultiplier) + { + keepMultiplier = m_keepAreaMultiplier; + coverMultiplier = m_coverAreaMultiplier; + } + void setKeepAndCoverAreaMultipliers(const FloatSize& keepMultiplier, const FloatSize& coverMultiplier); private: void startTileBufferUpdateTimer(); @@ -94,6 +108,9 @@ private: TileTimer* m_tileCreationTimer; IntSize m_tileSize; + double m_tileCreationDelay; + FloatSize m_keepAreaMultiplier; + FloatSize m_coverAreaMultiplier; IntRect m_previousVisibleRect; float m_contentsScale; diff --git a/WebCore/platform/graphics/cairo/ImageBufferCairo.cpp b/WebCore/platform/graphics/cairo/ImageBufferCairo.cpp index 124c7cf..85a4179 100644 --- a/WebCore/platform/graphics/cairo/ImageBufferCairo.cpp +++ b/WebCore/platform/graphics/cairo/ImageBufferCairo.cpp @@ -2,6 +2,7 @@ * Copyright (C) 2006 Nikolas Zimmermann <zimmermann@kde.org> * Copyright (C) 2007 Holger Hans Peter Freyther <zecke@selfish.org> * Copyright (C) 2008, 2009 Dirk Schulze <krit@webkit.org> + * Copyright (C) 2010 Torch Mobile (Beijing) Co. Ltd. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -283,7 +284,7 @@ static cairo_status_t writeFunction(void* closure, const unsigned char* data, un return CAIRO_STATUS_SUCCESS; } -String ImageBuffer::toDataURL(const String& mimeType) const +String ImageBuffer::toDataURL(const String& mimeType, double) const { cairo_surface_t* image = cairo_get_target(context()->platformContext()); if (!image) diff --git a/WebCore/platform/graphics/cg/ImageBufferCG.cpp b/WebCore/platform/graphics/cg/ImageBufferCG.cpp index c82ebdc..ce11499 100644 --- a/WebCore/platform/graphics/cg/ImageBufferCG.cpp +++ b/WebCore/platform/graphics/cg/ImageBufferCG.cpp @@ -1,6 +1,7 @@ /* * Copyright (C) 2006 Nikolas Zimmermann <zimmermann@kde.org> * Copyright (C) 2008 Apple Inc. All rights reserved. + * Copyright (C) 2010 Torch Mobile (Beijing) Co. Ltd. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -275,7 +276,7 @@ static RetainPtr<CFStringRef> utiFromMIMEType(const String& mimeType) #endif } -String ImageBuffer::toDataURL(const String& mimeType) const +String ImageBuffer::toDataURL(const String& mimeType, double) const { ASSERT(MIMETypeRegistry::isSupportedImageMIMETypeForEncoding(mimeType)); diff --git a/WebCore/platform/graphics/cg/ImageSourceCG.cpp b/WebCore/platform/graphics/cg/ImageSourceCG.cpp index 0b5f0b0..9ad3166 100644 --- a/WebCore/platform/graphics/cg/ImageSourceCG.cpp +++ b/WebCore/platform/graphics/cg/ImageSourceCG.cpp @@ -202,14 +202,17 @@ int ImageSource::repetitionCount() if (!initialized()) return result; - // A property with value 0 means loop forever. RetainPtr<CFDictionaryRef> properties(AdoptCF, CGImageSourceCopyProperties(m_decoder, imageSourceOptions())); if (properties) { CFDictionaryRef gifProperties = (CFDictionaryRef)CFDictionaryGetValue(properties.get(), kCGImagePropertyGIFDictionary); if (gifProperties) { CFNumberRef num = (CFNumberRef)CFDictionaryGetValue(gifProperties, kCGImagePropertyGIFLoopCount); - if (num) + if (num) { + // A property with value 0 means loop forever. CFNumberGetValue(num, kCFNumberIntType, &result); + if (!result) + result = cAnimationLoopInfinite; + } } else result = cAnimationNone; // Turns out we're not a GIF after all, so we don't animate. } diff --git a/WebCore/platform/graphics/chromium/GraphicsLayerChromium.cpp b/WebCore/platform/graphics/chromium/GraphicsLayerChromium.cpp index 095ded2..37ea485 100644 --- a/WebCore/platform/graphics/chromium/GraphicsLayerChromium.cpp +++ b/WebCore/platform/graphics/chromium/GraphicsLayerChromium.cpp @@ -479,11 +479,6 @@ void GraphicsLayerChromium::updateLayerPreserves3D() void GraphicsLayerChromium::updateLayerDrawsContent() { - // Since only layers that draw content have a valid context - // we need to call updateGraphicsContext() here to make sure one - // gets created. - m_layer->drawsContentUpdated(); - if (m_drawsContent) m_layer->setNeedsDisplay(); diff --git a/WebCore/platform/graphics/chromium/LayerChromium.cpp b/WebCore/platform/graphics/chromium/LayerChromium.cpp index 8fb28ef..b08df82 100644 --- a/WebCore/platform/graphics/chromium/LayerChromium.cpp +++ b/WebCore/platform/graphics/chromium/LayerChromium.cpp @@ -34,10 +34,17 @@ #include "LayerChromium.h" +#include "LayerRendererChromium.h" +#if PLATFORM(SKIA) +#include "NativeImageSkia.h" #include "PlatformContextSkia.h" +#endif #include "RenderLayerBacking.h" #include "skia/ext/platform_canvas.h" +#include <GLES2/gl2.h> + + namespace WebCore { using namespace std; @@ -52,7 +59,9 @@ LayerChromium::LayerChromium(LayerType type, GraphicsLayerChromium* owner) , m_owner(owner) , m_layerType(type) , m_superlayer(0) + , m_layerRenderer(0) , m_borderWidth(0) + , m_allocatedTextureId(0) , m_borderColor(0, 0, 0, 0) , m_backgroundColor(0, 0, 0, 0) , m_anchorPoint(0.5, 0.5) @@ -66,13 +75,9 @@ LayerChromium::LayerChromium(LayerType type, GraphicsLayerChromium* owner) , m_opacity(1.0) , m_opaque(true) , m_zPosition(0.0) - , m_canvas(0) - , m_skiaContext(0) - , m_graphicsContext(0) , m_geometryFlipped(false) , m_contentsDirty(false) , m_contents(0) - , m_hasContext(false) { } @@ -84,61 +89,92 @@ LayerChromium::~LayerChromium() // Remove the superlayer reference from all sublayers. removeAllSublayers(); -} - -void LayerChromium::updateGraphicsContext() -{ - // If the layer doesn't draw anything (e.g. it's a container layer) then we - // don't create a canvas / context for it. The root layer is a special - // case as even if it's marked as a container layer it does actually have - // content that it draws. - RenderLayerBacking* backing = static_cast<RenderLayerBacking*>(m_owner->client()); - if (!drawsContent() && !(this == rootLayer())) { - m_graphicsContext.clear(); - m_skiaContext.clear(); - m_canvas.clear(); - m_hasContext = false; - return; - } - -#if PLATFORM(SKIA) - // Create new canvas and context. OwnPtr takes care of freeing up - // the old ones. - m_canvas = new skia::PlatformCanvas(m_backingStoreSize.width(), m_backingStoreSize.height(), false); - m_skiaContext = new PlatformContextSkia(m_canvas.get()); - - // This is needed to get text to show up correctly. Without it, - // GDI renders with zero alpha and the text becomes invisible. - // Unfortunately, setting this to true disables cleartype. - m_skiaContext->setDrawingToImageBuffer(true); - - m_graphicsContext = new GraphicsContext(reinterpret_cast<PlatformGraphicsContext*>(m_skiaContext.get())); - m_hasContext = true; - m_contentsDirty = true; -#else -#error "Need to implement for your platform." -#endif - - return; + // Notify the renderer to clean up the texture associated with the layer. + if (m_layerRenderer) + m_layerRenderer->freeLayerTexture(this); } -void LayerChromium::drawsContentUpdated() +void LayerChromium::setLayerRenderer(LayerRendererChromium* renderer) { - // Create a drawing context if the layer now draws content - // or delete the existing context if the layer doesn't draw - // content anymore. - updateGraphicsContext(); + // It's not expected that layers will ever switch renderers. + ASSERT(!renderer || !m_layerRenderer || renderer == m_layerRenderer); + + m_layerRenderer = renderer; } -void LayerChromium::updateContents() +void LayerChromium::updateTextureContents(unsigned int textureId) { RenderLayerBacking* backing = static_cast<RenderLayerBacking*>(m_owner->client()); - if (backing && !backing->paintingGoesToWindow() && drawsContent()) - m_owner->paintGraphicsLayerContents(*m_graphicsContext, IntRect(0, 0, m_bounds.width(), m_bounds.height())); + if (backing && !backing->paintingGoesToWindow()) { + void* pixels = 0; + IntRect dirtyRect(m_dirtyRect); + IntSize requiredTextureSize; + IntSize bitmapSize; +#if PLATFORM(SKIA) + const SkBitmap* skiaBitmap = 0; + OwnPtr<skia::PlatformCanvas> canvas; + OwnPtr<PlatformContextSkia> skiaContext; + OwnPtr<GraphicsContext> graphicsContext; + if (drawsContent()) { // Layer contents must be drawn into a canvas. + 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. Without it, + // GDI renders with zero alpha and the text becomes invisible. + // Unfortunately, setting this to true disables cleartype. + // FIXME: Does this take us down a very slow text rendering path? + skiaContext->setDrawingToImageBuffer(true); + + graphicsContext.set(new GraphicsContext(reinterpret_cast<PlatformGraphicsContext*>(skiaContext.get()))); + + // 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(*graphicsContext, dirtyRect); + const SkBitmap& bitmap = canvas->getDevice()->accessBitmap(false); + skiaBitmap = &bitmap; + requiredTextureSize = IntSize(max(m_bounds.width(), dirtyRect.width()), + max(m_bounds.height(), dirtyRect.height())); + } else { // Layer is a container. + // The layer contains an Image. + NativeImageSkia* skiaImage = static_cast<NativeImageSkia*>(contents()); + skiaBitmap = skiaImage; + requiredTextureSize = IntSize(skiaBitmap->width(), skiaBitmap->height()); + } + + ASSERT(skiaBitmap); + 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()); + } +#else +#error "Need to implement for your platform." +#endif + if (pixels) { + glBindTexture(GL_TEXTURE_2D, textureId); + // If the texture id or size changed since last time then we need to tell GL + // to re-allocate a texture. + if (m_allocatedTextureId != textureId || requiredTextureSize != m_allocatedTextureSize) { + ASSERT(bitmapSize == requiredTextureSize); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, requiredTextureSize.width(), requiredTextureSize.height(), 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels); + + m_allocatedTextureId = textureId; + m_allocatedTextureSize = requiredTextureSize; + } else { + ASSERT(dirtyRect.width() <= m_allocatedTextureSize.width() && dirtyRect.height() <= m_allocatedTextureSize.height()); + ASSERT(dirtyRect.width() == bitmapSize.width() && dirtyRect.height() == bitmapSize.height()); + glTexSubImage2D(GL_TEXTURE_2D, 0, dirtyRect.x(), dirtyRect.y(), dirtyRect.width(), dirtyRect.height(), GL_RGBA, GL_UNSIGNED_BYTE, pixels); + } + } + } m_contentsDirty = false; + m_dirtyRect.setSize(FloatSize()); } void LayerChromium::setContents(NativeImagePtr contents) @@ -147,7 +183,7 @@ void LayerChromium::setContents(NativeImagePtr contents) if (m_contents == contents) return; m_contents = contents; - m_contentsDirty = true; + setNeedsDisplay(); } void LayerChromium::setNeedsCommit() @@ -221,19 +257,6 @@ int LayerChromium::indexOfSublayer(const LayerChromium* reference) return -1; } -// This method can be called to overide the size of the backing store -// used for the layer. It's typically called on the root layer to limit -// its size to the actual visible size. -void LayerChromium::setBackingStoreSize(const IntSize& size) -{ - if (m_backingStoreSize == size) - return; - - m_backingStoreSize = size; - updateGraphicsContext(); - setNeedsCommit(); -} - void LayerChromium::setBounds(const IntSize& size) { if (m_bounds == size) @@ -242,8 +265,6 @@ void LayerChromium::setBounds(const IntSize& size) m_bounds = size; m_backingStoreSize = size; - // Re-create the canvas and associated contexts. - updateGraphicsContext(); setNeedsCommit(); } @@ -293,16 +314,17 @@ void LayerChromium::setNeedsDisplay(const FloatRect& dirtyRect) { // Simply mark the contents as dirty. The actual redraw will // happen when it's time to do the compositing. - // FIXME: Should only update the dirty rect instead of marking - // the entire layer dirty. m_contentsDirty = true; + m_dirtyRect.unite(dirtyRect); + setNeedsCommit(); } void LayerChromium::setNeedsDisplay() { - // FIXME: implement + m_dirtyRect.setSize(m_bounds); + m_contentsDirty = true; } } diff --git a/WebCore/platform/graphics/chromium/LayerChromium.h b/WebCore/platform/graphics/chromium/LayerChromium.h index 1b807a5..59952eb 100644 --- a/WebCore/platform/graphics/chromium/LayerChromium.h +++ b/WebCore/platform/graphics/chromium/LayerChromium.h @@ -52,6 +52,8 @@ class PlatformCanvas; namespace WebCore { +class LayerRendererChromium; + class LayerChromium : public RefCounted<LayerChromium> { public: enum LayerType { Layer, TransformLayer }; @@ -150,22 +152,15 @@ public: void setGeometryFlipped(bool flipped) { m_geometryFlipped = flipped; setNeedsCommit(); } bool geometryFlipped() const { return m_geometryFlipped; } - void updateContents(); + void updateTextureContents(unsigned int textureId); bool contentsDirty() { return m_contentsDirty; } void setContents(NativeImagePtr contents); NativeImagePtr contents() const { return m_contents; } - skia::PlatformCanvas* platformCanvas() { return m_canvas.get(); } - GraphicsContext* graphicsContext() { return m_graphicsContext.get(); } - - void setBackingStoreSize(const IntSize&); - bool drawsContent() { return m_owner && m_owner->drawsContent(); } - // This method should be called every time the status drawsContent() - // status changes to ensure that the internal graphics context is in sync. - void drawsContentUpdated(); + void setLayerRenderer(LayerRendererChromium*); private: LayerChromium(LayerType, GraphicsLayerChromium* owner); @@ -187,21 +182,10 @@ private: // This should only be called from removeFromSuperlayer. void removeSublayer(LayerChromium*); - // Re-creates the canvas and graphics context. This method - // must be called every time the layer is resized. Only layers - // that do drawing and the root layer get a context. - void updateGraphicsContext(); - Vector<RefPtr<LayerChromium> > m_sublayers; LayerChromium* m_superlayer; GraphicsLayerChromium* m_owner; -#if PLATFORM(SKIA) - OwnPtr<skia::PlatformCanvas> m_canvas; - OwnPtr<PlatformContextSkia> m_skiaContext; - OwnPtr<GraphicsContext> m_graphicsContext; -#endif - bool m_hasContext; LayerType m_layerType; @@ -211,6 +195,9 @@ private: FloatPoint m_anchorPoint; Color m_backgroundColor; Color m_borderColor; + FloatRect m_dirtyRect; + + LayerRendererChromium* m_layerRenderer; FloatRect m_frame; TransformationMatrix m_transform; @@ -222,6 +209,9 @@ private: float m_anchorPointZ; float m_borderWidth; + unsigned int m_allocatedTextureId; + IntSize m_allocatedTextureSize; + bool m_clearsContext; bool m_doubleSided; bool m_hidden; diff --git a/WebCore/platform/graphics/chromium/LayerRendererChromium.cpp b/WebCore/platform/graphics/chromium/LayerRendererChromium.cpp index fbdb9e2..dfb6078 100644 --- a/WebCore/platform/graphics/chromium/LayerRendererChromium.cpp +++ b/WebCore/platform/graphics/chromium/LayerRendererChromium.cpp @@ -187,6 +187,33 @@ LayerRendererChromium::~LayerRendererChromium() glDeleteProgram(m_scrollProgramObject); glDeleteProgram(m_borderProgramObject); } + + // Free up all GL textures. + for (TextureIdMap::iterator iter = m_textureIdMap.begin(); iter != m_textureIdMap.end(); ++iter) { + glDeleteTextures(1, &(iter->second)); + iter->first->setLayerRenderer(0); + } +} + +// Creates a canvas and an associated graphics context that the root layer will +// render into. +void LayerRendererChromium::setRootLayerCanvasSize(const IntSize& size) +{ + if (size == m_rootLayerCanvasSize) + return; + +#if PLATFORM(SKIA) + // Create new canvas and context. OwnPtr takes care of freeing up + // the old ones. + m_rootLayerCanvas = new skia::PlatformCanvas(size.width(), size.height(), false); + m_rootLayerSkiaContext = new PlatformContextSkia(m_rootLayerCanvas.get()); + m_rootLayerSkiaContext->setDrawingToImageBuffer(true); + m_rootLayerGraphicsContext = new GraphicsContext(reinterpret_cast<PlatformGraphicsContext*>(m_rootLayerSkiaContext.get())); +#else +#error "Need to implement for your platform." +#endif + + m_rootLayerCanvasSize = size; } void LayerRendererChromium::drawTexturedQuad(const TransformationMatrix& matrix, float width, float height, float opacity, bool scrolling) @@ -292,7 +319,7 @@ void LayerRendererChromium::drawLayers(const IntRect& updateRect, const IntRect& #if PLATFORM(SKIA) // Get the contents of the updated rect. - const SkBitmap bitmap = m_rootLayer->platformCanvas()->getDevice()->accessBitmap(false); + const SkBitmap bitmap = m_rootLayerCanvas->getDevice()->accessBitmap(false); int rootLayerWidth = bitmap.width(); int rootLayerHeight = bitmap.height(); ASSERT(rootLayerWidth == updateRect.width() && rootLayerHeight == updateRect.height()); @@ -331,11 +358,12 @@ void LayerRendererChromium::drawLayers(const IntRect& updateRect, const IntRect& checkGLError(); - // FIXME: Need to prevent composited layers from drawing over the scroll - // bars. - // FIXME: Sublayers need to be sorted in Z to get the correct transparency effect. + // Enable scissoring to avoid rendering composited layers over the scrollbars. + glEnable(GL_SCISSOR_TEST); + glScissor(0, visibleRect.height() - contentRect.height(), contentRect.width(), contentRect.height()); + // Translate all the composited layers by the scroll position. TransformationMatrix matrix; matrix.translate3d(-m_scrollPosition.x(), -m_scrollPosition.y(), 0); @@ -344,6 +372,8 @@ void LayerRendererChromium::drawLayers(const IntRect& updateRect, const IntRect& for (size_t i = 0; i < sublayers.size(); i++) compositeLayersRecursive(sublayers[i].get(), matrix, opacity, visibleRect); + glDisable(GL_SCISSOR_TEST); + glFlush(); m_gles2Context->swapBuffers(); @@ -363,13 +393,15 @@ int LayerRendererChromium::getTextureId(LayerChromium* layer) // Allocates a new texture for the layer and registers it in the textureId map. // FIXME: We will need to come up with a more sophisticated allocation strategy here. -// FIXME: We need to free up the associated texture upon layer destruction. int LayerRendererChromium::assignTextureForLayer(LayerChromium* layer) { GLuint textureId = createLayerTexture(); // FIXME: Check that textureId is valid m_textureIdMap.set(layer, textureId); + + layer->setLayerRenderer(this); + return textureId; } @@ -491,40 +523,7 @@ void LayerRendererChromium::compositeLayersRecursive(LayerChromium* layer, const // Update the contents of the layer before taking a snapshot. For layers that // are simply containers, the following call just clears the dirty flag but doesn't // actually do any draws/copies. - layer->updateContents(); - - const SkBitmap* skiaBitmap = 0; - void* pixels = 0; - if (layer->drawsContent()) { // Layer has its own GraphicsContext. - // The contents of the layer are stored in the canvas associated with it. - const SkBitmap& bitmap = layer->platformCanvas()->getDevice()->accessBitmap(false); - skiaBitmap = &bitmap; - } else { // Layer is a container. - // The layer contains an Image. - NativeImageSkia* skiaImage = static_cast<NativeImageSkia*>(layer->contents()); - skiaBitmap = skiaImage; - } - - ASSERT(skiaBitmap); - SkBitmap::Config skiaConfig = skiaBitmap->config(); - // FIXME: must support more image configurations. - if (skiaConfig == SkBitmap::kARGB_8888_Config) { - SkAutoLockPixels lock(*skiaBitmap); - int bitmapWidth = skiaBitmap->width(); - int bitmapHeight = skiaBitmap->height(); - int rowBytes = skiaBitmap->rowBytes(); - ASSERT(rowBytes == bitmapWidth * 4); - - // Copy the layer contents into the texture. - glBindTexture(GL_TEXTURE_2D, textureId); - void* pixels = skiaBitmap->getPixels(); - if (pixels) { - // FIXME. We can be smart here and call glTexSubImage2D if the new bitmap has the same - // size as the old one which will save us one unecessary allocation / deallocation. - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, bitmapWidth, bitmapHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels); - checkGLError(); - } - } + layer->updateTextureContents(textureId); } if (layer->doubleSided()) diff --git a/WebCore/platform/graphics/chromium/LayerRendererChromium.h b/WebCore/platform/graphics/chromium/LayerRendererChromium.h index 498678e..eb66dac 100644 --- a/WebCore/platform/graphics/chromium/LayerRendererChromium.h +++ b/WebCore/platform/graphics/chromium/LayerRendererChromium.h @@ -69,6 +69,10 @@ public: bool hardwareCompositing() const { return m_hardwareCompositing; } + void setRootLayerCanvasSize(const IntSize&); + + GraphicsContext* rootLayerGraphicsContext() const { return m_rootLayerGraphicsContext.get(); } + private: void compositeLayersRecursive(LayerChromium*, const TransformationMatrix&, float opacity, const IntRect& visibleRect); @@ -124,6 +128,13 @@ private: typedef HashMap<LayerChromium*, unsigned int> TextureIdMap; TextureIdMap m_textureIdMap; +#if PLATFORM(SKIA) + OwnPtr<skia::PlatformCanvas> m_rootLayerCanvas; + OwnPtr<PlatformContextSkia> m_rootLayerSkiaContext; + OwnPtr<GraphicsContext> m_rootLayerGraphicsContext; +#endif + IntSize m_rootLayerCanvasSize; + OwnPtr<GLES2Context> m_gles2Context; // The WebCore Page that the compositor renders into. diff --git a/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.cpp b/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.cpp index d619e14..7e6b71a 100644 --- a/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.cpp +++ b/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.cpp @@ -195,7 +195,7 @@ void mediaPlayerPrivateMuteChangedCallback(GObject *element, GParamSpec *pspec, static float playbackPosition(GstElement* playbin) { - float ret = 0.0; + float ret = 0.0f; GstQuery* query = gst_query_new_position(GST_FORMAT_TIME); if (!gst_element_query(playbin, query)) { @@ -417,10 +417,10 @@ void MediaPlayerPrivateGStreamer::pause() float MediaPlayerPrivateGStreamer::duration() const { if (!m_playBin) - return 0.0; + return 0.0f; if (m_errorOccured) - return 0.0; + return 0.0f; // Media duration query failed already, don't attempt new useless queries. if (!m_mediaDurationKnown) @@ -446,13 +446,13 @@ float MediaPlayerPrivateGStreamer::duration() const float MediaPlayerPrivateGStreamer::currentTime() const { if (!m_playBin) - return 0; + return 0.0f; if (m_errorOccured) - return 0; + return 0.0f; if (m_seeking) - return m_seekTime; + return static_cast<float>(m_seekTime); return playbackPosition(m_playBin); @@ -470,7 +470,7 @@ void MediaPlayerPrivateGStreamer::seek(float time) if (m_errorOccured) return; - GstClockTime sec = (GstClockTime)(time * GST_SECOND); + GstClockTime sec = (GstClockTime)(static_cast<float>(time * GST_SECOND)); LOG_VERBOSE(Media, "Seek: %" GST_TIME_FORMAT, GST_TIME_ARGS(sec)); if (!gst_element_seek(m_playBin, m_player->rate(), GST_FORMAT_TIME, @@ -519,7 +519,7 @@ IntSize MediaPlayerPrivateGStreamer::naturalSize() const if (!pad) return IntSize(); - int width = 0, height = 0; + guint64 width = 0, height = 0; GstCaps* caps = GST_PAD_CAPS(pad); int pixelAspectRatioNumerator, pixelAspectRatioDenominator; int displayWidth, displayHeight, displayAspectRatioGCD; @@ -557,19 +557,19 @@ IntSize MediaPlayerPrivateGStreamer::naturalSize() const if (!(originalHeight % displayHeight)) { LOG_VERBOSE(Media, "Keeping video original height"); width = gst_util_uint64_scale_int(originalHeight, displayWidth, displayHeight); - height = originalHeight; + height = static_cast<guint64>(originalHeight); } else if (!(originalWidth % displayWidth)) { LOG_VERBOSE(Media, "Keeping video original width"); height = gst_util_uint64_scale_int(originalWidth, displayHeight, displayWidth); - width = originalWidth; + width = static_cast<guint64>(originalWidth); } else { LOG_VERBOSE(Media, "Approximating while keeping original video height"); width = gst_util_uint64_scale_int(originalHeight, displayWidth, displayHeight); - height = originalHeight; + height = static_cast<guint64>(originalHeight); } - LOG_VERBOSE(Media, "Natural size: %dx%d", width, height); - return IntSize(width, height); + LOG_VERBOSE(Media, "Natural size: %" G_GUINT64_FORMAT "x%" G_GUINT64_FORMAT, width, height); + return IntSize(static_cast<int>(width), static_cast<int>(height)); } bool MediaPlayerPrivateGStreamer::hasVideo() const @@ -628,7 +628,7 @@ void MediaPlayerPrivateGStreamer::setRate(float rate) m_playbackRate = rate; m_changingRate = true; - float currentPosition = playbackPosition(m_playBin) * GST_SECOND; + float currentPosition = static_cast<float>(playbackPosition(m_playBin) * GST_SECOND); GstSeekFlags flags = (GstSeekFlags)(GST_SEEK_FLAG_FLUSH); gint64 start, end; bool mute = false; @@ -647,7 +647,7 @@ void MediaPlayerPrivateGStreamer::setRate(float rate) // If we are at beginning of media, start from the end to // avoid immediate EOS. if (currentPosition <= 0) - end = duration() * GST_SECOND; + end = static_cast<gint64>(duration() * GST_SECOND); else end = currentPosition; } @@ -761,12 +761,12 @@ void MediaPlayerPrivateGStreamer::fillTimerFired(Timer<MediaPlayerPrivateGStream float MediaPlayerPrivateGStreamer::maxTimeSeekable() const { if (m_errorOccured) - return 0.0; + return 0.0f; LOG_VERBOSE(Media, "maxTimeSeekable"); // infinite duration means live stream if (isinf(duration())) - return 0.0; + return 0.0f; return maxTimeLoaded(); } @@ -774,7 +774,7 @@ float MediaPlayerPrivateGStreamer::maxTimeSeekable() const float MediaPlayerPrivateGStreamer::maxTimeLoaded() const { if (m_errorOccured) - return 0.0; + return 0.0f; float loaded = m_maxTimeLoaded; if (!loaded && !m_fillTimer.isActive()) @@ -809,7 +809,7 @@ unsigned MediaPlayerPrivateGStreamer::totalBytes() const gst_element_query_duration(m_source, &fmt, &length); LOG_VERBOSE(Media, "totalBytes %" G_GINT64_FORMAT, length); - return length; + return static_cast<unsigned>(length); } void MediaPlayerPrivateGStreamer::cancelLoad() diff --git a/WebCore/platform/graphics/gstreamer/WebKitWebSourceGStreamer.cpp b/WebCore/platform/graphics/gstreamer/WebKitWebSourceGStreamer.cpp index daee506..c55f7bf 100644 --- a/WebCore/platform/graphics/gstreamer/WebKitWebSourceGStreamer.cpp +++ b/WebCore/platform/graphics/gstreamer/WebKitWebSourceGStreamer.cpp @@ -388,10 +388,6 @@ static bool webKitWebSrcStart(WebKitWebSrc* src) request.setTargetType(ResourceRequestBase::TargetIsMedia); request.setAllowCookies(true); - // Let Apple web servers know we want to access their nice movie trailers. - if (!g_ascii_strcasecmp("movies.apple.com", url.host().utf8().data())) - request.setHTTPUserAgent("Quicktime/7.2.0"); - if (priv->frame) { Document* document = priv->frame->document(); if (document) @@ -402,6 +398,11 @@ static bool webKitWebSrcStart(WebKitWebSrc* src) loader->addExtraFieldsToSubresourceRequest(request); } + // Let Apple web servers know we want to access their nice movie trailers. + if (!g_ascii_strcasecmp("movies.apple.com", url.host().utf8().data()) + || !g_ascii_strcasecmp("trailers.apple.com", url.host().utf8().data())) + request.setHTTPUserAgent("Quicktime/7.6.6"); + if (priv->requestedOffset) { GOwnPtr<gchar> val; diff --git a/WebCore/platform/graphics/haiku/ImageBufferHaiku.cpp b/WebCore/platform/graphics/haiku/ImageBufferHaiku.cpp index 44943d7..fdab656 100644 --- a/WebCore/platform/graphics/haiku/ImageBufferHaiku.cpp +++ b/WebCore/platform/graphics/haiku/ImageBufferHaiku.cpp @@ -1,5 +1,6 @@ /* * Copyright (C) 2010 Stephan AĂŸmus <superstippi@gmx.de> + * Copyright (C) 2010 Torch Mobile (Beijing) Co. Ltd. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -309,7 +310,7 @@ void ImageBuffer::putPremultipliedImageData(ImageData* source, const IntRect& so putImageData(source, sourceRect, destPoint, m_data, m_size, true); } -String ImageBuffer::toDataURL(const String& mimeType) const +String ImageBuffer::toDataURL(const String& mimeType, double) const { if (!MIMETypeRegistry::isSupportedImageMIMETypeForEncoding(mimeType)) return "data:,"; diff --git a/WebCore/platform/graphics/mac/GraphicsContext3DMac.cpp b/WebCore/platform/graphics/mac/GraphicsContext3DMac.cpp index 80c0d03..79a10dd 100644 --- a/WebCore/platform/graphics/mac/GraphicsContext3DMac.cpp +++ b/WebCore/platform/graphics/mac/GraphicsContext3DMac.cpp @@ -321,15 +321,53 @@ void GraphicsContext3D::reshape(int width, int height) notImplemented(); } - if (mustRestoreFBO) - ::glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_boundFBO); + if (m_attrs.antialias) { + ::glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_multisampleFBO); + if (m_boundFBO == m_multisampleFBO) + mustRestoreFBO = false; + } - GLenum clearMask = GL_COLOR_BUFFER_BIT; - if (m_attrs.depth) + // Initialize renderbuffers to 0. + GLboolean colorMask[] = {GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE}, depthMask = GL_TRUE, stencilMask = GL_TRUE; + GLboolean isScissorEnabled = GL_FALSE; + GLboolean isDitherEnabled = GL_FALSE; + GLbitfield clearMask = GL_COLOR_BUFFER_BIT; + ::glGetBooleanv(GL_COLOR_WRITEMASK, colorMask); + ::glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); + if (m_attrs.depth) { + ::glGetBooleanv(GL_DEPTH_WRITEMASK, &depthMask); + ::glDepthMask(GL_TRUE); clearMask |= GL_DEPTH_BUFFER_BIT; - if (m_attrs.stencil) + } + if (m_attrs.stencil) { + ::glGetBooleanv(GL_STENCIL_WRITEMASK, &stencilMask); + ::glStencilMask(GL_TRUE); clearMask |= GL_STENCIL_BUFFER_BIT; + } + isScissorEnabled = ::glIsEnabled(GL_SCISSOR_TEST); + ::glDisable(GL_SCISSOR_TEST); + isDitherEnabled = ::glIsEnabled(GL_DITHER); + ::glDisable(GL_DITHER); + ::glClear(clearMask); + + ::glColorMask(colorMask[0], colorMask[1], colorMask[2], colorMask[3]); + if (m_attrs.depth) + ::glDepthMask(depthMask); + if (m_attrs.stencil) + ::glStencilMask(stencilMask); + if (isScissorEnabled) + ::glEnable(GL_SCISSOR_TEST); + else + ::glDisable(GL_SCISSOR_TEST); + if (isDitherEnabled) + ::glEnable(GL_DITHER); + else + ::glDisable(GL_DITHER); + + if (mustRestoreFBO) + ::glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_boundFBO); + ::glFlush(); } diff --git a/WebCore/platform/graphics/mac/SimpleFontDataMac.mm b/WebCore/platform/graphics/mac/SimpleFontDataMac.mm index 7f1a72e..04badbe 100644 --- a/WebCore/platform/graphics/mac/SimpleFontDataMac.mm +++ b/WebCore/platform/graphics/mac/SimpleFontDataMac.mm @@ -265,14 +265,19 @@ void SimpleFontData::platformInit() GlyphPage* glyphPageZero = GlyphPageTreeNode::getRootChild(this, 0)->page(); NSGlyph xGlyph = glyphPageZero ? glyphPageZero->glyphDataForCharacter('x').glyph : 0; if (xGlyph) { - NSRect xBox = [m_platformData.font() boundingRectForGlyph:xGlyph]; + CGRect xBox = platformBoundsForGlyph(xGlyph); // Use the maximum of either width or height because "x" is nearly square // and web pages that foolishly use this metric for width will be laid out // poorly if we return an accurate height. Classic case is Times 13 point, // which has an "x" that is 7x6 pixels. - m_xHeight = max(NSMaxX(xBox), NSMaxY(xBox)); - } else - m_xHeight = [m_platformData.font() xHeight]; + m_xHeight = static_cast<float>(max(CGRectGetMaxX(xBox), CGRectGetMaxY(xBox))); + } else { +#ifndef BUILDING_ON_TIGER + m_xHeight = static_cast<float>(CGFontGetXHeight(m_platformData.cgFont())) / m_unitsPerEm; +#else + m_xHeight = m_platformData.font() ? [m_platformData.font() xHeight] : 0; +#endif + } } static CFDataRef copyFontTableForTag(FontPlatformData platformData, FourCharCode tableName) @@ -417,11 +422,15 @@ FloatRect SimpleFontData::platformBoundsForGlyph(Glyph glyph) const float pointSize = platformData().m_size; CGFloat scale = pointSize / unitsPerEm(); boundingBox = CGRectApplyAffineTransform(box, CGAffineTransformMakeScale(scale, -scale)); - if (m_syntheticBoldOffset) - boundingBox.setWidth(boundingBox.width() + m_syntheticBoldOffset); #else - UNUSED_PARAM(glyph); + // FIXME: Custom fonts don't have NSFonts, so this function doesn't compute correct bounds for these on Tiger. + if (!m_platformData.font()) + return boundingBox; + boundingBox = [m_platformData.font() boundingRectForGlyph:glyph]; #endif + if (m_syntheticBoldOffset) + boundingBox.setWidth(boundingBox.width() + m_syntheticBoldOffset); + return boundingBox; } diff --git a/WebCore/platform/graphics/qt/FontQt.cpp b/WebCore/platform/graphics/qt/FontQt.cpp index 946faeb..2009424 100644 --- a/WebCore/platform/graphics/qt/FontQt.cpp +++ b/WebCore/platform/graphics/qt/FontQt.cpp @@ -73,28 +73,31 @@ void Font::drawComplexText(GraphicsContext* ctx, const TextRun& run, const Float QPainter *p = ctx->platformContext(); + QPen textFillPen; if (ctx->textDrawingMode() & cTextFill) { if (ctx->fillGradient()) { QBrush brush(*ctx->fillGradient()->platformGradient()); brush.setTransform(ctx->fillGradient()->gradientSpaceTransform()); - p->setPen(QPen(brush, 0)); + textFillPen = QPen(brush, 0); } else if (ctx->fillPattern()) { AffineTransform affine; - p->setPen(QPen(QBrush(ctx->fillPattern()->createPlatformPattern(affine)), 0)); + textFillPen = QPen(QBrush(ctx->fillPattern()->createPlatformPattern(affine)), 0); } else - p->setPen(QColor(ctx->fillColor())); + textFillPen = QPen(QColor(ctx->fillColor())); } + QPen textStrokePen; if (ctx->textDrawingMode() & cTextStroke) { if (ctx->strokeGradient()) { QBrush brush(*ctx->strokeGradient()->platformGradient()); brush.setTransform(ctx->strokeGradient()->gradientSpaceTransform()); - p->setPen(QPen(brush, ctx->strokeThickness())); + textStrokePen = QPen(brush, ctx->strokeThickness()); } else if (ctx->strokePattern()) { AffineTransform affine; - p->setPen(QPen(QBrush(ctx->strokePattern()->createPlatformPattern(affine)), ctx->strokeThickness())); + QBrush brush(ctx->strokePattern()->createPlatformPattern(affine)); + textStrokePen = QPen(brush, ctx->strokeThickness()); } else - p->setPen(QPen(QColor(ctx->strokeColor()), ctx->strokeThickness())); + textStrokePen = QPen(QColor(ctx->strokeColor()), ctx->strokeThickness()); } String sanitized = Font::normalizeSpaces(String(run.characters(), run.length())); @@ -163,10 +166,13 @@ void Font::drawComplexText(GraphicsContext* ctx, const TextRun& run, const Float if (ctx->textDrawingMode() & cTextStroke) { QPainterPath path; path.addText(pt, font(), string); + p->setPen(textStrokePen); p->strokePath(path, p->pen()); } - if (ctx->textDrawingMode() & cTextFill) + if (ctx->textDrawingMode() & cTextFill) { + p->setPen(textFillPen); p->drawText(pt, string, flags, run.padding()); + } } float Font::floatWidthForComplexText(const TextRun& run, HashSet<const SimpleFontData*>*, GlyphOverflow*) const diff --git a/WebCore/platform/graphics/qt/GraphicsContextQt.cpp b/WebCore/platform/graphics/qt/GraphicsContextQt.cpp index 69121c8..bdb810a 100644 --- a/WebCore/platform/graphics/qt/GraphicsContextQt.cpp +++ b/WebCore/platform/graphics/qt/GraphicsContextQt.cpp @@ -173,7 +173,7 @@ struct TransparencyLayer : FastAllocBase { , alphaMask(alphaMask) , saveCounter(1) // see the comment for saveCounter { - offset = p->transform().mapRect(rect).topLeft(); + offset = rect.topLeft(); pixmap.fill(Qt::transparent); painter.begin(&pixmap); painter.setRenderHint(QPainter::Antialiasing, p->testRenderHint(QPainter::Antialiasing)); @@ -1125,7 +1125,7 @@ void GraphicsContext::clipToImageBuffer(const FloatRect& floatRect, const ImageB if (alphaMask.width() != rect.width() || alphaMask.height() != rect.height()) alphaMask = alphaMask.scaled(rect.width(), rect.height()); - m_data->layers.push(new TransparencyLayer(m_data->p(), rect, 1.0, alphaMask)); + m_data->layers.push(new TransparencyLayer(m_data->p(), m_data->p()->transform().mapRect(rect), 1.0, alphaMask)); } void GraphicsContext::addInnerRoundedRectClip(const IntRect& rect, diff --git a/WebCore/platform/graphics/qt/GraphicsLayerQt.cpp b/WebCore/platform/graphics/qt/GraphicsLayerQt.cpp index 9f36b2a..be54735 100644 --- a/WebCore/platform/graphics/qt/GraphicsLayerQt.cpp +++ b/WebCore/platform/graphics/qt/GraphicsLayerQt.cpp @@ -1361,13 +1361,14 @@ public: if (m_fillsForwards) setCurrentTime(1); } + virtual void applyFrame(const qreal& fromValue, const qreal& toValue, qreal progress) { qreal opacity = qBound(qreal(0), fromValue + (toValue - fromValue) * progress, qreal(1)); // FIXME: This is a hack, due to a probable QGraphicsScene bug. // Without this the opacity change doesn't always have immediate effect. - if (!m_layer.data()->opacity() && opacity) + if (m_layer.data()->scene() && !m_layer.data()->opacity() && opacity) m_layer.data()->scene()->update(); m_layer.data()->m_layer->setOpacity(opacity); diff --git a/WebCore/platform/graphics/qt/ImageBufferQt.cpp b/WebCore/platform/graphics/qt/ImageBufferQt.cpp index 4245ee5..bee15f2 100644 --- a/WebCore/platform/graphics/qt/ImageBufferQt.cpp +++ b/WebCore/platform/graphics/qt/ImageBufferQt.cpp @@ -2,6 +2,7 @@ * Copyright (C) 2006 Nikolas Zimmermann <zimmermann@kde.org> * Copyright (C) 2008 Holger Hans Peter Freyther * Copyright (C) 2009 Dirk Schulze <krit@webkit.org> + * Copyright (C) 2010 Torch Mobile (Beijing) Co. Ltd. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -275,9 +276,10 @@ void ImageBuffer::putPremultipliedImageData(ImageData* source, const IntRect& so // We get a mimeType here but QImageWriter does not support mimetypes but // only formats (png, gif, jpeg..., xpm). So assume we get image/ as image // mimetypes and then remove the image/ to get the Qt format. -String ImageBuffer::toDataURL(const String& mimeType) const +String ImageBuffer::toDataURL(const String& mimeType, double quality) const { ASSERT(MIMETypeRegistry::isSupportedImageMIMETypeForEncoding(mimeType)); + ASSERT(0.0 <= quality && quality <= 1.0); if (!mimeType.startsWith("image/")) return "data:,"; @@ -287,8 +289,10 @@ String ImageBuffer::toDataURL(const String& mimeType) const QBuffer buffer(&data); buffer.open(QBuffer::WriteOnly); - if (!m_data.m_pixmap.save(&buffer, mimeType.substring(sizeof "image").utf8().data())) + if (!m_data.m_pixmap.save(&buffer, mimeType.substring(sizeof "image").utf8().data(), quality * 100 + 0.5)) { + buffer.close(); return "data:,"; + } buffer.close(); return String::format("data:%s;base64,%s", mimeType.utf8().data(), data.toBase64().data()); diff --git a/WebCore/platform/graphics/qt/ImageDecoderQt.cpp b/WebCore/platform/graphics/qt/ImageDecoderQt.cpp index a8110ca..cc707da 100644 --- a/WebCore/platform/graphics/qt/ImageDecoderQt.cpp +++ b/WebCore/platform/graphics/qt/ImageDecoderQt.cpp @@ -115,24 +115,8 @@ size_t ImageDecoderQt::frameCount() int ImageDecoderQt::repetitionCount() const { - if (m_reader && m_reader->supportsAnimation()) { + if (m_reader && m_reader->supportsAnimation()) m_repetitionCount = m_reader->loopCount(); - - // Qt and WebCore have a incompatible understanding of - // the loop count and we can not completely map everything. - // Qt | WebCore | description - // -1 | 0 | infinite animation - // 0 | cAnimationLoopOnce | show every frame once - // n | n+1 | Qt returns the # of iterations - 1 - // n/a | cAnimationNone | show only the first frame - if (m_repetitionCount == -1) - m_repetitionCount = 0; - else if (m_repetitionCount == 0) - m_repetitionCount = cAnimationLoopOnce; - else - ++m_repetitionCount; - } - return m_repetitionCount; } diff --git a/WebCore/platform/graphics/skia/GraphicsContextSkia.cpp b/WebCore/platform/graphics/skia/GraphicsContextSkia.cpp index e16b373..9de21e0 100644 --- a/WebCore/platform/graphics/skia/GraphicsContextSkia.cpp +++ b/WebCore/platform/graphics/skia/GraphicsContextSkia.cpp @@ -875,9 +875,9 @@ void GraphicsContext::setCompositeOperation(CompositeOperator op) platformContext()->setXfermodeMode(WebCoreCompositeToSkiaComposite(op)); } -void GraphicsContext::setImageInterpolationQuality(InterpolationQuality) +void GraphicsContext::setImageInterpolationQuality(InterpolationQuality q) { - notImplemented(); + platformContext()->setInterpolationQuality(q); } void GraphicsContext::setLineCap(LineCap cap) diff --git a/WebCore/platform/graphics/skia/ImageBufferSkia.cpp b/WebCore/platform/graphics/skia/ImageBufferSkia.cpp index 4ea3d7a..1b03694 100644 --- a/WebCore/platform/graphics/skia/ImageBufferSkia.cpp +++ b/WebCore/platform/graphics/skia/ImageBufferSkia.cpp @@ -1,6 +1,7 @@ /* * Copyright (c) 2008, Google Inc. All rights reserved. * Copyright (C) 2009 Dirk Schulze <krit@webkit.org> + * Copyright (C) 2010 Torch Mobile (Beijing) Co. Ltd. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are @@ -260,7 +261,7 @@ void ImageBuffer::putPremultipliedImageData(ImageData* source, const IntRect& so putImageData<Premultiplied>(source, sourceRect, destPoint, *context()->platformContext()->bitmap(), m_size); } -String ImageBuffer::toDataURL(const String&) const +String ImageBuffer::toDataURL(const String&, double) const { // Encode the image into a vector. Vector<unsigned char> pngEncodedData; diff --git a/WebCore/platform/graphics/skia/ImageSkia.cpp b/WebCore/platform/graphics/skia/ImageSkia.cpp index 21ba934..d1fb647 100644 --- a/WebCore/platform/graphics/skia/ImageSkia.cpp +++ b/WebCore/platform/graphics/skia/ImageSkia.cpp @@ -64,7 +64,7 @@ enum ResamplingMode { RESAMPLE_AWESOME, }; -static ResamplingMode computeResamplingMode(const NativeImageSkia& bitmap, int srcWidth, int srcHeight, float destWidth, float destHeight) +static ResamplingMode computeResamplingMode(PlatformContextSkia* platformContext, const NativeImageSkia& bitmap, int srcWidth, int srcHeight, float destWidth, float destHeight) { int destIWidth = static_cast<int>(destWidth); int destIHeight = static_cast<int>(destHeight); @@ -130,7 +130,11 @@ static ResamplingMode computeResamplingMode(const NativeImageSkia& bitmap, int s return RESAMPLE_LINEAR; // Everything else gets resampled. - return RESAMPLE_AWESOME; + // If the platform context permits high quality interpolation, use it. + if (platformContext->interpolationQuality() == InterpolationHigh) + return RESAMPLE_AWESOME; + + return RESAMPLE_LINEAR; } // Draws the given bitmap to the given canvas. The subset of the source bitmap @@ -184,7 +188,7 @@ static void drawResampledBitmap(SkCanvas& canvas, SkPaint& paint, const NativeIm if (!destBitmapSubsetSkI.intersect(resizedImageRect)) return; // Resized image does not intersect. - if (srcIsFull && bitmap.shouldCacheResampling( + if (srcIsFull || bitmap.shouldCacheResampling( resizedImageRect.width(), resizedImageRect.height(), destBitmapSubsetSkI.width(), @@ -230,7 +234,7 @@ static void paintSkBitmap(PlatformContextSkia* platformContext, const NativeImag skia::PlatformCanvas* canvas = platformContext->canvas(); ResamplingMode resampling = platformContext->isPrinting() ? RESAMPLE_NONE : - computeResamplingMode(bitmap, srcRect.width(), srcRect.height(), + computeResamplingMode(platformContext, bitmap, srcRect.width(), srcRect.height(), SkScalarToFloat(destRect.width()), SkScalarToFloat(destRect.height())); if (resampling == RESAMPLE_AWESOME) { @@ -336,7 +340,7 @@ void Image::drawPattern(GraphicsContext* context, if (context->platformContext()->isPrinting()) resampling = RESAMPLE_LINEAR; else { - resampling = computeResamplingMode(*bitmap, + resampling = computeResamplingMode(context->platformContext(), *bitmap, srcRect.width(), srcRect.height(), destBitmapWidth, destBitmapHeight); } diff --git a/WebCore/platform/graphics/skia/PlatformContextSkia.cpp b/WebCore/platform/graphics/skia/PlatformContextSkia.cpp index e0f6f5d..7ec403c 100644 --- a/WebCore/platform/graphics/skia/PlatformContextSkia.cpp +++ b/WebCore/platform/graphics/skia/PlatformContextSkia.cpp @@ -99,6 +99,7 @@ struct PlatformContextSkia::State { // This is a list of clipping paths which are currently active, in the // order in which they were pushed. WTF::Vector<SkPath> m_antiAliasClipPaths; + WebCore::InterpolationQuality m_interpolationQuality; private: // Not supported. @@ -123,6 +124,7 @@ PlatformContextSkia::State::State() , m_lineJoin(SkPaint::kDefault_Join) , m_dash(0) , m_textDrawingMode(WebCore::cTextFill) + , m_interpolationQuality(WebCore::InterpolationHigh) { } @@ -147,6 +149,7 @@ PlatformContextSkia::State::State(const State& other) , m_imageBufferClip(other.m_imageBufferClip) , m_clip(other.m_clip) #endif + , m_interpolationQuality(other.m_interpolationQuality) { // Up the ref count of these. saveRef does nothing if 'this' is NULL. m_looper->safeRef(); @@ -539,6 +542,16 @@ void PlatformContextSkia::setFillShader(SkShader* fillShader) } } +WebCore::InterpolationQuality PlatformContextSkia::interpolationQuality() const +{ + return m_state->m_interpolationQuality; +} + +void PlatformContextSkia::setInterpolationQuality(WebCore::InterpolationQuality interpolationQuality) +{ + m_state->m_interpolationQuality = interpolationQuality; +} + void PlatformContextSkia::setDashPathEffect(SkDashPathEffect* dash) { if (dash != m_state->m_dash) { diff --git a/WebCore/platform/graphics/skia/PlatformContextSkia.h b/WebCore/platform/graphics/skia/PlatformContextSkia.h index e445262..2f24646 100644 --- a/WebCore/platform/graphics/skia/PlatformContextSkia.h +++ b/WebCore/platform/graphics/skia/PlatformContextSkia.h @@ -147,6 +147,9 @@ public: skia::PlatformCanvas* canvas() { return m_canvas; } + WebCore::InterpolationQuality interpolationQuality() const; + void setInterpolationQuality(WebCore::InterpolationQuality interpolationQuality); + // FIXME: This should be pushed down to GraphicsContext. void drawRect(SkRect rect); diff --git a/WebCore/platform/graphics/win/MediaPlayerPrivateFullscreenWindow.cpp b/WebCore/platform/graphics/win/MediaPlayerPrivateFullscreenWindow.cpp new file mode 100644 index 0000000..c6be087 --- /dev/null +++ b/WebCore/platform/graphics/win/MediaPlayerPrivateFullscreenWindow.cpp @@ -0,0 +1,182 @@ +/* + * Copyright (C) 2010 Apple 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" +#include "MediaPlayerPrivateFullscreenWindow.h" + +#include "IntRect.h" +#include "WebCoreInstanceHandle.h" +#include <CoreGraphics/CGColor.h> +#include <windows.h> + +namespace WebCore { + +MediaPlayerPrivateFullscreenWindow::MediaPlayerPrivateFullscreenWindow(MediaPlayerPrivateFullscreenClient* client) + : m_client(client) + , m_hwnd(0) +#if USE(ACCELERATED_COMPOSITING) + , m_layerRenderer(WKCACFLayerRenderer::create(0)) +#endif +{ +} + +MediaPlayerPrivateFullscreenWindow::~MediaPlayerPrivateFullscreenWindow() +{ + if (m_hwnd) + close(); +} + +void MediaPlayerPrivateFullscreenWindow::createWindow(HWND parentHwnd) +{ + static ATOM windowAtom; + static LPCWSTR windowClassName = L"MediaPlayerPrivateFullscreenWindowClass"; + if (!windowAtom) { + WNDCLASSEX wcex = {0}; + wcex.cbSize = sizeof(WNDCLASSEX); + wcex.style = CS_HREDRAW | CS_VREDRAW; + wcex.lpfnWndProc = staticWndProc; + wcex.hInstance = instanceHandle(); + wcex.lpszClassName = windowClassName; + windowAtom = ::RegisterClassEx(&wcex); + } + + if (m_hwnd) + close(); + + MONITORINFO mi = {0}; + mi.cbSize = sizeof(MONITORINFO); + if (!GetMonitorInfo(MonitorFromWindow(parentHwnd, MONITOR_DEFAULTTONEAREST), &mi)) + return; + + IntRect monitorRect = mi.rcMonitor; + + ::CreateWindowExW(WS_EX_TOOLWINDOW, windowClassName, L"", WS_POPUP | WS_VISIBLE, + monitorRect.x(), monitorRect.y(), monitorRect.width(), monitorRect.height(), + parentHwnd, 0, WebCore::instanceHandle(), this); + ASSERT(IsWindow(m_hwnd)); + + ::SetFocus(m_hwnd); +} + +void MediaPlayerPrivateFullscreenWindow::close() +{ + ::DestroyWindow(m_hwnd); + ASSERT(!m_hwnd); +} + +#if USE(ACCELERATED_COMPOSITING) +void MediaPlayerPrivateFullscreenWindow::setRootChildLayer(PassRefPtr<WKCACFLayer> rootChild) +{ + if (m_rootChild == rootChild) + return; + + if (m_rootChild) + m_rootChild->removeFromSuperlayer(); + + m_rootChild = rootChild; + + if (!m_rootChild) + return; + + m_layerRenderer->setRootChildLayer(m_rootChild.get()); + WKCACFLayer* rootLayer = m_rootChild->rootLayer(); + CGRect rootBounds = m_rootChild->rootLayer()->bounds(); + m_rootChild->setFrame(rootBounds); + m_layerRenderer->setScrollFrame(IntPoint(rootBounds.origin), IntSize(rootBounds.size)); + m_rootChild->setBackgroundColor(CGColorGetConstantColor(kCGColorBlack)); +#ifndef NDEBUG + RetainPtr<CGColorRef> redColor(AdoptCF, CGColorCreateGenericRGB(1, 0, 0, 1)); + rootLayer->setBackgroundColor(redColor.get()); +#else + rootLayer->setBackgroundColor(CGColorGetConstantColor(kCGColorBlack)); +#endif +} +#endif + +LRESULT MediaPlayerPrivateFullscreenWindow::staticWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) +{ + LONG_PTR longPtr = GetWindowLongPtr(hWnd, GWLP_USERDATA); + + if (!longPtr && message == WM_CREATE) { + LPCREATESTRUCT lpcs = reinterpret_cast<LPCREATESTRUCT>(lParam); + longPtr = reinterpret_cast<LONG_PTR>(lpcs->lpCreateParams); + ::SetWindowLongPtr(hWnd, GWLP_USERDATA, longPtr); + } + + if (MediaPlayerPrivateFullscreenWindow* window = reinterpret_cast<MediaPlayerPrivateFullscreenWindow*>(longPtr)) + return window->wndProc(hWnd, message, wParam, lParam); + + return ::DefWindowProc(hWnd, message, wParam, lParam); +} + +LRESULT MediaPlayerPrivateFullscreenWindow::wndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) +{ + LRESULT lResult = 0; + switch (message) { + case WM_CREATE: + m_hwnd = hWnd; +#if USE(ACCELERATED_COMPOSITING) + m_layerRenderer->setHostWindow(m_hwnd); + m_layerRenderer->createRenderer(); + if (m_rootChild) + m_layerRenderer->setNeedsDisplay(); +#endif + break; + case WM_DESTROY: + m_hwnd = 0; +#if USE(ACCELERATED_COMPOSITING) + m_layerRenderer->destroyRenderer(); + m_layerRenderer->setHostWindow(0); +#endif + break; + case WM_WINDOWPOSCHANGED: + { + LPWINDOWPOS wp = reinterpret_cast<LPWINDOWPOS>(lParam); + if (wp->flags & SWP_NOSIZE) + break; +#if USE(ACCELERATED_COMPOSITING) + m_layerRenderer->resize(); + WKCACFLayer* rootLayer = m_rootChild->rootLayer(); + CGRect rootBounds = m_rootChild->rootLayer()->bounds(); + m_rootChild->setFrame(rootBounds); + m_rootChild->setNeedsLayout(); + m_layerRenderer->setScrollFrame(IntPoint(rootBounds.origin), IntSize(rootBounds.size)); +#endif + } + break; + case WM_PAINT: +#if USE(ACCELERATED_COMPOSITING) + m_layerRenderer->renderSoon(); +#endif + break; + } + + if (m_client) + lResult = m_client->fullscreenClientWndProc(hWnd, message, wParam, lParam); + + return lResult; +} + +} diff --git a/WebCore/platform/graphics/win/MediaPlayerPrivateFullscreenWindow.h b/WebCore/platform/graphics/win/MediaPlayerPrivateFullscreenWindow.h new file mode 100644 index 0000000..d42f7f3 --- /dev/null +++ b/WebCore/platform/graphics/win/MediaPlayerPrivateFullscreenWindow.h @@ -0,0 +1,82 @@ +/* + * Copyright (C) 2010 Apple 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 MediaPlayerPrivateFullscreenWindow_h +#define MediaPlayerPrivateFullscreenWindow_h + +#if USE(ACCELERATED_COMPOSITING) +#include "WKCACFLayer.h" +#include "WKCACFLayerRenderer.h" +#endif +#include <wtf/OwnPtr.h> + +typedef unsigned WPARAM; +typedef long LPARAM; +typedef struct HWND__* HWND; +typedef _W64 long LONG_PTR; +typedef LONG_PTR LRESULT; +typedef unsigned int UINT; + +namespace WebCore { + +class MediaPlayerPrivateFullscreenClient { +public: + virtual LRESULT fullscreenClientWndProc(HWND, UINT message, WPARAM, LPARAM) = 0; +protected: + virtual ~MediaPlayerPrivateFullscreenClient() {} +}; + +class MediaPlayerPrivateFullscreenWindow { +public: + MediaPlayerPrivateFullscreenWindow(MediaPlayerPrivateFullscreenClient*); + ~MediaPlayerPrivateFullscreenWindow(); + + void createWindow(HWND ownerWindow); + void close(); + + HWND hwnd() const { return m_hwnd; } + +#if USE(ACCELERATED_COMPOSITING) + WKCACFLayerRenderer* layerRenderer() const { return m_layerRenderer.get(); } + + WKCACFLayer* rootChildLayer() const { return m_rootChild.get(); } + void setRootChildLayer(PassRefPtr<WKCACFLayer>); +#endif + +private: + static LRESULT __stdcall staticWndProc(HWND, UINT message, WPARAM, LPARAM); + LRESULT wndProc(HWND, UINT message, WPARAM, LPARAM); + + MediaPlayerPrivateFullscreenClient* m_client; +#if USE(ACCELERATED_COMPOSITING) + OwnPtr<WKCACFLayerRenderer> m_layerRenderer; + RefPtr<WKCACFLayer> m_rootChild; +#endif + HWND m_hwnd; +}; + +} + +#endif diff --git a/WebCore/platform/graphics/win/MediaPlayerPrivateQuickTimeVisualContext.cpp b/WebCore/platform/graphics/win/MediaPlayerPrivateQuickTimeVisualContext.cpp index e1d457f..aa7bdd4 100644 --- a/WebCore/platform/graphics/win/MediaPlayerPrivateQuickTimeVisualContext.cpp +++ b/WebCore/platform/graphics/win/MediaPlayerPrivateQuickTimeVisualContext.cpp @@ -40,6 +40,7 @@ #include "QTMovieTask.h" #include "QTMovieVisualContext.h" #include "ScrollView.h" +#include "Settings.h" #include "SoftLinking.h" #include "StringBuilder.h" #include "StringHash.h" @@ -56,16 +57,15 @@ #if USE(ACCELERATED_COMPOSITING) #include "GraphicsLayerCACF.h" #include "WKCACFLayer.h" +#include "WKCAImageQueue.h" #endif using namespace std; -const CFStringRef kMinQuartzCoreVersion = CFSTR("1.0.43.0"); -const CFStringRef kMinCoreVideoVersion = CFSTR("1.0.0.2"); - namespace WebCore { static CGImageRef CreateCGImageFromPixelBuffer(QTPixelBuffer buffer); +static bool requiredDllsAvailable(); SOFT_LINK_LIBRARY(Wininet) SOFT_LINK(Wininet, InternetSetCookieExW, DWORD, WINAPI, (LPCWSTR lpszUrl, LPCWSTR lpszCookieName, LPCWSTR lpszCookieData, DWORD dwFlags, DWORD_PTR dwReserved), (lpszUrl, lpszCookieName, lpszCookieData, dwFlags, dwReserved)) @@ -144,12 +144,16 @@ MediaPlayerPrivateQuickTimeVisualContext::MediaPlayerPrivateQuickTimeVisualConte MediaPlayerPrivateQuickTimeVisualContext::~MediaPlayerPrivateQuickTimeVisualContext() { tearDownVideoRendering(); - m_visualContext->setMovie(0); cancelCallOnMainThread(&VisualContextClient::retrieveCurrentImageProc, this); } bool MediaPlayerPrivateQuickTimeVisualContext::supportsFullscreen() const { +#if USE(ACCELERATED_COMPOSITING) + Document* document = m_player->mediaPlayerClient()->mediaPlayerOwningDocument(); + if (document && document->settings()) + return document->settings()->acceleratedCompositingEnabled(); +#endif return false; } @@ -285,10 +289,6 @@ void MediaPlayerPrivateQuickTimeVisualContext::load(const String& url) m_movie = adoptRef(new QTMovie(m_movieClient.get())); m_movie->load(url.characters(), url.length(), m_player->preservesPitch()); m_movie->setVolume(m_player->volume()); - - CFDictionaryRef options = QTMovieVisualContext::getCGImageOptions(); - m_visualContext = adoptRef(new QTMovieVisualContext(m_visualContextClient.get(), options)); - m_visualContext->setMovie(m_movie.get()); } void MediaPlayerPrivateQuickTimeVisualContext::play() @@ -630,6 +630,14 @@ void MediaPlayerPrivateQuickTimeVisualContext::setVisible(bool visible) void MediaPlayerPrivateQuickTimeVisualContext::paint(GraphicsContext* p, const IntRect& r) { + MediaRenderingMode currentMode = currentRenderingMode(); + + if (currentMode == MediaRenderingNone) + return; + + if (currentMode == MediaRenderingSoftwareRenderer && !m_visualContext) + return; + #if USE(ACCELERATED_COMPOSITING) if (m_qtVideoLayer) return; @@ -756,16 +764,40 @@ void MediaPlayerPrivateQuickTimeVisualContext::retrieveCurrentImage() WKCACFLayer* layer = static_cast<WKCACFLayer*>(m_qtVideoLayer->platformLayer()); - if (!buffer.lockBaseAddress()) { - CFTimeInterval imageTime = QTMovieVisualContext::currentHostTime(); + if (!buffer.lockBaseAddress()) { + if (requiredDllsAvailable()) { + if (!m_imageQueue) { + m_imageQueue = new WKCAImageQueue(buffer.width(), buffer.height(), 30); + m_imageQueue->setFlags(WKCAImageQueue::Fill, WKCAImageQueue::Fill); + layer->setContents(m_imageQueue->get()); + } + + // Debug QuickTime links against a non-Debug version of CoreFoundation, so the + // CFDictionary attached to the CVPixelBuffer cannot be directly passed on into the + // CAImageQueue without being converted to a non-Debug CFDictionary. Additionally, + // old versions of QuickTime used a non-AAS CoreFoundation, so the types are not + // interchangable even in the release case. + RetainPtr<CFDictionaryRef> attachments(AdoptCF, QTCFDictionaryCreateCopyWithDataCallback(kCFAllocatorDefault, buffer.attachments(), &QTCFDictionaryCreateWithDataCallback)); + CFTimeInterval imageTime = QTMovieVisualContext::currentHostTime(); + + m_imageQueue->collect(); + uint64_t imageId = m_imageQueue->registerPixelBuffer(buffer.baseAddress(), buffer.dataSize(), buffer.bytesPerRow(), buffer.width(), buffer.height(), buffer.pixelFormatType(), attachments.get(), 0); + + if (m_imageQueue->insertImage(imageTime, WKCAImageQueue::Buffer, imageId, WKCAImageQueue::Opaque | WKCAImageQueue::Flush, &QTPixelBuffer::imageQueueReleaseCallback, buffer.pixelBufferRef())) { + // Retain the buffer one extra time so it doesn't dissappear before CAImageQueue decides to release it: + QTPixelBuffer::retainCallback(buffer.pixelBufferRef()); + } + + } else { CGImageRef image = CreateCGImageFromPixelBuffer(buffer); layer->setContents(image); CGImageRelease(image); - - buffer.unlockBaseAddress(); - layer->rootLayer()->setNeedsRender(); } + + buffer.unlockBaseAddress(); + layer->rootLayer()->setNeedsRender(); + } } else #endif m_player->repaint(); @@ -794,6 +826,69 @@ static HashSet<String> mimeTypeCache() return typeCache; } +static CFStringRef createVersionStringFromModuleName(LPCWSTR moduleName) +{ + HMODULE module = GetModuleHandleW(moduleName); + if (!module) + return 0; + + wchar_t filePath[MAX_PATH] = {0}; + if (!GetModuleFileNameW(module, filePath, MAX_PATH)) + return 0; + + DWORD versionInfoSize = GetFileVersionInfoSizeW(filePath, 0); + if (!versionInfoSize) + return 0; + + CFStringRef versionString = 0; + void* versionInfo = calloc(versionInfoSize, sizeof(char)); + if (GetFileVersionInfo(filePath, 0, versionInfoSize, versionInfo)) { + VS_FIXEDFILEINFO* fileInfo = 0; + UINT fileInfoLength = 0; + + if (VerQueryValueW(versionInfo, L"\\", reinterpret_cast<LPVOID*>(&fileInfo), &fileInfoLength)) { + versionString = CFStringCreateWithFormat(kCFAllocatorDefault, 0, CFSTR("%d.%d.%d.%d"), + HIWORD(fileInfo->dwFileVersionMS), LOWORD(fileInfo->dwFileVersionMS), + HIWORD(fileInfo->dwFileVersionLS), LOWORD(fileInfo->dwFileVersionLS)); + } + } + free(versionInfo); + + return versionString; +} + +static bool requiredDllsAvailable() +{ + static bool s_prerequisitesChecked = false; + static bool s_prerequisitesSatisfied; + static const CFStringRef kMinQuartzCoreVersion = CFSTR("1.0.42.0"); + static const CFStringRef kMinCoreVideoVersion = CFSTR("1.0.1.0"); + + if (s_prerequisitesChecked) + return s_prerequisitesSatisfied; + s_prerequisitesChecked = true; + s_prerequisitesSatisfied = false; + + CFStringRef quartzCoreString = createVersionStringFromModuleName(L"QuartzCore"); + if (!quartzCoreString) + quartzCoreString = createVersionStringFromModuleName(L"QuartzCore_debug"); + + CFStringRef coreVideoString = createVersionStringFromModuleName(L"CoreVideo"); + if (!coreVideoString) + coreVideoString = createVersionStringFromModuleName(L"CoreVideo_debug"); + + s_prerequisitesSatisfied = (quartzCoreString && coreVideoString + && CFStringCompare(quartzCoreString, kMinQuartzCoreVersion, kCFCompareNumerically) != kCFCompareLessThan + && CFStringCompare(coreVideoString, kMinCoreVideoVersion, kCFCompareNumerically) != kCFCompareLessThan); + + if (quartzCoreString) + CFRelease(quartzCoreString); + if (coreVideoString) + CFRelease(coreVideoString); + + return s_prerequisitesSatisfied; +} + void MediaPlayerPrivateQuickTimeVisualContext::getSupportedTypes(HashSet<String>& types) { types = mimeTypeCache(); @@ -858,7 +953,7 @@ MediaPlayerPrivateQuickTimeVisualContext::MediaRenderingMode MediaPlayerPrivateQ return MediaRenderingMovieLayer; #endif - return MediaRenderingSoftwareRenderer; + return m_visualContext ? MediaRenderingSoftwareRenderer : MediaRenderingNone; } MediaPlayerPrivateQuickTimeVisualContext::MediaRenderingMode MediaPlayerPrivateQuickTimeVisualContext::preferredRenderingMode() const @@ -896,6 +991,10 @@ void MediaPlayerPrivateQuickTimeVisualContext::setUpVideoRendering() if (currentMode == MediaRenderingMovieLayer || preferredMode == MediaRenderingMovieLayer) m_player->mediaPlayerClient()->mediaPlayerRenderingModeChanged(m_player); #endif + + QTMovieVisualContext::Type contextType = requiredDllsAvailable() && preferredMode == MediaRenderingMovieLayer ? QTMovieVisualContext::ConfigureForCAImageQueue : QTMovieVisualContext::ConfigureForCGImage; + m_visualContext = QTMovieVisualContext::create(m_visualContextClient.get(), contextType); + m_visualContext->setMovie(m_movie.get()); } void MediaPlayerPrivateQuickTimeVisualContext::tearDownVideoRendering() @@ -904,12 +1003,14 @@ void MediaPlayerPrivateQuickTimeVisualContext::tearDownVideoRendering() if (m_qtVideoLayer) destroyLayerForMovie(); #endif + + m_visualContext = 0; } bool MediaPlayerPrivateQuickTimeVisualContext::hasSetUpVideoRendering() const { #if USE(ACCELERATED_COMPOSITING) - return m_qtVideoLayer || currentRenderingMode() != MediaRenderingMovieLayer; + return m_qtVideoLayer || (currentRenderingMode() != MediaRenderingMovieLayer && m_visualContext); #else return true; #endif @@ -939,14 +1040,22 @@ void MediaPlayerPrivateQuickTimeVisualContext::createLayerForMovie() #endif // The layer will get hooked up via RenderLayerBacking::updateGraphicsLayerConfiguration(). #endif + + // Fill the newly created layer with image data, so we're not looking at + // an empty layer until the next time a new image is available, which could + // be a long time if we're paused. + if (m_visualContext) + retrieveCurrentImage(); } void MediaPlayerPrivateQuickTimeVisualContext::destroyLayerForMovie() { #if USE(ACCELERATED_COMPOSITING) - if (!m_qtVideoLayer) - return; - m_qtVideoLayer = 0; + if (m_qtVideoLayer) + m_qtVideoLayer = 0; + + if (m_imageQueue) + m_imageQueue = 0; #endif } diff --git a/WebCore/platform/graphics/win/MediaPlayerPrivateQuickTimeVisualContext.h b/WebCore/platform/graphics/win/MediaPlayerPrivateQuickTimeVisualContext.h index 12166a3..7bf796c 100644 --- a/WebCore/platform/graphics/win/MediaPlayerPrivateQuickTimeVisualContext.h +++ b/WebCore/platform/graphics/win/MediaPlayerPrivateQuickTimeVisualContext.h @@ -41,7 +41,6 @@ typedef struct CGImage *CGImageRef; class QTMovie; class QTMovieVisualContext; -class WKCAImageQueue; namespace WebCore { @@ -50,6 +49,10 @@ class IntSize; class IntRect; class String; +#if USE(ACCELERATED_COMPOSITING) +class WKCAImageQueue; +#endif + class MediaPlayerPrivateQuickTimeVisualContext : public MediaPlayerPrivateInterface { public: static void registerMediaEngine(MediaEngineRegistrar); @@ -161,6 +164,7 @@ private: RefPtr<QTMovie> m_movie; #if USE(ACCELERATED_COMPOSITING) OwnPtr<GraphicsLayer> m_qtVideoLayer; + OwnPtr<WKCAImageQueue> m_imageQueue; #endif RefPtr<QTMovieVisualContext> m_visualContext; float m_seekTo; diff --git a/WebCore/platform/graphics/win/QTMovieVisualContext.cpp b/WebCore/platform/graphics/win/QTMovieVisualContext.cpp index 9c08cd9..0232d3b 100644 --- a/WebCore/platform/graphics/win/QTMovieVisualContext.cpp +++ b/WebCore/platform/graphics/win/QTMovieVisualContext.cpp @@ -39,7 +39,7 @@ struct QTCVTimeStamp { class QTMovieVisualContextPriv { public: - QTMovieVisualContextPriv(QTMovieVisualContext* parent, QTMovieVisualContextClient* client, CFDictionaryRef options); + QTMovieVisualContextPriv(QTMovieVisualContext* parent, QTMovieVisualContextClient* client, QTMovieVisualContext::Type contextType); ~QTMovieVisualContextPriv(); bool isImageAvailableForTime(const QTCVTimeStamp*) const; @@ -61,7 +61,61 @@ private: }; -QTMovieVisualContextPriv::QTMovieVisualContextPriv(QTMovieVisualContext* parent, QTMovieVisualContextClient* client, CFDictionaryRef options) +static OSStatus SetNumberValue(CFMutableDictionaryRef inDict, CFStringRef inKey, SInt32 inValue) +{ + CFNumberRef number; + + number = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &inValue); + if (!number) + return coreFoundationUnknownErr; + + CFDictionarySetValue(inDict, inKey, number); + CFRelease(number); + + return noErr; +} + +static CFDictionaryRef createPixelBufferOptionsDictionary(QTMovieVisualContext::Type contextType) +{ + static const CFStringRef kDirect3DCompatibilityKey = CFSTR("Direct3DCompatibility"); + + CFMutableDictionaryRef pixelBufferOptions = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); + + CFMutableDictionaryRef pixelBufferAttributes = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); + if (contextType == QTMovieVisualContext::ConfigureForCAImageQueue) { + // Ask for D3D compatible pixel buffers so no further work is needed. + CFDictionarySetValue(pixelBufferAttributes, kDirect3DCompatibilityKey, kCFBooleanTrue); + } else { + // Use the k32BGRAPixelFormat, as QuartzCore will be able to use the pixels directly, + // without needing an additional copy or rendering pass. + SetNumberValue(pixelBufferAttributes, kCVPixelBufferPixelFormatTypeKey, k32BGRAPixelFormat); + + // Set kCVPixelBufferBytesPerRowAlignmentKey to 16 to ensure that each row of pixels + // starts at a 16 byte aligned address for most efficient data reading. + SetNumberValue(pixelBufferAttributes, kCVPixelBufferBytesPerRowAlignmentKey, 16); + CFDictionarySetValue(pixelBufferAttributes, kCVPixelBufferCGImageCompatibilityKey, kCFBooleanTrue); + } + + CFDictionarySetValue(pixelBufferOptions, kQTVisualContextPixelBufferAttributesKey, pixelBufferAttributes); + + CFRelease(pixelBufferAttributes); + + return pixelBufferOptions; +} + +static CFDictionaryRef pixelBufferCreationOptions(QTMovieVisualContext::Type contextType) +{ + if (contextType == QTMovieVisualContext::ConfigureForCAImageQueue) { + static CFDictionaryRef imageQueueOptions = createPixelBufferOptionsDictionary(contextType); + return imageQueueOptions; + } + + ASSERT(contextType == QTMovieVisualContext::ConfigureForCGImage); + static CFDictionaryRef cgImageOptions = createPixelBufferOptionsDictionary(contextType); + return cgImageOptions; +} + +QTMovieVisualContextPriv::QTMovieVisualContextPriv(QTMovieVisualContext* parent, QTMovieVisualContextClient* client, QTMovieVisualContext::Type contextType) : m_parent(parent) , m_client(client) , m_visualContext(0) @@ -77,13 +131,15 @@ QTMovieVisualContextPriv::QTMovieVisualContextPriv(QTMovieVisualContext* parent, return; } - OSStatus status = pPixelBufferContextCreate(kCFAllocatorDefault, options, &m_visualContext); + OSStatus status = pPixelBufferContextCreate(kCFAllocatorDefault, pixelBufferCreationOptions(contextType), &m_visualContext); if (status == noErr && m_visualContext) QTVisualContextSetImageAvailableCallback(m_visualContext, &QTMovieVisualContextPriv::imageAvailableCallback, static_cast<void*>(this)); } QTMovieVisualContextPriv::~QTMovieVisualContextPriv() { + if (m_visualContext) + QTVisualContextSetImageAvailableCallback(m_visualContext, 0, 0); } bool QTMovieVisualContextPriv::isImageAvailableForTime(const QTCVTimeStamp* timeStamp) const @@ -150,66 +206,13 @@ void QTMovieVisualContextPriv::imageAvailableCallback(QTVisualContextRef visualC vc->m_client->imageAvailableForTime(reinterpret_cast<const QTCVTimeStamp*>(timeStamp)); } -static OSStatus SetNumberValue(CFMutableDictionaryRef inDict, CFStringRef inKey, SInt32 inValue) +PassRefPtr<QTMovieVisualContext> QTMovieVisualContext::create(QTMovieVisualContextClient* client, Type contextType) { - CFNumberRef number; - - number = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &inValue); - if (!number) - return coreFoundationUnknownErr; - - CFDictionarySetValue(inDict, inKey, number); - - CFRelease(number); - - return noErr; -} - -CFDictionaryRef QTMovieVisualContext::getCGImageOptions() -{ - static CFDictionaryRef options = 0; - - if (!options) { - CFMutableDictionaryRef pixelBufferOptions = 0; - CFMutableDictionaryRef visualContextOptions = 0; - OSStatus status = noErr; - - // Pixel Buffer attributes - pixelBufferOptions = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, - &kCFTypeDictionaryKeyCallBacks, - &kCFTypeDictionaryValueCallBacks); - - // Use the k32BGRAPixelFormat, as QuartzCore will be able to use the pixels directly, - // without needing an aditional copy or rendering pass:s - SetNumberValue(pixelBufferOptions, kCVPixelBufferPixelFormatTypeKey, k32BGRAPixelFormat); - - // alignment - SetNumberValue(pixelBufferOptions, kCVPixelBufferBytesPerRowAlignmentKey, 16); - - // compatability - SetNumberValue(pixelBufferOptions, kCVPixelBufferCGImageCompatibilityKey, 1); - - // QT Visual Context attributes - visualContextOptions = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, - &kCFTypeDictionaryKeyCallBacks, - &kCFTypeDictionaryValueCallBacks); - - // set the pixel buffer attributes for the visual context - CFDictionarySetValue(visualContextOptions, - kQTVisualContextPixelBufferAttributesKey, - pixelBufferOptions); - - if (pixelBufferOptions) - CFRelease(pixelBufferOptions); - - options = visualContextOptions; - } - - return options; + return adoptRef(new QTMovieVisualContext(client, contextType)); } -QTMovieVisualContext::QTMovieVisualContext(QTMovieVisualContextClient* client, CFDictionaryRef options) - : m_private(new QTMovieVisualContextPriv(this, client, options)) +QTMovieVisualContext::QTMovieVisualContext(QTMovieVisualContextClient* client, Type contextType) + : m_private(new QTMovieVisualContextPriv(this, client, contextType)) { } diff --git a/WebCore/platform/graphics/win/QTMovieVisualContext.h b/WebCore/platform/graphics/win/QTMovieVisualContext.h index 8846416..057031e 100644 --- a/WebCore/platform/graphics/win/QTMovieVisualContext.h +++ b/WebCore/platform/graphics/win/QTMovieVisualContext.h @@ -54,7 +54,9 @@ public: class QTMOVIEWIN_API QTMovieVisualContext : public RefCounted<QTMovieVisualContext> { public: - QTMovieVisualContext(QTMovieVisualContextClient*, CFDictionaryRef options = 0); + enum Type { ConfigureForCGImage, ConfigureForCAImageQueue }; + + static PassRefPtr<QTMovieVisualContext> create(QTMovieVisualContextClient*, Type); ~QTMovieVisualContext(); bool isImageAvailableForTime(const QTCVTimeStamp*) const; @@ -66,10 +68,10 @@ public: void setMovie(PassRefPtr<QTMovie>); QTMovie* movie() const; - static CFDictionaryRef getCGImageOptions(); static double currentHostTime(); protected: + QTMovieVisualContext(QTMovieVisualContextClient*, Type); void setupVisualContext(); friend class QTMovieVisualContextPriv; diff --git a/WebCore/platform/graphics/win/QTPixelBuffer.cpp b/WebCore/platform/graphics/win/QTPixelBuffer.cpp index f874287..657b68e 100644 --- a/WebCore/platform/graphics/win/QTPixelBuffer.cpp +++ b/WebCore/platform/graphics/win/QTPixelBuffer.cpp @@ -172,6 +172,11 @@ void QTPixelBuffer::getExtendedPixels(size_t* left, size_t* right, size_t* top, return CVPixelBufferGetExtendedPixels(m_pixelBuffer, left, right, top, bottom); } +CFDictionaryRef QTPixelBuffer::attachments() const +{ + return CVBufferGetAttachments(m_pixelBuffer, kCVAttachmentMode_ShouldPropagate); +} + void QTPixelBuffer::retainCallback(void* refcon) { CVPixelBufferRetain(static_cast<CVPixelBufferRef>(refcon)); diff --git a/WebCore/platform/graphics/win/QTPixelBuffer.h b/WebCore/platform/graphics/win/QTPixelBuffer.h index 3af2197..22f8ba4 100644 --- a/WebCore/platform/graphics/win/QTPixelBuffer.h +++ b/WebCore/platform/graphics/win/QTPixelBuffer.h @@ -38,6 +38,7 @@ typedef struct __CVBuffer *CVBufferRef; typedef CVBufferRef CVPixelBufferRef; typedef struct CGImage* CGImageRef; typedef int32_t CVReturn; +typedef const struct __CFDictionary * CFDictionaryRef; // QTPixelBuffer wraps QuickTime's implementation of CVPixelBuffer, so its functions are // safe to call within WebKit. @@ -74,6 +75,7 @@ public: size_t bytesPerRowOfPlane(size_t) const; void getExtendedPixels(size_t* left, size_t* right, size_t* top, size_t* bottom) const; + CFDictionaryRef attachments() const; // Generic CFRetain/CFRelease callbacks static void releaseCallback(void* refcon); diff --git a/WebCore/platform/graphics/win/WKCACFLayer.cpp b/WebCore/platform/graphics/win/WKCACFLayer.cpp index 3f332d8..d3928f1 100644 --- a/WebCore/platform/graphics/win/WKCACFLayer.cpp +++ b/WebCore/platform/graphics/win/WKCACFLayer.cpp @@ -154,6 +154,7 @@ PassRefPtr<WKCACFLayer> WKCACFLayer::create(LayerType type) WKCACFLayer::WKCACFLayer(LayerType type) : m_layer(AdoptCF, CACFLayerCreate(toCACFLayerType(type))) + , m_layoutClient(0) , m_needsDisplayOnBoundsChange(false) { CACFLayerSetUserData(layer(), this); @@ -286,11 +287,10 @@ void WKCACFLayer::adoptSublayers(WKCACFLayer* source) void WKCACFLayer::removeFromSuperlayer() { WKCACFLayer* superlayer = this->superlayer(); - if (!superlayer) - return; - CACFLayerRemoveFromSuperlayer(layer()); - superlayer->setNeedsCommit(); + + if (superlayer) + superlayer->setNeedsCommit(); } WKCACFLayer* WKCACFLayer::internalSublayerAtIndex(int index) const @@ -343,6 +343,19 @@ void WKCACFLayer::setBounds(const CGRect& rect) setNeedsDisplay(); } +void WKCACFLayer::setFrame(const CGRect& rect) +{ + CGRect oldFrame = frame(); + if (CGRectEqualToRect(rect, oldFrame)) + return; + + CACFLayerSetFrame(layer(), rect); + setNeedsCommit(); + + if (m_needsDisplayOnBoundsChange && !CGSizeEqualToSize(rect.size, oldFrame.size)) + setNeedsDisplay(); +} + void WKCACFLayer::setContentsGravity(ContentsGravityType type) { CACFLayerSetContentsGravity(layer(), toCACFContentsGravityType(type)); @@ -418,6 +431,22 @@ void WKCACFLayer::internalSetNeedsDisplay(const CGRect* dirtyRect) CACFLayerSetNeedsDisplay(layer(), dirtyRect); } +void WKCACFLayer::setLayoutClient(WKCACFLayerLayoutClient* layoutClient) +{ + if (layoutClient == m_layoutClient) + return; + + m_layoutClient = layoutClient; + CACFLayerSetLayoutCallback(layer(), m_layoutClient ? layoutSublayersProc : 0); +} + +void WKCACFLayer::layoutSublayersProc(CACFLayerRef caLayer) +{ + WKCACFLayer* layer = WKCACFLayer::layer(caLayer); + if (layer && layer->m_layoutClient) + layer->m_layoutClient->layoutSublayersOfLayer(layer); +} + #ifndef NDEBUG static void printIndent(int indent) { @@ -497,11 +526,14 @@ void WKCACFLayer::printLayer(int indent) const } // Print contents if needed - CGImageRef layerContents = contents(); + CFTypeRef layerContents = contents(); if (layerContents) { - printIndent(indent + 1); - fprintf(stderr, "(contents (image [%d %d]))\n", - CGImageGetWidth(layerContents), CGImageGetHeight(layerContents)); + if (CFGetTypeID(layerContents) == CGImageGetTypeID()) { + CGImageRef imageContents = static_cast<CGImageRef>(const_cast<void*>(layerContents)); + printIndent(indent + 1); + fprintf(stderr, "(contents (image [%d %d]))\n", + CGImageGetWidth(imageContents), CGImageGetHeight(imageContents)); + } } // Print sublayers if needed diff --git a/WebCore/platform/graphics/win/WKCACFLayer.h b/WebCore/platform/graphics/win/WKCACFLayer.h index bdc427e..5e8eb05 100644 --- a/WebCore/platform/graphics/win/WKCACFLayer.h +++ b/WebCore/platform/graphics/win/WKCACFLayer.h @@ -44,8 +44,14 @@ namespace WebCore { -class WKCACFAnimation; -class WKCACFTimingFunction; +class WKCACFLayer; + +class WKCACFLayerLayoutClient { +public: + virtual void layoutSublayersOfLayer(WKCACFLayer*) = 0; +protected: + virtual ~WKCACFLayerLayoutClient() {} +}; class WKCACFLayer : public RefCounted<WKCACFLayer> { public: @@ -63,6 +69,10 @@ public: virtual void drawInContext(PlatformGraphicsContext*) { } + void setLayoutClient(WKCACFLayerLayoutClient*); + WKCACFLayerLayoutClient* layoutClient() const { return m_layoutClient; } + void setNeedsLayout() { CACFLayerSetNeedsLayout(layer()); } + void setNeedsDisplay(const CGRect* dirtyRect = 0) { internalSetNeedsDisplay(dirtyRect); @@ -155,8 +165,8 @@ public: void setClearsContext(bool clears) { CACFLayerSetClearsContext(layer(), clears); setNeedsCommit(); } bool clearsContext() const { return CACFLayerGetClearsContext(layer()); } - void setContents(CGImageRef contents) { CACFLayerSetContents(layer(), contents); setNeedsCommit(); } - CGImageRef contents() const { return static_cast<CGImageRef>(const_cast<void*>(CACFLayerGetContents(layer()))); } + void setContents(CFTypeRef contents) { CACFLayerSetContents(layer(), contents); setNeedsCommit(); } + CFTypeRef contents() const { return CACFLayerGetContents(layer()); } void setContentsRect(const CGRect& contentsRect) { CACFLayerSetContentsRect(layer(), contentsRect); setNeedsCommit(); } CGRect contentsRect() const { return CACFLayerGetContentsRect(layer()); } @@ -173,6 +183,9 @@ public: void setFilters(CFArrayRef filters) { CACFLayerSetFilters(layer(), filters); setNeedsCommit(); } CFArrayRef filters() const { return CACFLayerGetFilters(layer()); } + virtual void setFrame(const CGRect&); + CGRect frame() const { return CACFLayerGetFrame(layer()); } + void setHidden(bool hidden) { CACFLayerSetHidden(layer(), hidden); setNeedsCommit(); } bool isHidden() const { return CACFLayerIsHidden(layer()); } @@ -206,10 +219,10 @@ public: CGFloat zPosition() const { return CACFLayerGetZPosition(layer()); } void setSpeed(float speed) { CACFLayerSetSpeed(layer(), speed); } - CFTimeInterval speed() const { CACFLayerGetSpeed(layer()); } + CFTimeInterval speed() const { return CACFLayerGetSpeed(layer()); } void setTimeOffset(CFTimeInterval t) { CACFLayerSetTimeOffset(layer(), t); } - CFTimeInterval timeOffset() const { CACFLayerGetTimeOffset(layer()); } + CFTimeInterval timeOffset() const { return CACFLayerGetTimeOffset(layer()); } WKCACFLayer* rootLayer() const; @@ -261,7 +274,10 @@ protected: #endif private: + static void layoutSublayersProc(CACFLayerRef); + RetainPtr<CACFLayerRef> m_layer; + WKCACFLayerLayoutClient* m_layoutClient; bool m_needsDisplayOnBoundsChange; }; diff --git a/WebCore/platform/graphics/win/WKCAImageQueue.cpp b/WebCore/platform/graphics/win/WKCAImageQueue.cpp new file mode 100644 index 0000000..b52b9a4 --- /dev/null +++ b/WebCore/platform/graphics/win/WKCAImageQueue.cpp @@ -0,0 +1,104 @@ +/* + * Copyright (C) 2010 Apple 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 "WKCAImageQueue.h" + +#include <WebKitSystemInterface/WebKitSystemInterface.h> +#include <wtf/RetainPtr.h> + +namespace WebCore { + +class WKCAImageQueuePrivate { +public: + RetainPtr<CAImageQueueRef> m_imageQueue; +}; + +static CAImageQueueRef WKCAImageQueueRetain(CAImageQueueRef iq) +{ + if (iq) + return (CAImageQueueRef)CFRetain(iq); + return 0; +} + +static void WKCAImageQueueRelease(CAImageQueueRef iq) +{ + if (iq) + CFRelease(iq); +} + +WKCAImageQueue::WKCAImageQueue(uint32_t width, uint32_t height, uint32_t capacity) + : m_private(new WKCAImageQueuePrivate()) +{ + m_private->m_imageQueue.adoptCF(wkCAImageQueueCreate(width, height, capacity)); +} + +WKCAImageQueue::WKCAImageQueue(const WKCAImageQueue& o) + : m_private(new WKCAImageQueuePrivate()) +{ + m_private->m_imageQueue = o.m_private->m_imageQueue; +} + +WKCAImageQueue::~WKCAImageQueue(void) +{ +} + +WKCAImageQueue& WKCAImageQueue::operator=(const WKCAImageQueue& o) +{ + m_private->m_imageQueue = o.m_private->m_imageQueue; + return *this; +} + +size_t WKCAImageQueue::collect() +{ + return wkCAImageQueueCollect(m_private->m_imageQueue.get()); +} + +bool WKCAImageQueue::insertImage(double t, unsigned int type, uint64_t id, uint32_t flags, ReleaseCallback release, void* info) +{ + return wkCAImageQueueInsertImage(m_private->m_imageQueue.get(), t, type, id, flags, release, info); +} + +uint64_t WKCAImageQueue::registerPixelBuffer(void *data, size_t data_size, size_t rowbytes, size_t width, size_t height, uint32_t pixel_format, CFDictionaryRef attachments, uint32_t flags) +{ + return wkCAImageQueueRegisterPixelBuffer(m_private->m_imageQueue.get(), data, data_size, rowbytes, width, height, pixel_format, attachments, flags); +} + +void WKCAImageQueue::setFlags(uint32_t mask, uint32_t flags) +{ + wkCAImageQueueSetFlags(m_private->m_imageQueue.get(), mask, flags); +} + +CFTypeRef WKCAImageQueue::get() +{ + return m_private->m_imageQueue.get(); +} + +} + +#endif diff --git a/WebCore/platform/graphics/win/WKCAImageQueue.h b/WebCore/platform/graphics/win/WKCAImageQueue.h new file mode 100644 index 0000000..5c17575 --- /dev/null +++ b/WebCore/platform/graphics/win/WKCAImageQueue.h @@ -0,0 +1,92 @@ +/* + * Copyright (C) 2010 Apple 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 WKCAImageQueue_h +#define WKCAImageQueue_h + +#if USE(ACCELERATED_COMPOSITING) + +typedef const void * CFTypeRef; +typedef const struct __CFDictionary * CFDictionaryRef; + +#include <stdint.h> +#include <wtf/OwnPtr.h> + +namespace WebCore { + +class WKCAImageQueuePrivate; + +class WKCAImageQueue { +public: + enum Flags { + Async = 1U << 0, + Fill = 1U << 1, + Protected = 1U << 2, + UseCleanAperture = 1U << 3, + UseAspectRatio = 1U << 4, + LowQualityColor = 1U << 5, + }; + + enum ImageType { + Nil = 1, + Surface, + Buffer, + IOSurface, + }; + + enum ImageFlags { + Opaque = 1U << 0, + Flush = 1U << 1, + WillFlush = 1U << 2, + Flipped = 1U << 3, + WaitGPU = 1U << 4, + }; + + typedef void (*ReleaseCallback)(unsigned int type, uint64_t id, void* info); + + WKCAImageQueue(uint32_t width, uint32_t height, uint32_t capacity); + ~WKCAImageQueue(void); + + size_t collect(); + + bool insertImage(double t, unsigned int type, uint64_t id, uint32_t flags, ReleaseCallback release, void* info); + uint64_t registerPixelBuffer(void *data, size_t data_size, size_t rowbytes, size_t width, size_t height, uint32_t pixel_format, CFDictionaryRef attachments, uint32_t flags); + + uint32_t flags() const; + void setFlags(uint32_t mask, uint32_t flags); + + CFTypeRef get(); + +private: + WKCAImageQueue(const WKCAImageQueue&); + WKCAImageQueue& operator=(const WKCAImageQueue&); + OwnPtr<WKCAImageQueuePrivate> m_private; +}; + +} + +#endif + +#endif diff --git a/WebCore/platform/graphics/win/WebTiledLayer.cpp b/WebCore/platform/graphics/win/WebTiledLayer.cpp index 0cf3f9d..d8c02d2 100755 --- a/WebCore/platform/graphics/win/WebTiledLayer.cpp +++ b/WebCore/platform/graphics/win/WebTiledLayer.cpp @@ -73,6 +73,15 @@ void WebTiledLayer::setBounds(const CGRect& rect) updateTiles(); } +void WebTiledLayer::setFrame(const CGRect& rect) +{ + if (CGRectEqualToRect(rect, frame())) + return; + + WebLayer::setFrame(rect); + updateTiles(); +} + void WebTiledLayer::internalSetNeedsDisplay(const CGRect* dirtyRect) { // FIXME: Only setNeedsDisplay for tiles that are currently visible diff --git a/WebCore/platform/graphics/win/WebTiledLayer.h b/WebCore/platform/graphics/win/WebTiledLayer.h index ed61656..fdf0205 100755 --- a/WebCore/platform/graphics/win/WebTiledLayer.h +++ b/WebCore/platform/graphics/win/WebTiledLayer.h @@ -39,6 +39,7 @@ public: virtual ~WebTiledLayer(); virtual void setBounds(const CGRect&); + virtual void setFrame(const CGRect&); protected: WebTiledLayer(const CGSize& tileSize, GraphicsLayer* owner); diff --git a/WebCore/platform/graphics/wince/ImageBufferWince.cpp b/WebCore/platform/graphics/wince/ImageBufferWince.cpp index ac3a630..0d5c8dd 100644 --- a/WebCore/platform/graphics/wince/ImageBufferWince.cpp +++ b/WebCore/platform/graphics/wince/ImageBufferWince.cpp @@ -1,5 +1,6 @@ /* * Copyright (C) 2009 Torch Mobile, Inc. All rights reserved. + * Copyright (C) 2010 Torch Mobile (Beijing) Co. Ltd. All rights reserved. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -215,7 +216,7 @@ void ImageBuffer::putPremultipliedImageData(ImageData* source, const IntRect& so putImageData<true>(source, sourceRect, destPoint, m_data.m_bitmap.get()); } -String ImageBuffer::toDataURL(const String& mimeType) const +String ImageBuffer::toDataURL(const String& mimeType, double) const { if (!m_data.m_bitmap->bytes()) return "data:,"; diff --git a/WebCore/platform/graphics/wx/FontWx.cpp b/WebCore/platform/graphics/wx/FontWx.cpp index c00c622..3dcabf1 100644 --- a/WebCore/platform/graphics/wx/FontWx.cpp +++ b/WebCore/platform/graphics/wx/FontWx.cpp @@ -35,7 +35,7 @@ #if OS(WINDOWS) #include "UniscribeController.h" -typedef UniscribeController ComplexTextController +typedef WebCore::UniscribeController ComplexTextController; #endif #if OS(DARWIN) diff --git a/WebCore/platform/graphics/wx/ImageBufferWx.cpp b/WebCore/platform/graphics/wx/ImageBufferWx.cpp index 6cc611e..1d37dfa 100644 --- a/WebCore/platform/graphics/wx/ImageBufferWx.cpp +++ b/WebCore/platform/graphics/wx/ImageBufferWx.cpp @@ -1,5 +1,6 @@ /* * Copyright (C) 2007 Kevin Ollivier <kevino@theolliviers.com> + * Copyright (C) 2010 Torch Mobile (Beijing) Co. Ltd. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -75,7 +76,7 @@ void ImageBuffer::putPremultipliedImageData(ImageData* source, const IntRect& so notImplemented(); } -String ImageBuffer::toDataURL(const String&) const +String ImageBuffer::toDataURL(const String&, double) const { notImplemented(); return String(); |