summaryrefslogtreecommitdiffstats
path: root/WebCore/platform/graphics/win
diff options
context:
space:
mode:
Diffstat (limited to 'WebCore/platform/graphics/win')
-rw-r--r--WebCore/platform/graphics/win/GraphicsLayerCACF.cpp185
-rw-r--r--WebCore/platform/graphics/win/GraphicsLayerCACF.h3
-rw-r--r--WebCore/platform/graphics/win/MediaPlayerPrivateQuickTimeVisualContext.cpp72
-rw-r--r--WebCore/platform/graphics/win/QTMovieVisualContext.h1
-rw-r--r--WebCore/platform/graphics/win/QTPixelBuffer.cpp5
-rw-r--r--WebCore/platform/graphics/win/QTPixelBuffer.h2
-rw-r--r--WebCore/platform/graphics/win/WKCACFContextFlusher.cpp4
-rw-r--r--WebCore/platform/graphics/win/WKCACFLayer.cpp69
-rw-r--r--WebCore/platform/graphics/win/WKCACFLayer.h52
-rw-r--r--WebCore/platform/graphics/win/WKCACFLayerRenderer.cpp142
-rw-r--r--WebCore/platform/graphics/win/WKCACFLayerRenderer.h14
-rwxr-xr-xWebCore/platform/graphics/win/WebLayer.cpp143
-rwxr-xr-xWebCore/platform/graphics/win/WebLayer.h62
-rwxr-xr-xWebCore/platform/graphics/win/WebTiledLayer.cpp274
-rwxr-xr-xWebCore/platform/graphics/win/WebTiledLayer.h80
15 files changed, 841 insertions, 267 deletions
diff --git a/WebCore/platform/graphics/win/GraphicsLayerCACF.cpp b/WebCore/platform/graphics/win/GraphicsLayerCACF.cpp
index 0065191..20d76ef 100644
--- a/WebCore/platform/graphics/win/GraphicsLayerCACF.cpp
+++ b/WebCore/platform/graphics/win/GraphicsLayerCACF.cpp
@@ -36,7 +36,8 @@
#include "Image.h"
#include "PlatformString.h"
#include "SystemTime.h"
-#include "WKCACFLayer.h"
+#include "WebLayer.h"
+#include "WebTiledLayer.h"
#include <wtf/CurrentTime.h>
#include <wtf/StringExtras.h>
#include <wtf/text/CString.h>
@@ -45,115 +46,15 @@ using namespace std;
namespace WebCore {
-class WebLayer : public WKCACFLayer {
-public:
- static PassRefPtr<WKCACFLayer> create(LayerType layerType, GraphicsLayerCACF* owner)
- {
- return adoptRef(new WebLayer(layerType, owner));
- }
-
- virtual void setNeedsDisplay(const CGRect* dirtyRect)
- {
- if (m_owner) {
- if (m_owner->showRepaintCounter()) {
- CGRect layerBounds = bounds();
- CGRect repaintCounterRect = layerBounds;
- // We assume a maximum of 4 digits and a font size of 22.
- repaintCounterRect.size.width = 48;
- repaintCounterRect.size.height = 25;
- if (m_owner->contentsOrientation() == WebCore::GraphicsLayer::CompositingCoordinatesTopDown)
- repaintCounterRect.origin.y = layerBounds.size.height - (layerBounds.origin.y + repaintCounterRect.size.height);
- WKCACFLayer::setNeedsDisplay(&repaintCounterRect);
- }
- if (dirtyRect && m_owner->contentsOrientation() == WebCore::GraphicsLayer::CompositingCoordinatesTopDown) {
- CGRect flippedDirtyRect = *dirtyRect;
- flippedDirtyRect.origin.y = bounds().size.height - (flippedDirtyRect.origin.y + flippedDirtyRect.size.height);
- WKCACFLayer::setNeedsDisplay(&flippedDirtyRect);
- return;
- }
- }
- WKCACFLayer::setNeedsDisplay(dirtyRect);
- }
-
- virtual void drawInContext(PlatformGraphicsContext* context)
- {
- if (!m_owner)
- return;
-
- CGContextSaveGState(context);
-
- CGRect layerBounds = bounds();
- if (m_owner->contentsOrientation() == WebCore::GraphicsLayer::CompositingCoordinatesTopDown) {
- CGContextScaleCTM(context, 1, -1);
- CGContextTranslateCTM(context, 0, -layerBounds.size.height);
- }
-
- if (m_owner->client()) {
- GraphicsContext graphicsContext(context);
-
- // It's important to get the clip from the context, because it may be significantly
- // smaller than the layer bounds (e.g. tiled layers)
- CGRect clipBounds = CGContextGetClipBoundingBox(context);
- IntRect clip(enclosingIntRect(clipBounds));
- m_owner->paintGraphicsLayerContents(graphicsContext, clip);
- }
-#ifndef NDEBUG
- else {
- ASSERT_NOT_REACHED();
-
- // FIXME: ideally we'd avoid calling -setNeedsDisplay on a layer that is a plain color,
- // so CA never makes backing store for it (which is what -setNeedsDisplay will do above).
- CGContextSetRGBFillColor(context, 0.0f, 1.0f, 0.0f, 1.0f);
- CGContextFillRect(context, layerBounds);
- }
-#endif
-
- if (m_owner->showRepaintCounter()) {
- String text = String::format("%d", m_owner->incrementRepaintCount());;
-
- CGContextSaveGState(context);
- CGContextSetRGBFillColor(context, 1.0f, 0.0f, 0.0f, 0.8f);
-
- CGRect aBounds = layerBounds;
-
- aBounds.size.width = 10 + 12 * text.length();
- aBounds.size.height = 25;
- CGContextFillRect(context, aBounds);
-
- FontDescription desc;
-
- NONCLIENTMETRICS metrics;
- metrics.cbSize = sizeof(metrics);
- SystemParametersInfo(SPI_GETNONCLIENTMETRICS, metrics.cbSize, &metrics, 0);
- FontFamily family;
- family.setFamily(metrics.lfSmCaptionFont.lfFaceName);
- desc.setFamily(family);
-
- desc.setComputedSize(22);
-
- Font font = Font(desc, 0, 0);
- font.update(0);
-
- GraphicsContext cg(context);
- cg.setFillColor(Color::black, DeviceColorSpace);
- cg.drawText(font, TextRun(text), IntPoint(aBounds.origin.x + 3, aBounds.origin.y + 20));
-
- CGContextRestoreGState(context);
- }
-
- CGContextRestoreGState(context);
- }
-
-protected:
- WebLayer(LayerType layerType, GraphicsLayerCACF* owner)
- : WKCACFLayer(layerType)
- , m_owner(owner)
- {
- }
+// The threshold width or height above which a tiled layer will be used. This should be
+// large enough to avoid tiled layers for most GraphicsLayers, but less than the D3D
+// texture size limit on all supported hardware.
+static const int cMaxPixelDimension = 2000;
-private:
- GraphicsLayer* m_owner;
-};
+// The width and height of a single tile in a tiled layer. Should be large enough to
+// avoid lots of small tiles (and therefore lots of drawing callbacks), but small enough
+// to keep the overall tile cost low.
+static const int cTiledLayerTileSize = 512;
static inline void copyTransform(CATransform3D& toT3D, const TransformationMatrix& t)
{
@@ -537,6 +438,64 @@ void GraphicsLayerCACF::setDebugBorder(const Color& color, float borderWidth)
}
}
+bool GraphicsLayerCACF::requiresTiledLayer(const FloatSize& size) const
+{
+ if (!m_drawsContent)
+ return false;
+
+ // FIXME: catch zero-size height or width here (or earlier)?
+ return size.width() > cMaxPixelDimension || size.height() > cMaxPixelDimension;
+}
+
+void GraphicsLayerCACF::swapFromOrToTiledLayer(bool useTiledLayer)
+{
+ if (useTiledLayer == m_usingTiledLayer)
+ return;
+
+ CGSize tileSize = CGSizeMake(cTiledLayerTileSize, cTiledLayerTileSize);
+
+ RefPtr<WKCACFLayer> oldLayer = m_layer;
+ if (useTiledLayer)
+ m_layer = WebTiledLayer::create(tileSize, this);
+ else
+ m_layer = WebLayer::create(WKCACFLayer::Layer, this);
+
+ m_usingTiledLayer = useTiledLayer;
+
+ if (useTiledLayer) {
+ if (GraphicsLayer::compositingCoordinatesOrientation() == GraphicsLayer::CompositingCoordinatesBottomUp)
+ m_layer->setContentsGravity(WKCACFLayer::BottomLeft);
+ else
+ m_layer->setContentsGravity(WKCACFLayer::TopLeft);
+ }
+
+ m_layer->adoptSublayers(oldLayer.get());
+ if (oldLayer->superlayer())
+ oldLayer->superlayer()->replaceSublayer(oldLayer.get(), m_layer.get());
+
+ updateLayerPosition();
+ updateLayerSize();
+ updateAnchorPoint();
+ updateTransform();
+ updateChildrenTransform();
+ updateMasksToBounds();
+ updateContentsOpaque();
+ updateBackfaceVisibility();
+ updateLayerBackgroundColor();
+
+ updateOpacityOnLayer();
+
+#ifndef NDEBUG
+ String name = String::format("CALayer(%p) GraphicsLayer(%p) %s", m_layer.get(), this, m_usingTiledLayer ? "[Tiled Layer] " : "") + m_name;
+ m_layer->setName(name);
+#endif
+
+ // need to tell new layer to draw itself
+ setNeedsDisplay();
+
+ updateDebugIndicators();
+}
+
GraphicsLayer::CompositingCoordinatesOrientation GraphicsLayerCACF::defaultContentsOrientation() const
{
return CompositingCoordinatesTopDown;
@@ -600,6 +559,10 @@ void GraphicsLayerCACF::updateLayerSize()
m_layer->setPosition(centerPoint);
}
+ bool needTiledLayer = requiresTiledLayer(m_size);
+ if (needTiledLayer != m_usingTiledLayer)
+ swapFromOrToTiledLayer(needTiledLayer);
+
m_layer->setBounds(rect);
// Note that we don't resize m_contentsLayer. It's up the caller to do that.
@@ -699,6 +662,10 @@ void GraphicsLayerCACF::updateLayerPreserves3D()
void GraphicsLayerCACF::updateLayerDrawsContent()
{
+ bool needTiledLayer = requiresTiledLayer(m_size);
+ if (needTiledLayer != m_usingTiledLayer)
+ swapFromOrToTiledLayer(needTiledLayer);
+
if (m_drawsContent)
m_layer->setNeedsDisplay();
else
diff --git a/WebCore/platform/graphics/win/GraphicsLayerCACF.h b/WebCore/platform/graphics/win/GraphicsLayerCACF.h
index 8c3f848..171cdbf 100644
--- a/WebCore/platform/graphics/win/GraphicsLayerCACF.h
+++ b/WebCore/platform/graphics/win/GraphicsLayerCACF.h
@@ -98,6 +98,9 @@ private:
WKCACFLayer* hostLayerForSublayers() const;
WKCACFLayer* layerForSuperlayer() const;
+ bool requiresTiledLayer(const FloatSize&) const;
+ void swapFromOrToTiledLayer(bool useTiledLayer);
+
CompositingCoordinatesOrientation defaultContentsOrientation() const;
void updateSublayerList();
void updateLayerPosition();
diff --git a/WebCore/platform/graphics/win/MediaPlayerPrivateQuickTimeVisualContext.cpp b/WebCore/platform/graphics/win/MediaPlayerPrivateQuickTimeVisualContext.cpp
index 87625d3..e1d457f 100644
--- a/WebCore/platform/graphics/win/MediaPlayerPrivateQuickTimeVisualContext.cpp
+++ b/WebCore/platform/graphics/win/MediaPlayerPrivateQuickTimeVisualContext.cpp
@@ -45,6 +45,7 @@
#include "StringHash.h"
#include "TimeRanges.h"
#include "Timer.h"
+#include <CoreGraphics/CGContext.h>
#include <Wininet.h>
#include <wtf/CurrentTime.h>
#include <wtf/HashSet.h>
@@ -64,6 +65,8 @@ const CFStringRef kMinCoreVideoVersion = CFSTR("1.0.0.2");
namespace WebCore {
+static CGImageRef CreateCGImageFromPixelBuffer(QTPixelBuffer buffer);
+
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))
@@ -141,12 +144,13 @@ MediaPlayerPrivateQuickTimeVisualContext::MediaPlayerPrivateQuickTimeVisualConte
MediaPlayerPrivateQuickTimeVisualContext::~MediaPlayerPrivateQuickTimeVisualContext()
{
tearDownVideoRendering();
+ m_visualContext->setMovie(0);
cancelCallOnMainThread(&VisualContextClient::retrieveCurrentImageProc, this);
}
bool MediaPlayerPrivateQuickTimeVisualContext::supportsFullscreen() const
{
- return true;
+ return false;
}
PlatformMedia MediaPlayerPrivateQuickTimeVisualContext::platformMedia() const
@@ -284,6 +288,7 @@ void MediaPlayerPrivateQuickTimeVisualContext::load(const String& url)
CFDictionaryRef options = QTMovieVisualContext::getCGImageOptions();
m_visualContext = adoptRef(new QTMovieVisualContext(m_visualContextClient.get(), options));
+ m_visualContext->setMovie(m_movie.get());
}
void MediaPlayerPrivateQuickTimeVisualContext::play()
@@ -629,7 +634,20 @@ void MediaPlayerPrivateQuickTimeVisualContext::paint(GraphicsContext* p, const I
if (m_qtVideoLayer)
return;
#endif
+ QTPixelBuffer buffer = m_visualContext->imageForTime(0);
+ if (buffer.pixelBufferRef()) {
+ CGImageRef image = CreateCGImageFromPixelBuffer(buffer);
+
+ CGContextRef context = p->platformContext();
+ CGContextSaveGState(context);
+ CGContextTranslateCTM(context, r.x(), r.y());
+ CGContextTranslateCTM(context, 0, r.height());
+ CGContextScaleCTM(context, 1, -1);
+ CGContextDrawImage(context, CGRectMake(0, 0, r.width(), r.height()), image);
+ CGContextRestoreGState(context);
+ CGImageRelease(image);
+ }
paintCompleted(*p, r);
}
@@ -654,16 +672,17 @@ void MediaPlayerPrivateQuickTimeVisualContext::VisualContextClient::imageAvailab
void MediaPlayerPrivateQuickTimeVisualContext::visualContextTimerFired(Timer<MediaPlayerPrivateQuickTimeVisualContext>*)
{
- retrieveCurrentImage();
+ if (m_visualContext && m_visualContext->isImageAvailableForTime(0))
+ retrieveCurrentImage();
}
static CFDictionaryRef QTCFDictionaryCreateWithDataCallback(CFAllocatorRef allocator, const UInt8* bytes, CFIndex length)
{
- CFDataRef data = CFDataCreateWithBytesNoCopy(allocator, bytes, length, 0);
+ RetainPtr<CFDataRef> data(AdoptCF, CFDataCreateWithBytesNoCopy(allocator, bytes, length, kCFAllocatorNull));
if (!data)
return 0;
- return reinterpret_cast<CFDictionaryRef>(CFPropertyListCreateFromXMLData(allocator, data, kCFPropertyListImmutable, 0));
+ return reinterpret_cast<CFDictionaryRef>(CFPropertyListCreateFromXMLData(allocator, data.get(), kCFPropertyListImmutable, 0));
}
static CGImageRef CreateCGImageFromPixelBuffer(QTPixelBuffer buffer)
@@ -729,38 +748,29 @@ void MediaPlayerPrivateQuickTimeVisualContext::retrieveCurrentImage()
return;
#if USE(ACCELERATED_COMPOSITING)
- if (!m_qtVideoLayer)
- return;
+ if (m_qtVideoLayer) {
- QTPixelBuffer buffer = m_visualContext->imageForTime(0);
- if (!buffer.pixelBufferRef())
- return;
+ QTPixelBuffer buffer = m_visualContext->imageForTime(0);
+ if (!buffer.pixelBufferRef())
+ return;
- WKCACFLayer* layer = static_cast<WKCACFLayer*>(m_qtVideoLayer->platformLayer());
+ WKCACFLayer* layer = static_cast<WKCACFLayer*>(m_qtVideoLayer->platformLayer());
- if (!buffer.lockBaseAddress()) {
-#ifndef NDEBUG
- // 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:
- CFDictionaryRef attachments = QTCFDictionaryCreateCopyWithDataCallback(kCFAllocatorDefault, buffer.attachments(), &QTCFDictionaryCreateWithDataCallback);
-#else
- // However, this is unnecssesary in the non-Debug case:
- CFDictionaryRef attachments = static_cast<CFDictionaryRef>(CFRetain(buffer.attachments()));
-#endif
+ if (!buffer.lockBaseAddress()) {
+ CFTimeInterval imageTime = QTMovieVisualContext::currentHostTime();
- CFTimeInterval imageTime = QTMovieVisualContext::currentHostTime();
+ CGImageRef image = CreateCGImageFromPixelBuffer(buffer);
+ layer->setContents(image);
+ CGImageRelease(image);
- CGImageRef image = CreateCGImageFromPixelBuffer(buffer);
- layer->setContents(image);
- CGImageRelease(image);
-
- if (attachments)
- CFRelease(attachments);
+ buffer.unlockBaseAddress();
+ layer->rootLayer()->setNeedsRender();
+ }
+ } else
+#endif
+ m_player->repaint();
- buffer.unlockBaseAddress();
- layer->rootLayer()->setNeedsRender();
- }
m_visualContext->task();
-#endif
}
static HashSet<String> mimeTypeCache()
@@ -886,8 +896,6 @@ void MediaPlayerPrivateQuickTimeVisualContext::setUpVideoRendering()
if (currentMode == MediaRenderingMovieLayer || preferredMode == MediaRenderingMovieLayer)
m_player->mediaPlayerClient()->mediaPlayerRenderingModeChanged(m_player);
#endif
-
- m_visualContext->setMovie(m_movie.get());
}
void MediaPlayerPrivateQuickTimeVisualContext::tearDownVideoRendering()
@@ -896,8 +904,6 @@ void MediaPlayerPrivateQuickTimeVisualContext::tearDownVideoRendering()
if (m_qtVideoLayer)
destroyLayerForMovie();
#endif
-
- m_visualContext->setMovie(0);
}
bool MediaPlayerPrivateQuickTimeVisualContext::hasSetUpVideoRendering() const
diff --git a/WebCore/platform/graphics/win/QTMovieVisualContext.h b/WebCore/platform/graphics/win/QTMovieVisualContext.h
index 7afe589..8846416 100644
--- a/WebCore/platform/graphics/win/QTMovieVisualContext.h
+++ b/WebCore/platform/graphics/win/QTMovieVisualContext.h
@@ -38,6 +38,7 @@
#include <WTF/OwnPtr.h>
#include <WTF/RefCounted.h>
+typedef const struct __CFDictionary* CFDictionaryRef;
typedef struct OpaqueQTVisualContext* QTVisualContextRef;
// QTCVTimeStamp is a struct containing only a CVTimeStamp. This is to
diff --git a/WebCore/platform/graphics/win/QTPixelBuffer.cpp b/WebCore/platform/graphics/win/QTPixelBuffer.cpp
index 657b68e..f874287 100644
--- a/WebCore/platform/graphics/win/QTPixelBuffer.cpp
+++ b/WebCore/platform/graphics/win/QTPixelBuffer.cpp
@@ -172,11 +172,6 @@ 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 22f8ba4..3af2197 100644
--- a/WebCore/platform/graphics/win/QTPixelBuffer.h
+++ b/WebCore/platform/graphics/win/QTPixelBuffer.h
@@ -38,7 +38,6 @@ 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.
@@ -75,7 +74,6 @@ 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/WKCACFContextFlusher.cpp b/WebCore/platform/graphics/win/WKCACFContextFlusher.cpp
index e97b530..1685a30 100644
--- a/WebCore/platform/graphics/win/WKCACFContextFlusher.cpp
+++ b/WebCore/platform/graphics/win/WKCACFContextFlusher.cpp
@@ -52,8 +52,8 @@ void WKCACFContextFlusher::addContext(CACFContextRef context)
{
ASSERT(context);
- m_contexts.add(context);
- CFRetain(context);
+ if (m_contexts.add(context).second)
+ CFRetain(context);
}
void WKCACFContextFlusher::removeContext(CACFContextRef context)
diff --git a/WebCore/platform/graphics/win/WKCACFLayer.cpp b/WebCore/platform/graphics/win/WKCACFLayer.cpp
index 4a0461d..3f332d8 100644
--- a/WebCore/platform/graphics/win/WKCACFLayer.cpp
+++ b/WebCore/platform/graphics/win/WKCACFLayer.cpp
@@ -200,12 +200,12 @@ bool WKCACFLayer::isTransformLayer() const
void WKCACFLayer::addSublayer(PassRefPtr<WKCACFLayer> sublayer)
{
- insertSublayer(sublayer, numSublayers());
+ insertSublayer(sublayer, sublayerCount());
}
-void WKCACFLayer::insertSublayer(PassRefPtr<WKCACFLayer> sublayer, size_t index)
+void WKCACFLayer::internalInsertSublayer(PassRefPtr<WKCACFLayer> sublayer, size_t index)
{
- index = min(index, numSublayers());
+ index = min(index, sublayerCount());
sublayer->removeFromSuperlayer();
CACFLayerInsertSublayer(layer(), sublayer->layer(), index);
setNeedsCommit();
@@ -218,7 +218,7 @@ void WKCACFLayer::insertSublayerAboveLayer(PassRefPtr<WKCACFLayer> sublayer, con
return;
}
- int referenceIndex = indexOfSublayer(reference);
+ int referenceIndex = internalIndexOfSublayer(reference);
if (referenceIndex == -1) {
addSublayer(sublayer);
return;
@@ -234,7 +234,7 @@ void WKCACFLayer::insertSublayerBelowLayer(PassRefPtr<WKCACFLayer> sublayer, con
return;
}
- int referenceIndex = indexOfSublayer(reference);
+ int referenceIndex = internalIndexOfSublayer(reference);
if (referenceIndex == -1) {
addSublayer(sublayer);
return;
@@ -251,7 +251,7 @@ void WKCACFLayer::replaceSublayer(WKCACFLayer* reference, PassRefPtr<WKCACFLayer
if (reference == newLayer)
return;
- int referenceIndex = indexOfSublayer(reference);
+ int referenceIndex = internalIndexOfSublayer(reference);
ASSERT(referenceIndex != -1);
if (referenceIndex == -1)
return;
@@ -264,6 +264,25 @@ void WKCACFLayer::replaceSublayer(WKCACFLayer* reference, PassRefPtr<WKCACFLayer
}
}
+size_t WKCACFLayer::internalSublayerCount() const
+{
+ CFArrayRef sublayers = CACFLayerGetSublayers(layer());
+ return sublayers ? CFArrayGetCount(sublayers) : 0;
+}
+
+void WKCACFLayer::adoptSublayers(WKCACFLayer* source)
+{
+ // We will use setSublayers() because it properly nulls
+ // out the superlayer pointer.
+ Vector<RefPtr<WKCACFLayer> > sublayers;
+ size_t n = source->sublayerCount();
+
+ for (size_t i = 0; i < n; ++i)
+ sublayers.append(source->internalSublayerAtIndex(i));
+
+ setSublayers(sublayers);
+}
+
void WKCACFLayer::removeFromSuperlayer()
{
WKCACFLayer* superlayer = this->superlayer();
@@ -274,22 +293,25 @@ void WKCACFLayer::removeFromSuperlayer()
superlayer->setNeedsCommit();
}
-const WKCACFLayer* WKCACFLayer::sublayerAtIndex(int index) const
+WKCACFLayer* WKCACFLayer::internalSublayerAtIndex(int index) const
{
CFArrayRef sublayers = CACFLayerGetSublayers(layer());
- if (index < 0 || CFArrayGetCount(sublayers) <= index)
+ if (!sublayers || index < 0 || CFArrayGetCount(sublayers) <= index)
return 0;
return layer(static_cast<CACFLayerRef>(const_cast<void*>(CFArrayGetValueAtIndex(sublayers, index))));
}
-int WKCACFLayer::indexOfSublayer(const WKCACFLayer* reference)
+int WKCACFLayer::internalIndexOfSublayer(const WKCACFLayer* reference)
{
CACFLayerRef ref = reference->layer();
if (!ref)
return -1;
CFArrayRef sublayers = CACFLayerGetSublayers(layer());
+ if (!sublayers)
+ return -1;
+
size_t n = CFArrayGetCount(sublayers);
for (size_t i = 0; i < n; ++i)
@@ -321,19 +343,6 @@ 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)
- setNeedsDisplay();
-}
-
void WKCACFLayer::setContentsGravity(ContentsGravityType type)
{
CACFLayerSetContentsGravity(layer(), toCACFContentsGravityType(type));
@@ -374,13 +383,13 @@ WKCACFLayer* WKCACFLayer::rootLayer() const
return layer;
}
-void WKCACFLayer::removeAllSublayers()
+void WKCACFLayer::internalRemoveAllSublayers()
{
CACFLayerSetSublayers(layer(), 0);
setNeedsCommit();
}
-void WKCACFLayer::setSublayers(const Vector<RefPtr<WKCACFLayer> >& sublayers)
+void WKCACFLayer::internalSetSublayers(const Vector<RefPtr<WKCACFLayer> >& sublayers)
{
// Remove all the current sublayers and add the passed layers
CACFLayerSetSublayers(layer(), 0);
@@ -404,15 +413,9 @@ WKCACFLayer* WKCACFLayer::superlayer() const
return WKCACFLayer::layer(super);
}
-void WKCACFLayer::setNeedsDisplay(const CGRect* dirtyRect)
+void WKCACFLayer::internalSetNeedsDisplay(const CGRect* dirtyRect)
{
CACFLayerSetNeedsDisplay(layer(), dirtyRect);
- setNeedsCommit();
-}
-
-void WKCACFLayer::setNeedsDisplay()
-{
- setNeedsDisplay(0);
}
#ifndef NDEBUG
@@ -502,12 +505,12 @@ void WKCACFLayer::printLayer(int indent) const
}
// Print sublayers if needed
- int n = numSublayers();
+ int n = sublayerCount();
if (n > 0) {
printIndent(indent + 1);
fprintf(stderr, "(sublayers\n");
for (int i = 0; i < n; ++i)
- sublayerAtIndex(i)->printLayer(indent + 2);
+ internalSublayerAtIndex(i)->printLayer(indent + 2);
printIndent(indent + 1);
fprintf(stderr, ")\n");
diff --git a/WebCore/platform/graphics/win/WKCACFLayer.h b/WebCore/platform/graphics/win/WKCACFLayer.h
index f1b2613..bdc427e 100644
--- a/WebCore/platform/graphics/win/WKCACFLayer.h
+++ b/WebCore/platform/graphics/win/WKCACFLayer.h
@@ -60,9 +60,14 @@ public:
virtual ~WKCACFLayer();
virtual void setNeedsRender() { }
+
virtual void drawInContext(PlatformGraphicsContext*) { }
- virtual void setNeedsDisplay(const CGRect* dirtyRect);
- void setNeedsDisplay();
+
+ void setNeedsDisplay(const CGRect* dirtyRect = 0)
+ {
+ internalSetNeedsDisplay(dirtyRect);
+ setNeedsCommit();
+ }
// Makes this layer the root when the passed context is rendered
void becomeRootLayerForContext(CACFContextRef);
@@ -113,10 +118,18 @@ public:
bool isTransformLayer() const;
void addSublayer(PassRefPtr<WKCACFLayer> sublayer);
- void insertSublayer(PassRefPtr<WKCACFLayer>, size_t index);
void insertSublayerAboveLayer(PassRefPtr<WKCACFLayer>, const WKCACFLayer* reference);
void insertSublayerBelowLayer(PassRefPtr<WKCACFLayer>, const WKCACFLayer* reference);
void replaceSublayer(WKCACFLayer* reference, PassRefPtr<WKCACFLayer>);
+ void adoptSublayers(WKCACFLayer* source);
+
+ void removeAllSublayers() { internalRemoveAllSublayers(); }
+ void setSublayers(const Vector<RefPtr<WKCACFLayer> >& sublayers) { internalSetSublayers(sublayers); }
+
+ void insertSublayer(PassRefPtr<WKCACFLayer> layer, size_t index) { internalInsertSublayer(layer, index); }
+
+ size_t sublayerCount() const { return internalSublayerCount(); }
+
void removeFromSuperlayer();
WKCACFLayer* ancestorOrSelfWithSuperlayer(WKCACFLayer*) const;
@@ -136,7 +149,7 @@ public:
void setBorderWidth(CGFloat width) { CACFLayerSetBorderWidth(layer(), width); setNeedsCommit(); }
CGFloat borderWidth() const { return CACFLayerGetBorderWidth(layer()); }
- void setBounds(const CGRect&);
+ virtual void setBounds(const CGRect&);
CGRect bounds() const { return CACFLayerGetBounds(layer()); }
void setClearsContext(bool clears) { CACFLayerSetClearsContext(layer(), clears); setNeedsCommit(); }
@@ -160,9 +173,6 @@ public:
void setFilters(CFArrayRef filters) { CACFLayerSetFilters(layer(), filters); setNeedsCommit(); }
CFArrayRef filters() const { return CACFLayerGetFilters(layer()); }
- 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 +216,6 @@ public:
void setSortsSublayers(bool sorts) { CACFLayerSetSortsSublayers(layer(), sorts); setNeedsCommit(); }
bool sortsSublayers() const { return CACFLayerGetSortsSublayers(layer()); }
- void removeAllSublayers();
-
- void setSublayers(const Vector<RefPtr<WKCACFLayer> >&);
-
void setSublayerTransform(const CATransform3D& transform) { CACFLayerSetSublayerTransform(layer(), transform); setNeedsCommit(); }
CATransform3D sublayerTransform() const { return CACFLayerGetSublayerTransform(layer()); }
@@ -231,28 +237,30 @@ protected:
void setNeedsCommit();
-private:
CACFLayerRef layer() const { return m_layer.get(); }
- size_t numSublayers() const
- {
- CFArrayRef sublayers = CACFLayerGetSublayers(layer());
- return sublayers ? CFArrayGetCount(sublayers) : 0;
- }
+ // This should only be called from removeFromSuperlayer.
+ void removeSublayer(const WKCACFLayer*);
+
+ // Methods to be overridden for sublayer and rendering management
+ virtual WKCACFLayer* internalSublayerAtIndex(int) const;
- const WKCACFLayer* sublayerAtIndex(int) const;
-
// Returns the index of the passed layer in this layer's sublayers list
// or -1 if not found
- int indexOfSublayer(const WKCACFLayer*);
+ virtual int internalIndexOfSublayer(const WKCACFLayer*);
- // This should only be called from removeFromSuperlayer.
- void removeSublayer(const WKCACFLayer*);
+ virtual size_t internalSublayerCount() const;
+ virtual void internalInsertSublayer(PassRefPtr<WKCACFLayer>, size_t index);
+ virtual void internalRemoveAllSublayers();
+ virtual void internalSetSublayers(const Vector<RefPtr<WKCACFLayer> >&);
+
+ virtual void internalSetNeedsDisplay(const CGRect* dirtyRect);
#ifndef NDEBUG
// Print this layer and its children to the console
void printLayer(int indent) const;
#endif
+private:
RetainPtr<CACFLayerRef> m_layer;
bool m_needsDisplayOnBoundsChange;
};
diff --git a/WebCore/platform/graphics/win/WKCACFLayerRenderer.cpp b/WebCore/platform/graphics/win/WKCACFLayerRenderer.cpp
index 994d079..0ee61f3 100644
--- a/WebCore/platform/graphics/win/WKCACFLayerRenderer.cpp
+++ b/WebCore/platform/graphics/win/WKCACFLayerRenderer.cpp
@@ -198,7 +198,7 @@ bool WKCACFLayerRenderer::acceleratedCompositingAvailable()
return available;
}
- OwnPtr<WKCACFLayerRenderer> testLayerRenderer = WKCACFLayerRenderer::create();
+ OwnPtr<WKCACFLayerRenderer> testLayerRenderer = WKCACFLayerRenderer::create(0);
testLayerRenderer->setHostWindow(testWindow);
available = testLayerRenderer->createRenderer();
::DestroyWindow(testWindow);
@@ -215,16 +215,21 @@ void WKCACFLayerRenderer::didFlushContext(CACFContextRef context)
window->renderSoon();
}
-PassOwnPtr<WKCACFLayerRenderer> WKCACFLayerRenderer::create()
+PassOwnPtr<WKCACFLayerRenderer> WKCACFLayerRenderer::create(WKCACFLayerRendererClient* client)
{
if (!acceleratedCompositingAvailable())
return 0;
- return new WKCACFLayerRenderer;
+ return new WKCACFLayerRenderer(client);
}
-WKCACFLayerRenderer::WKCACFLayerRenderer()
- : m_triedToCreateD3DRenderer(false)
- , m_renderContext(0)
+WKCACFLayerRenderer::WKCACFLayerRenderer(WKCACFLayerRendererClient* client)
+ : m_client(client)
+ , m_mightBeAbleToCreateDeviceLater(true)
+ , m_rootLayer(WKCACFRootLayer::create(this))
+ , m_scrollLayer(WKCACFLayer::create(WKCACFLayer::Layer))
+ , m_clipLayer(WKCACFLayer::create(WKCACFLayer::Layer))
+ , m_context(AdoptCF, CACFContextCreate(0))
+ , m_renderContext(static_cast<CARenderContext*>(CACFContextGetRenderContext(m_context.get())))
, m_renderer(0)
, m_hostWindow(0)
, m_renderTimer(this, &WKCACFLayerRenderer::renderTimerFired)
@@ -233,6 +238,37 @@ WKCACFLayerRenderer::WKCACFLayerRenderer()
, m_backingStoreDirty(false)
, m_mustResetLostDeviceBeforeRendering(false)
{
+ windowsForContexts().set(m_context.get(), this);
+
+ // Under the root layer, we have a clipping layer to clip the content,
+ // that contains a scroll layer that we use for scrolling the content.
+ // The root layer is the size of the client area of the window.
+ // The clipping layer is the size of the WebView client area (window less the scrollbars).
+ // The scroll layer is the size of the root child layer.
+ // Resizing the window will change the bounds of the rootLayer and the clip layer and will not
+ // cause any repositioning.
+ // Scrolling will affect only the position of the scroll layer without affecting the bounds.
+
+ m_rootLayer->setName("WKCACFLayerRenderer rootLayer");
+ m_clipLayer->setName("WKCACFLayerRenderer clipLayer");
+ m_scrollLayer->setName("WKCACFLayerRenderer scrollLayer");
+
+ m_rootLayer->addSublayer(m_clipLayer);
+ m_clipLayer->addSublayer(m_scrollLayer);
+ m_clipLayer->setMasksToBounds(true);
+ m_rootLayer->setAnchorPoint(CGPointMake(0, 0));
+ m_scrollLayer->setAnchorPoint(CGPointMake(0, 1));
+ m_clipLayer->setAnchorPoint(CGPointMake(0, 1));
+
+#ifndef NDEBUG
+ CGColorRef debugColor = createCGColor(Color(255, 0, 0, 204));
+ m_rootLayer->setBackgroundColor(debugColor);
+ CGColorRelease(debugColor);
+#endif
+
+ if (m_context)
+ m_rootLayer->becomeRootLayerForContext(m_context.get());
+
#ifndef NDEBUG
char* printTreeFlag = getenv("CA_PRINT_TREE");
m_printTree = printTreeFlag && atoi(printTreeFlag);
@@ -306,10 +342,10 @@ void WKCACFLayerRenderer::setNeedsDisplay()
bool WKCACFLayerRenderer::createRenderer()
{
- if (m_triedToCreateD3DRenderer)
+ if (m_d3dDevice || !m_mightBeAbleToCreateDeviceLater)
return m_d3dDevice;
- m_triedToCreateD3DRenderer = true;
+ m_mightBeAbleToCreateDeviceLater = false;
D3DPRESENT_PARAMETERS parameters = initialPresentationParameters();
if (!d3d() || !::IsWindow(m_hostWindow))
@@ -326,9 +362,31 @@ bool WKCACFLayerRenderer::createRenderer()
parameters.BackBufferHeight = 1;
}
+ D3DCAPS9 d3dCaps;
+ if (FAILED(d3d()->GetDeviceCaps(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, &d3dCaps)))
+ return false;
+
+ DWORD behaviorFlags = D3DCREATE_FPU_PRESERVE;
+ if ((d3dCaps.DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT) && d3dCaps.VertexProcessingCaps)
+ behaviorFlags |= D3DCREATE_HARDWARE_VERTEXPROCESSING;
+ else
+ behaviorFlags |= D3DCREATE_SOFTWARE_VERTEXPROCESSING;
+
COMPtr<IDirect3DDevice9> device;
- if (FAILED(d3d()->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, m_hostWindow, D3DCREATE_HARDWARE_VERTEXPROCESSING | D3DCREATE_FPU_PRESERVE, &parameters, &device)))
+ if (FAILED(d3d()->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, m_hostWindow, behaviorFlags, &parameters, &device))) {
+ // In certain situations (e.g., shortly after waking from sleep), Direct3DCreate9() will
+ // return an IDirect3D9 for which IDirect3D9::CreateDevice will always fail. In case we
+ // have one of these bad IDirect3D9s, get rid of it so we'll fetch a new one the next time
+ // we want to call CreateDevice.
+ s_d3d->Release();
+ s_d3d = 0;
+
+ // Even if we don't have a bad IDirect3D9, in certain situations (e.g., shortly after
+ // waking from sleep), CreateDevice will fail, but will later succeed if called again.
+ m_mightBeAbleToCreateDeviceLater = true;
+
return false;
+ }
// Now that we've created the IDirect3DDevice9 based on the capabilities we
// got from the IDirect3D9 global object, we requery the device for its
@@ -349,48 +407,10 @@ bool WKCACFLayerRenderer::createRenderer()
m_d3dDevice->SetTransform(D3DTS_PROJECTION, &projection);
- m_context.adoptCF(CACFContextCreate(0));
- windowsForContexts().set(m_context.get(), this);
-
- m_renderContext = static_cast<CARenderContext*>(CACFContextGetRenderContext(m_context.get()));
m_renderer = CARenderOGLNew(&kCARenderDX9Callbacks, m_d3dDevice.get(), 0);
- // Create the root hierarchy.
- // Under the root layer, we have a clipping layer to clip the content,
- // that contains a scroll layer that we use for scrolling the content.
- // The root layer is the size of the client area of the window.
- // The clipping layer is the size of the WebView client area (window less the scrollbars).
- // The scroll layer is the size of the root child layer.
- // Resizing the window will change the bounds of the rootLayer and the clip layer and will not
- // cause any repositioning.
- // Scrolling will affect only the position of the scroll layer without affecting the bounds.
-
- m_rootLayer = WKCACFRootLayer::create(this);
- m_rootLayer->setName("WKCACFLayerRenderer rootLayer");
-
- m_clipLayer = WKCACFLayer::create(WKCACFLayer::Layer);
- m_clipLayer->setName("WKCACFLayerRenderer clipLayer");
-
- m_scrollLayer = WKCACFLayer::create(WKCACFLayer::Layer);
- m_scrollLayer->setName("WKCACFLayerRenderer scrollLayer");
-
- m_rootLayer->addSublayer(m_clipLayer);
- m_clipLayer->addSublayer(m_scrollLayer);
- m_clipLayer->setMasksToBounds(true);
- m_scrollLayer->setAnchorPoint(CGPointMake(0, 1));
- m_clipLayer->setAnchorPoint(CGPointMake(0, 1));
-
-#ifndef NDEBUG
- CGColorRef debugColor = createCGColor(Color(255, 0, 0, 204));
- m_rootLayer->setBackgroundColor(debugColor);
- CGColorRelease(debugColor);
-#endif
-
if (IsWindow(m_hostWindow))
- m_rootLayer->setFrame(bounds());
-
- if (m_context)
- m_rootLayer->becomeRootLayerForContext(m_context.get());
+ m_rootLayer->setBounds(bounds());
return true;
}
@@ -398,6 +418,7 @@ bool WKCACFLayerRenderer::createRenderer()
void WKCACFLayerRenderer::destroyRenderer()
{
if (m_context) {
+ CACFContextSetLayer(m_context.get(), 0);
windowsForContexts().remove(m_context.get());
WKCACFContextFlusher::shared().removeContext(m_context.get());
}
@@ -415,7 +436,7 @@ void WKCACFLayerRenderer::destroyRenderer()
m_scrollLayer = 0;
m_rootChildLayer = 0;
- m_triedToCreateD3DRenderer = false;
+ m_mightBeAbleToCreateDeviceLater = true;
}
void WKCACFLayerRenderer::resize()
@@ -428,7 +449,7 @@ void WKCACFLayerRenderer::resize()
resetDevice(ChangedWindowSize);
if (m_rootLayer) {
- m_rootLayer->setFrame(bounds());
+ m_rootLayer->setBounds(bounds());
WKCACFContextFlusher::shared().flushAllContexts();
updateScrollFrame();
}
@@ -442,8 +463,8 @@ static void getDirtyRects(HWND window, Vector<CGRect>& outRects)
if (!GetClientRect(window, &clientRect))
return;
- HRGN region = CreateRectRgn(0, 0, 0, 0);
- int regionType = GetUpdateRgn(window, region, false);
+ OwnPtr<HRGN> region(CreateRectRgn(0, 0, 0, 0));
+ int regionType = GetUpdateRgn(window, region.get(), false);
if (regionType != COMPLEXREGION) {
RECT dirtyRect;
if (GetUpdateRect(window, &dirtyRect, false))
@@ -451,10 +472,10 @@ static void getDirtyRects(HWND window, Vector<CGRect>& outRects)
return;
}
- DWORD dataSize = GetRegionData(region, 0, 0);
+ DWORD dataSize = GetRegionData(region.get(), 0, 0);
OwnArrayPtr<unsigned char> regionDataBuffer(new unsigned char[dataSize]);
RGNDATA* regionData = reinterpret_cast<RGNDATA*>(regionDataBuffer.get());
- if (!GetRegionData(region, dataSize, regionData))
+ if (!GetRegionData(region.get(), dataSize, regionData))
return;
outRects.resize(regionData->rdh.nCount);
@@ -462,8 +483,6 @@ static void getDirtyRects(HWND window, Vector<CGRect>& outRects)
RECT* rect = reinterpret_cast<RECT*>(regionData->Buffer);
for (size_t i = 0; i < outRects.size(); ++i, ++rect)
outRects[i] = winRectToCGRect(*rect, clientRect);
-
- DeleteObject(region);
}
void WKCACFLayerRenderer::renderTimerFired(Timer<WKCACFLayerRenderer>*)
@@ -473,8 +492,12 @@ void WKCACFLayerRenderer::renderTimerFired(Timer<WKCACFLayerRenderer>*)
void WKCACFLayerRenderer::paint()
{
- if (!m_d3dDevice)
+ createRenderer();
+ if (!m_d3dDevice) {
+ if (m_mightBeAbleToCreateDeviceLater)
+ renderSoon();
return;
+ }
if (m_backingStoreDirty) {
// If the backing store is still dirty when we are about to draw the
@@ -500,6 +523,11 @@ void WKCACFLayerRenderer::render(const Vector<CGRect>& dirtyRects)
return;
}
+ if (m_client && !m_client->shouldRender()) {
+ renderSoon();
+ return;
+ }
+
// Flush the root layer to the render tree.
WKCACFContextFlusher::shared().flushAllContexts();
diff --git a/WebCore/platform/graphics/win/WKCACFLayerRenderer.h b/WebCore/platform/graphics/win/WKCACFLayerRenderer.h
index 259c52f..1ff955a 100644
--- a/WebCore/platform/graphics/win/WKCACFLayerRenderer.h
+++ b/WebCore/platform/graphics/win/WKCACFLayerRenderer.h
@@ -49,12 +49,18 @@ namespace WebCore {
class WKCACFRootLayer;
+class WKCACFLayerRendererClient {
+public:
+ virtual ~WKCACFLayerRendererClient() { }
+ virtual bool shouldRender() const = 0;
+};
+
// FIXME: Currently there is a WKCACFLayerRenderer for each WebView and each
// has its own CARenderOGLContext and Direct3DDevice9, which is inefficient.
// (https://bugs.webkit.org/show_bug.cgi?id=31855)
class WKCACFLayerRenderer : public Noncopyable {
public:
- static PassOwnPtr<WKCACFLayerRenderer> create();
+ static PassOwnPtr<WKCACFLayerRenderer> create(WKCACFLayerRendererClient*);
~WKCACFLayerRenderer();
static bool acceleratedCompositingAvailable();
@@ -77,7 +83,7 @@ protected:
WKCACFLayer* rootLayer() const;
private:
- WKCACFLayerRenderer();
+ WKCACFLayerRenderer(WKCACFLayerRendererClient*);
void renderTimerFired(Timer<WKCACFLayerRenderer>*);
@@ -94,10 +100,10 @@ private:
void render(const Vector<CGRect>& dirtyRects = Vector<CGRect>());
void paint();
- bool m_triedToCreateD3DRenderer;
+ WKCACFLayerRendererClient* m_client;
+ bool m_mightBeAbleToCreateDeviceLater;
COMPtr<IDirect3DDevice9> m_d3dDevice;
RefPtr<WKCACFRootLayer> m_rootLayer;
- RefPtr<WKCACFLayer> m_viewLayer;
RefPtr<WKCACFLayer> m_scrollLayer;
RefPtr<WKCACFLayer> m_rootChildLayer;
RefPtr<WKCACFLayer> m_clipLayer;
diff --git a/WebCore/platform/graphics/win/WebLayer.cpp b/WebCore/platform/graphics/win/WebLayer.cpp
new file mode 100755
index 0000000..70a522d
--- /dev/null
+++ b/WebCore/platform/graphics/win/WebLayer.cpp
@@ -0,0 +1,143 @@
+/*
+ * Copyright (C) 2009 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. ``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 COMPUTER, INC. OR
+ * 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 "WebLayer.h"
+
+#include "Font.h"
+#include "GraphicsLayer.h"
+
+namespace WebCore {
+
+using namespace std;
+
+void WebLayer::internalSetNeedsDisplay(const CGRect* dirtyRect)
+{
+ if (m_owner) {
+ if (m_owner->showRepaintCounter()) {
+ CGRect layerBounds = bounds();
+ CGRect repaintCounterRect = layerBounds;
+ // We assume a maximum of 4 digits and a font size of 18.
+ repaintCounterRect.size.width = 80;
+ repaintCounterRect.size.height = 22;
+ if (m_owner->contentsOrientation() == WebCore::GraphicsLayer::CompositingCoordinatesTopDown)
+ repaintCounterRect.origin.y = layerBounds.size.height - (layerBounds.origin.y + repaintCounterRect.size.height);
+ WKCACFLayer::internalSetNeedsDisplay(&repaintCounterRect);
+ }
+ if (dirtyRect && m_owner->contentsOrientation() == WebCore::GraphicsLayer::CompositingCoordinatesTopDown) {
+ CGRect flippedDirtyRect = *dirtyRect;
+ flippedDirtyRect.origin.y = bounds().size.height - (flippedDirtyRect.origin.y + flippedDirtyRect.size.height);
+ WKCACFLayer::internalSetNeedsDisplay(&flippedDirtyRect);
+ return;
+ }
+ }
+
+ WKCACFLayer::internalSetNeedsDisplay(dirtyRect);
+}
+
+void WebLayer::drawInContext(PlatformGraphicsContext* context)
+{
+ if (!m_owner)
+ return;
+
+ CGContextSaveGState(context);
+
+ CGRect layerBounds = bounds();
+ if (m_owner->contentsOrientation() == WebCore::GraphicsLayer::CompositingCoordinatesTopDown) {
+ CGContextScaleCTM(context, 1, -1);
+ CGContextTranslateCTM(context, 0, -layerBounds.size.height);
+ }
+
+ if (m_owner->client()) {
+ GraphicsContext graphicsContext(context);
+
+ // It's important to get the clip from the context, because it may be significantly
+ // smaller than the layer bounds (e.g. tiled layers)
+ CGRect clipBounds = CGContextGetClipBoundingBox(context);
+ IntRect clip(enclosingIntRect(clipBounds));
+ m_owner->paintGraphicsLayerContents(graphicsContext, clip);
+ }
+#ifndef NDEBUG
+ else {
+ ASSERT_NOT_REACHED();
+
+ // FIXME: ideally we'd avoid calling -setNeedsDisplay on a layer that is a plain color,
+ // so CA never makes backing store for it (which is what -setNeedsDisplay will do above).
+ CGContextSetRGBFillColor(context, 0.0f, 1.0f, 0.0f, 1.0f);
+ CGContextFillRect(context, layerBounds);
+ }
+#endif
+
+ if (m_owner->showRepaintCounter()) {
+ String text = String::format("%d", m_owner->incrementRepaintCount());;
+
+ CGContextSaveGState(context);
+
+ // Make the background of the counter the same as the border color,
+ // unless there is no border, then make it red
+ float borderWidth = CACFLayerGetBorderWidth(layer());
+ if (borderWidth > 0) {
+ CGColorRef borderColor = CACFLayerGetBorderColor(layer());
+ const CGFloat* colors = CGColorGetComponents(borderColor);
+ CGContextSetRGBFillColor(context, colors[0], colors[1], colors[2], colors[3]);
+ } else
+ CGContextSetRGBFillColor(context, 1.0f, 0.0f, 0.0f, 0.8f);
+
+ CGRect aBounds = layerBounds;
+
+ aBounds.size.width = 10 + 10 * text.length();
+ aBounds.size.height = 22;
+ CGContextFillRect(context, aBounds);
+
+ FontDescription desc;
+
+ NONCLIENTMETRICS metrics;
+ metrics.cbSize = sizeof(metrics);
+ SystemParametersInfo(SPI_GETNONCLIENTMETRICS, metrics.cbSize, &metrics, 0);
+ FontFamily family;
+ family.setFamily(metrics.lfSmCaptionFont.lfFaceName);
+ desc.setFamily(family);
+
+ desc.setComputedSize(18);
+
+ Font font = Font(desc, 0, 0);
+ font.update(0);
+
+ GraphicsContext cg(context);
+ cg.setFillColor(Color::black, DeviceColorSpace);
+ cg.drawText(font, TextRun(text), IntPoint(aBounds.origin.x + 5, aBounds.origin.y + 17));
+
+ CGContextRestoreGState(context);
+ }
+
+ CGContextRestoreGState(context);
+}
+
+}
+
+#endif // USE(ACCELERATED_COMPOSITING)
diff --git a/WebCore/platform/graphics/win/WebLayer.h b/WebCore/platform/graphics/win/WebLayer.h
new file mode 100755
index 0000000..8dab5cc
--- /dev/null
+++ b/WebCore/platform/graphics/win/WebLayer.h
@@ -0,0 +1,62 @@
+/*
+ * 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. ``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 COMPUTER, INC. OR
+ * 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 WebLayer_h
+#define WebLayer_h
+
+#if USE(ACCELERATED_COMPOSITING)
+
+#include "WKCACFLayer.h"
+
+namespace WebCore {
+
+class GraphicsLayer;
+
+class WebLayer : public WKCACFLayer {
+public:
+ static PassRefPtr<WKCACFLayer> create(LayerType layerType, GraphicsLayer* owner)
+ {
+ return adoptRef(new WebLayer(layerType, owner));
+ }
+
+ virtual void drawInContext(PlatformGraphicsContext*);
+
+protected:
+ WebLayer(LayerType layerType, GraphicsLayer* owner)
+ : WKCACFLayer(layerType)
+ , m_owner(owner)
+ {
+ }
+
+ virtual void internalSetNeedsDisplay(const CGRect* dirtyRect);
+
+ GraphicsLayer* m_owner;
+};
+
+}
+
+#endif // USE(ACCELERATED_COMPOSITING)
+
+#endif // WebLayer_h
diff --git a/WebCore/platform/graphics/win/WebTiledLayer.cpp b/WebCore/platform/graphics/win/WebTiledLayer.cpp
new file mode 100755
index 0000000..0cf3f9d
--- /dev/null
+++ b/WebCore/platform/graphics/win/WebTiledLayer.cpp
@@ -0,0 +1,274 @@
+/*
+ * Copyright (C) 2009 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. ``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 COMPUTER, INC. OR
+ * 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 "WebTiledLayer.h"
+
+#include "GraphicsLayer.h"
+#include "WKCACFLayerRenderer.h"
+
+namespace WebCore {
+
+using namespace std;
+
+void WebTiledLayer::tileDisplayCallback(CACFLayerRef layer, CGContextRef context)
+{
+ static_cast<WebTiledLayer*>(CACFLayerGetUserData(layer))->drawTile(layer, context);
+}
+
+PassRefPtr<WebTiledLayer> WebTiledLayer::create(const CGSize& tileSize, GraphicsLayer* owner)
+{
+ ASSERT(WKCACFLayerRenderer::acceleratedCompositingAvailable());
+ return adoptRef(new WebTiledLayer(tileSize, owner));
+}
+
+WebTiledLayer::WebTiledLayer(const CGSize& tileSize, GraphicsLayer* owner)
+ : WebLayer(WKCACFLayer::Layer, owner)
+ , m_tileSize(tileSize)
+ , m_constrainedSize(constrainedSize(bounds().size))
+{
+ // Tiled layers are placed in a child layer that is always the first child of the TiledLayer
+ m_tileParent.adoptCF(CACFLayerCreate(kCACFLayer));
+ CACFLayerInsertSublayer(layer(), m_tileParent.get(), 0);
+
+ updateTiles();
+}
+
+WebTiledLayer::~WebTiledLayer()
+{
+}
+
+void WebTiledLayer::setBounds(const CGRect& rect)
+{
+ if (CGRectEqualToRect(rect, bounds()))
+ return;
+
+ WebLayer::setBounds(rect);
+ m_constrainedSize = constrainedSize(rect.size);
+ updateTiles();
+}
+
+void WebTiledLayer::internalSetNeedsDisplay(const CGRect* dirtyRect)
+{
+ // FIXME: Only setNeedsDisplay for tiles that are currently visible
+ int numTileLayers = tileCount();
+ for (int i = 0; i < numTileLayers; ++i)
+ CACFLayerSetNeedsDisplay(tileAtIndex(i), dirtyRect);
+
+ if (m_owner->showRepaintCounter()) {
+ CGRect layerBounds = bounds();
+ CGRect indicatorRect = CGRectMake(layerBounds.origin.x, layerBounds.origin.y, 80, 25);
+ CACFLayerSetNeedsDisplay(tileAtIndex(0), &indicatorRect);
+ }
+}
+
+size_t WebTiledLayer::internalSublayerCount() const
+{
+ ASSERT(WebLayer::internalSublayerCount() > 0);
+
+ // Subtract 1 to account for the tile parent layer
+ return WebLayer::internalSublayerCount() - 1;
+}
+
+void WebTiledLayer::internalRemoveAllSublayers()
+{
+ // Restore the tile parent after removal
+ WebLayer::internalRemoveAllSublayers();
+ CACFLayerInsertSublayer(layer(), m_tileParent.get(), 0);
+}
+
+void WebTiledLayer::internalSetSublayers(const Vector<RefPtr<WKCACFLayer> >& sublayers)
+{
+ // Preserve the tile parent after set
+ WebLayer::internalSetSublayers(sublayers);
+ CACFLayerInsertSublayer(layer(), m_tileParent.get(), 0);
+}
+
+void WebTiledLayer::internalInsertSublayer(PassRefPtr<WKCACFLayer> layer, size_t index)
+{
+ // Add 1 to account for the tile parent layer
+ WebLayer::internalInsertSublayer(layer, index + 1);
+}
+
+WKCACFLayer* WebTiledLayer::internalSublayerAtIndex(int i) const
+{
+ // Add 1 to account for the tile parent layer
+ return WebLayer::internalSublayerAtIndex(i + 1);
+}
+
+int WebTiledLayer::internalIndexOfSublayer(const WKCACFLayer* layer)
+{
+ int i = WebLayer::internalIndexOfSublayer(layer);
+
+ // Add 1 to account for the tile parent layer (but be safe about it)
+ return (i > 0) ? i - 1 : -1;
+}
+
+CGSize WebTiledLayer::constrainedSize(const CGSize& size) const
+{
+ const int cMaxTileCount = 512;
+ const float cSqrtMaxTileCount = sqrtf(cMaxTileCount);
+
+ CGSize constrainedSize = size;
+
+ int tileColumns = ceilf(constrainedSize.width / m_tileSize.width);
+ int tileRows = ceilf(constrainedSize.height / m_tileSize.height);
+ int numTiles = tileColumns * tileRows;
+
+ // If number of tiles vertically or horizontally is < sqrt(cMaxTileCount)
+ // just shorten the longer dimension. Otherwise shorten both dimensions
+ // according to the ratio of width to height
+
+ if (numTiles > cMaxTileCount) {
+ if (tileRows < cSqrtMaxTileCount)
+ tileColumns = floorf(cMaxTileCount / tileRows);
+ else if (tileColumns < cSqrtMaxTileCount)
+ tileRows = floorf(cMaxTileCount / tileColumns);
+ else {
+ tileRows = ceilf(sqrtf(cMaxTileCount * constrainedSize.height / constrainedSize.width));
+ tileColumns = floorf(cMaxTileCount / tileRows);
+ }
+
+ constrainedSize.width = tileColumns * m_tileSize.width;
+ constrainedSize.height = tileRows * m_tileSize.height;
+ }
+
+ return constrainedSize;
+}
+
+void WebTiledLayer::addTile()
+{
+ RetainPtr<CACFLayerRef> newLayer(AdoptCF, CACFLayerCreate(kCACFLayer));
+ CACFLayerSetAnchorPoint(newLayer.get(), CGPointMake(0, 1));
+ CACFLayerSetUserData(newLayer.get(), this);
+ CACFLayerSetDisplayCallback(newLayer.get(), tileDisplayCallback);
+
+ CFArrayRef sublayers = CACFLayerGetSublayers(m_tileParent.get());
+ CACFLayerInsertSublayer(m_tileParent.get(), newLayer.get(), sublayers ? CFArrayGetCount(sublayers) : 0);
+
+ if (m_owner->showDebugBorders()) {
+ CGColorRef borderColor = createCGColor(Color(128, 0, 128, 180));
+ CACFLayerSetBorderColor(newLayer.get(), borderColor);
+ CGColorRelease(borderColor);
+ CACFLayerSetBorderWidth(newLayer.get(), 2);
+ }
+}
+
+void WebTiledLayer::removeTile()
+{
+ CACFLayerRemoveFromSuperlayer(tileAtIndex(tileCount() - 1));
+}
+
+CACFLayerRef WebTiledLayer::tileAtIndex(int index)
+{
+ CFArrayRef sublayers = CACFLayerGetSublayers(m_tileParent.get());
+ if (!sublayers || index < 0 || index >= tileCount() )
+ return 0;
+
+ return static_cast<CACFLayerRef>(const_cast<void*>(CFArrayGetValueAtIndex(sublayers, index)));
+}
+
+int WebTiledLayer::tileCount() const
+{
+ CFArrayRef sublayers = CACFLayerGetSublayers(m_tileParent.get());
+ return sublayers ? CFArrayGetCount(sublayers) : 0;
+}
+
+void WebTiledLayer::updateTiles()
+{
+ // FIXME: In addition to redoing the number of tiles, we need to only render and have backing
+ // store for visible layers
+ int numTilesHorizontal = ceil(m_constrainedSize.width / m_tileSize.width);
+ int numTilesVertical = ceil(m_constrainedSize.height / m_tileSize.height);
+ int numTilesTotal = numTilesHorizontal * numTilesVertical;
+
+ int numTilesToChange = numTilesTotal - tileCount();
+ if (numTilesToChange >= 0) {
+ // Add new tiles
+ for (int i = 0; i < numTilesToChange; ++i)
+ addTile();
+ } else {
+ // Remove old tiles
+ numTilesToChange = -numTilesToChange;
+ for (int i = 0; i < numTilesToChange; ++i)
+ removeTile();
+ }
+
+ // Set coordinates for all tiles
+ CFArrayRef tileArray = CACFLayerGetSublayers(m_tileParent.get());
+
+ for (int i = 0; i < numTilesHorizontal; ++i) {
+ for (int j = 0; j < numTilesVertical; ++j) {
+ CACFLayerRef tile = static_cast<CACFLayerRef>(const_cast<void*>(CFArrayGetValueAtIndex(tileArray, i * numTilesVertical + j)));
+ CACFLayerSetPosition(tile, CGPointMake(i * m_tileSize.width, j * m_tileSize.height));
+ int width = min(m_tileSize.width, m_constrainedSize.width - i * m_tileSize.width);
+ int height = min(m_tileSize.height, m_constrainedSize.height - j * m_tileSize.height);
+ CACFLayerSetBounds(tile, CGRectMake(i * m_tileSize.width, j * m_tileSize.height, width, height));
+
+ // Flip Y to compensate for the flipping that happens during render to match the CG context coordinate space
+ CATransform3D transform = CATransform3DMakeScale(1, -1, 1);
+ CATransform3DTranslate(transform, 0, height, 0);
+ CACFLayerSetTransform(tile, transform);
+
+#ifndef NDEBUG
+ String name = "Tile (" + String::number(i) + "," + String::number(j) + ")";
+ CACFLayerSetName(tile, RetainPtr<CFStringRef>(AdoptCF, name.createCFString()).get());
+#endif
+ }
+ }
+}
+
+void WebTiledLayer::drawTile(CACFLayerRef tile, CGContextRef context)
+{
+ CGPoint tilePosition = CACFLayerGetPosition(tile);
+ CGRect tileBounds = CACFLayerGetBounds(tile);
+
+ CGContextSaveGState(context);
+
+ // Transform context to be at the origin of the parent layer
+ CGContextTranslateCTM(context, -tilePosition.x, -tilePosition.y);
+
+ // Set the context clipping rectangle to the current tile
+ CGContextClipToRect(context, CGRectMake(tilePosition.x, tilePosition.y, tileBounds.size.width, tileBounds.size.height));
+
+ if (m_owner->contentsOrientation() == WebCore::GraphicsLayer::CompositingCoordinatesTopDown) {
+ // If the layer is rendering top-down, it will flip the coordinates in y. Tiled layers are
+ // already flipping, so we need to undo that here.
+ CGContextTranslateCTM(context, 0, bounds().size.height);
+ CGContextScaleCTM(context, 1, -1);
+ }
+
+ // Draw the tile
+ drawInContext(context);
+
+ CGContextRestoreGState(context);
+}
+
+}
+
+#endif // USE(ACCELERATED_COMPOSITING)
diff --git a/WebCore/platform/graphics/win/WebTiledLayer.h b/WebCore/platform/graphics/win/WebTiledLayer.h
new file mode 100755
index 0000000..ed61656
--- /dev/null
+++ b/WebCore/platform/graphics/win/WebTiledLayer.h
@@ -0,0 +1,80 @@
+/*
+ * 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. ``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 COMPUTER, INC. OR
+ * 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 WebTiledLayer_h
+#define WebTiledLayer_h
+
+#if USE(ACCELERATED_COMPOSITING)
+
+#include "WebLayer.h"
+
+namespace WebCore {
+
+class WebTiledLayer : public WebLayer {
+public:
+ static PassRefPtr<WebTiledLayer> create(const CGSize& tileSize, GraphicsLayer* owner);
+
+ virtual ~WebTiledLayer();
+
+ virtual void setBounds(const CGRect&);
+
+protected:
+ WebTiledLayer(const CGSize& tileSize, GraphicsLayer* owner);
+
+ // Overridden from WKCACFLayer
+ virtual WKCACFLayer* internalSublayerAtIndex(int) const;
+ virtual int internalIndexOfSublayer(const WKCACFLayer*);
+
+ virtual size_t internalSublayerCount() const;
+ virtual void internalInsertSublayer(PassRefPtr<WKCACFLayer>, size_t index);
+
+ virtual void internalRemoveAllSublayers();
+ virtual void internalSetSublayers(const Vector<RefPtr<WKCACFLayer> >&);
+
+ virtual void internalSetNeedsDisplay(const CGRect* dirtyRect);
+
+private:
+ static void tileDisplayCallback(CACFLayerRef, CGContextRef);
+ void drawTile(CACFLayerRef, CGContextRef);
+
+ CGSize constrainedSize(const CGSize& size) const;
+
+ void addTile();
+ void removeTile();
+ CACFLayerRef tileAtIndex(int);
+ int tileCount() const;
+
+ void updateTiles();
+
+ CGSize m_tileSize;
+ CGSize m_constrainedSize;
+ RetainPtr<CACFLayerRef> m_tileParent;
+};
+
+}
+
+#endif // USE(ACCELERATED_COMPOSITING)
+
+#endif // WebTiledLayer_h