summaryrefslogtreecommitdiffstats
path: root/WebCore/platform/graphics/chromium
diff options
context:
space:
mode:
Diffstat (limited to 'WebCore/platform/graphics/chromium')
-rw-r--r--WebCore/platform/graphics/chromium/Canvas2DLayerChromium.cpp6
-rw-r--r--WebCore/platform/graphics/chromium/Canvas2DLayerChromium.h2
-rw-r--r--WebCore/platform/graphics/chromium/ContentLayerChromium.cpp160
-rw-r--r--WebCore/platform/graphics/chromium/ContentLayerChromium.h19
-rw-r--r--WebCore/platform/graphics/chromium/DrawingBufferChromium.cpp2
-rw-r--r--WebCore/platform/graphics/chromium/Extensions3DChromium.h1
-rw-r--r--WebCore/platform/graphics/chromium/FontCacheChromiumWin.cpp183
-rw-r--r--WebCore/platform/graphics/chromium/FontCacheLinux.cpp3
-rw-r--r--WebCore/platform/graphics/chromium/FontChromiumWin.cpp12
-rw-r--r--WebCore/platform/graphics/chromium/FontLinux.cpp71
-rw-r--r--WebCore/platform/graphics/chromium/FontPlatformDataLinux.cpp8
-rw-r--r--WebCore/platform/graphics/chromium/FontPlatformDataLinux.h7
-rw-r--r--WebCore/platform/graphics/chromium/GraphicsLayerChromium.cpp5
-rw-r--r--WebCore/platform/graphics/chromium/GraphicsLayerChromium.h3
-rw-r--r--WebCore/platform/graphics/chromium/ImageLayerChromium.cpp45
-rw-r--r--WebCore/platform/graphics/chromium/ImageLayerChromium.h2
-rw-r--r--WebCore/platform/graphics/chromium/LayerChromium.cpp4
-rw-r--r--WebCore/platform/graphics/chromium/LayerChromium.h18
-rw-r--r--WebCore/platform/graphics/chromium/LayerRendererChromium.cpp198
-rw-r--r--WebCore/platform/graphics/chromium/LayerRendererChromium.h17
-rw-r--r--WebCore/platform/graphics/chromium/LayerTexture.cpp93
-rw-r--r--WebCore/platform/graphics/chromium/LayerTexture.h69
-rw-r--r--WebCore/platform/graphics/chromium/PluginLayerChromium.cpp2
-rw-r--r--WebCore/platform/graphics/chromium/PluginLayerChromium.h2
-rw-r--r--WebCore/platform/graphics/chromium/RenderSurfaceChromium.cpp109
-rw-r--r--WebCore/platform/graphics/chromium/RenderSurfaceChromium.h35
-rw-r--r--WebCore/platform/graphics/chromium/SimpleFontDataChromiumWin.cpp38
-rw-r--r--WebCore/platform/graphics/chromium/SimpleFontDataLinux.cpp36
-rw-r--r--WebCore/platform/graphics/chromium/TextureManager.cpp171
-rw-r--r--WebCore/platform/graphics/chromium/TextureManager.h83
-rw-r--r--WebCore/platform/graphics/chromium/VideoLayerChromium.cpp7
-rw-r--r--WebCore/platform/graphics/chromium/VideoLayerChromium.h2
-rw-r--r--WebCore/platform/graphics/chromium/WebGLLayerChromium.cpp5
-rw-r--r--WebCore/platform/graphics/chromium/WebGLLayerChromium.h2
34 files changed, 1014 insertions, 406 deletions
diff --git a/WebCore/platform/graphics/chromium/Canvas2DLayerChromium.cpp b/WebCore/platform/graphics/chromium/Canvas2DLayerChromium.cpp
index c2cde19..ad961aa 100644
--- a/WebCore/platform/graphics/chromium/Canvas2DLayerChromium.cpp
+++ b/WebCore/platform/graphics/chromium/Canvas2DLayerChromium.cpp
@@ -56,9 +56,9 @@ Canvas2DLayerChromium::~Canvas2DLayerChromium()
layerRendererContext()->deleteTexture(m_textureId);
}
-void Canvas2DLayerChromium::updateContents()
+void Canvas2DLayerChromium::updateContentsIfDirty()
{
- if (!m_drawingBuffer)
+ if (!m_contentsDirty || !m_drawingBuffer)
return;
if (m_textureChanged) { // We have to generate a new backing texture.
GraphicsContext3D* context = layerRendererContext();
@@ -68,7 +68,7 @@ void Canvas2DLayerChromium::updateContents()
context->activeTexture(GraphicsContext3D::TEXTURE0);
context->bindTexture(GraphicsContext3D::TEXTURE_2D, m_textureId);
IntSize size = m_drawingBuffer->size();
- context->texImage2D(GraphicsContext3D::TEXTURE_2D, 0, GraphicsContext3D::RGBA, size.width(), size.height(), 0, GraphicsContext3D::RGBA, GraphicsContext3D::UNSIGNED_BYTE, 0);
+ context->texImage2DResourceSafe(GraphicsContext3D::TEXTURE_2D, 0, GraphicsContext3D::RGBA, size.width(), size.height(), 0, GraphicsContext3D::RGBA, GraphicsContext3D::UNSIGNED_BYTE);
// Set the min-mag filters to linear and wrap modes to GraphicsContext3D::CLAMP_TO_EDGE
// to get around NPOT texture limitations of GLES.
context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_MIN_FILTER, GraphicsContext3D::LINEAR);
diff --git a/WebCore/platform/graphics/chromium/Canvas2DLayerChromium.h b/WebCore/platform/graphics/chromium/Canvas2DLayerChromium.h
index 0031229..44ef050 100644
--- a/WebCore/platform/graphics/chromium/Canvas2DLayerChromium.h
+++ b/WebCore/platform/graphics/chromium/Canvas2DLayerChromium.h
@@ -46,7 +46,7 @@ public:
static PassRefPtr<Canvas2DLayerChromium> create(DrawingBuffer*, GraphicsLayerChromium* owner);
virtual ~Canvas2DLayerChromium();
virtual bool drawsContent() { return true; }
- virtual void updateContents();
+ virtual void updateContentsIfDirty();
void setTextureChanged();
unsigned textureId() const;
diff --git a/WebCore/platform/graphics/chromium/ContentLayerChromium.cpp b/WebCore/platform/graphics/chromium/ContentLayerChromium.cpp
index 375a74b..d00faf8 100644
--- a/WebCore/platform/graphics/chromium/ContentLayerChromium.cpp
+++ b/WebCore/platform/graphics/chromium/ContentLayerChromium.cpp
@@ -36,11 +36,13 @@
#include "GraphicsContext3D.h"
#include "LayerRendererChromium.h"
+#include "LayerTexture.h"
#include "RenderLayerBacking.h"
#if PLATFORM(SKIA)
#include "NativeImageSkia.h"
#include "PlatformContextSkia.h"
+#include "SkColorPriv.h"
#include "skia/ext/platform_canvas.h"
#elif PLATFORM(CG)
#include <CoreGraphics/CGBitmapContext.h>
@@ -68,8 +70,22 @@ ContentLayerChromium::SharedValues::SharedValues(GraphicsContext3D* context)
" v_texCoord = a_texCoord; \n"
"} \n";
+#if PLATFORM(SKIA)
+ // Color is in RGBA order.
+ char rgbaFragmentShaderString[] =
+ "precision mediump float; \n"
+ "varying vec2 v_texCoord; \n"
+ "uniform sampler2D s_texture; \n"
+ "uniform float alpha; \n"
+ "void main() \n"
+ "{ \n"
+ " vec4 texColor = texture2D(s_texture, v_texCoord); \n"
+ " gl_FragColor = texColor * alpha; \n"
+ "} \n";
+#endif
+
// Color is in BGRA order.
- char fragmentShaderString[] =
+ char bgraFragmentShaderString[] =
"precision mediump float; \n"
"varying vec2 v_texCoord; \n"
"uniform sampler2D s_texture; \n"
@@ -80,6 +96,12 @@ ContentLayerChromium::SharedValues::SharedValues(GraphicsContext3D* context)
" gl_FragColor = vec4(texColor.z, texColor.y, texColor.x, texColor.w) * alpha; \n"
"} \n";
+#if PLATFORM(SKIA)
+ // Assuming the packing is either Skia default RGBA or Chromium default BGRA.
+ char* fragmentShaderString = SK_B32_SHIFT ? rgbaFragmentShaderString : bgraFragmentShaderString;
+#else
+ char* fragmentShaderString = bgraFragmentShaderString;
+#endif
m_contentShaderProgram = createShaderProgram(m_context, vertexShaderString, fragmentShaderString);
if (!m_contentShaderProgram) {
LOG_ERROR("ContentLayerChromium: Failed to create shader program");
@@ -123,12 +145,7 @@ ContentLayerChromium::~ContentLayerChromium()
void ContentLayerChromium::cleanupResources()
{
LayerChromium::cleanupResources();
- if (layerRenderer()) {
- if (m_contentsTexture) {
- layerRenderer()->deleteLayerTexture(m_contentsTexture);
- m_contentsTexture = 0;
- }
- }
+ m_contentsTexture.clear();
}
bool ContentLayerChromium::requiresClippedUpdateRect() const
@@ -142,33 +159,7 @@ bool ContentLayerChromium::requiresClippedUpdateRect() const
|| !layerRenderer()->checkTextureSize(m_bounds));
}
-void ContentLayerChromium::calculateClippedUpdateRect(IntRect& dirtyRect, IntRect& drawRect) const
-{
- // For the given layer size and content rect, calculate:
- // 1) The minimal texture space rectangle to be uploaded, returned in dirtyRect.
- // 2) The rectangle to draw this texture in relative to the target render surface, returned in drawRect.
-
- ASSERT(m_targetRenderSurface);
- const IntRect clipRect = m_targetRenderSurface->contentRect();
-
- TransformationMatrix layerOriginTransform = drawTransform();
- layerOriginTransform.translate3d(-0.5 * m_bounds.width(), -0.5 * m_bounds.height(), 0);
-
- // For now we apply the large layer treatment only for layers that are either untransformed
- // or are purely translated. Their matrix is expected to be invertible.
- ASSERT(layerOriginTransform.isInvertible());
-
- TransformationMatrix targetToLayerMatrix = layerOriginTransform.inverse();
- IntRect clipRectInLayerCoords = targetToLayerMatrix.mapRect(clipRect);
- clipRectInLayerCoords.intersect(IntRect(0, 0, m_bounds.width(), m_bounds.height()));
-
- dirtyRect = clipRectInLayerCoords;
-
- // Map back to the target surface coordinate system.
- drawRect = layerOriginTransform.mapRect(dirtyRect);
-}
-
-void ContentLayerChromium::updateContents()
+void ContentLayerChromium::updateContentsIfDirty()
{
RenderLayerBacking* backing = static_cast<RenderLayerBacking*>(m_owner->client());
if (!backing || backing->paintingGoesToWindow())
@@ -183,6 +174,7 @@ void ContentLayerChromium::updateContents()
IntRect updateRect;
IntSize requiredTextureSize;
IntSize bitmapSize;
+ IntRect boundsRect(IntPoint(0, 0), m_bounds);
// FIXME: Remove this test when tiled layers are implemented.
if (requiresClippedUpdateRect()) {
@@ -194,33 +186,57 @@ void ContentLayerChromium::updateContents()
return;
}
- calculateClippedUpdateRect(dirtyRect, m_largeLayerDrawRect);
- if (!layerRenderer()->checkTextureSize(m_largeLayerDrawRect.size())) {
+ // Calculate the region of this layer that is currently visible.
+ const IntRect clipRect = m_targetRenderSurface->contentRect();
+
+ TransformationMatrix layerOriginTransform = drawTransform();
+ layerOriginTransform.translate3d(-0.5 * m_bounds.width(), -0.5 * m_bounds.height(), 0);
+
+ // For now we apply the large layer treatment only for layers that are either untransformed
+ // or are purely translated. Their matrix is expected to be invertible.
+ ASSERT(layerOriginTransform.isInvertible());
+
+ TransformationMatrix targetToLayerMatrix = layerOriginTransform.inverse();
+ IntRect visibleRectInLayerCoords = targetToLayerMatrix.mapRect(clipRect);
+ visibleRectInLayerCoords.intersect(IntRect(0, 0, m_bounds.width(), m_bounds.height()));
+
+ // For normal layers, the center of the texture corresponds with the center of the layer.
+ // In large layers the center of the texture is the center of the visible region so we have
+ // to keep track of the offset in order to render correctly.
+ IntRect visibleRectInSurfaceCoords = layerOriginTransform.mapRect(visibleRectInLayerCoords);
+ m_layerCenterInSurfaceCoords = FloatRect(visibleRectInSurfaceCoords).center();
+
+ // If this is still too large to render, then skip the layer completely.
+ if (!layerRenderer()->checkTextureSize(visibleRectInLayerCoords.size())) {
m_skipsDraw = true;
return;
}
- // If the portion of the large layer that's visible hasn't changed
- // then we don't need to update it, _unless_ its contents have changed
- // in which case we only update the dirty bits.
- if (m_largeLayerDirtyRect == dirtyRect) {
- if (!m_dirtyRect.intersects(dirtyRect))
- return;
- dirtyRect.intersect(IntRect(m_dirtyRect));
- updateRect = dirtyRect;
- requiredTextureSize = m_largeLayerDirtyRect.size();
- } else {
- m_largeLayerDirtyRect = dirtyRect;
- requiredTextureSize = dirtyRect.size();
- updateRect = IntRect(IntPoint(0, 0), dirtyRect.size());
- }
+ // If the visible portion of the layer is different from the last upload, or if our backing
+ // texture has been evicted, then the whole layer is considered dirty.
+ if (visibleRectInLayerCoords != m_visibleRectInLayerCoords || !m_contentsTexture || !m_contentsTexture->isValid(requiredTextureSize, GraphicsContext3D::RGBA))
+ m_dirtyRect = boundsRect;
+ m_visibleRectInLayerCoords = visibleRectInLayerCoords;
+
+ // Calculate the portion of the dirty rectangle that is visible. m_dirtyRect is in layer space.
+ IntRect visibleDirtyRectInLayerSpace = enclosingIntRect(m_dirtyRect);
+ visibleDirtyRectInLayerSpace.intersect(visibleRectInLayerCoords);
+
+ // What the rectangles mean:
+ // dirtyRect: The region of this layer that will be updated.
+ // updateRect: The region of the layer's texture that will be uploaded into.
+ // requiredTextureSize: is the required size of this layer's texture.
+ dirtyRect = visibleDirtyRectInLayerSpace;
+ updateRect = dirtyRect;
+ IntSize visibleRectOffsetInLayerCoords(visibleRectInLayerCoords.x(), visibleRectInLayerCoords.y());
+ updateRect.move(-visibleRectOffsetInLayerCoords);
+ requiredTextureSize = visibleRectInLayerCoords.size();
} else {
dirtyRect = IntRect(m_dirtyRect);
- IntRect boundsRect(IntPoint(0, 0), m_bounds);
requiredTextureSize = m_bounds;
// If the texture needs to be reallocated then we must redraw the entire
// contents of the layer.
- if (requiredTextureSize != m_allocatedTextureSize)
+ if (!m_contentsTexture || !m_contentsTexture->isValid(requiredTextureSize, GraphicsContext3D::RGBA))
dirtyRect = boundsRect;
else {
// Clip the dirtyRect to the size of the layer to avoid drawing
@@ -289,36 +305,28 @@ void ContentLayerChromium::updateContents()
#error "Need to implement for your platform."
#endif
- unsigned textureId = m_contentsTexture;
- if (!textureId)
- textureId = layerRenderer()->createLayerTexture();
-
if (pixels)
- updateTextureRect(pixels, bitmapSize, requiredTextureSize, updateRect, textureId);
+ updateTextureRect(pixels, requiredTextureSize, updateRect);
}
-void ContentLayerChromium::updateTextureRect(void* pixels, const IntSize& bitmapSize, const IntSize& requiredTextureSize, const IntRect& updateRect, unsigned textureId)
+void ContentLayerChromium::updateTextureRect(void* pixels, const IntSize& requiredTextureSize, const IntRect& updateRect)
{
if (!pixels)
return;
GraphicsContext3D* context = layerRendererContext();
- context->bindTexture(GraphicsContext3D::TEXTURE_2D, textureId);
+ if (!m_contentsTexture)
+ m_contentsTexture = LayerTexture::create(context, layerRenderer()->textureManager());
- // If the texture id or size changed since last time then we need to tell GL
- // to re-allocate a texture.
- if (m_contentsTexture != textureId || requiredTextureSize != m_allocatedTextureSize) {
- ASSERT(bitmapSize == requiredTextureSize);
- GLC(context, context->texImage2D(GraphicsContext3D::TEXTURE_2D, 0, GraphicsContext3D::RGBA, requiredTextureSize.width(), requiredTextureSize.height(), 0, GraphicsContext3D::RGBA, GraphicsContext3D::UNSIGNED_BYTE, pixels));
-
- m_contentsTexture = textureId;
- m_allocatedTextureSize = requiredTextureSize;
- } else {
- ASSERT(updateRect.width() <= m_allocatedTextureSize.width() && updateRect.height() <= m_allocatedTextureSize.height());
- ASSERT(updateRect.width() == bitmapSize.width() && updateRect.height() == bitmapSize.height());
- GLC(context, context->texSubImage2D(GraphicsContext3D::TEXTURE_2D, 0, updateRect.x(), updateRect.y(), updateRect.width(), updateRect.height(), GraphicsContext3D::RGBA, GraphicsContext3D::UNSIGNED_BYTE, pixels));
+ if (!m_contentsTexture->reserve(requiredTextureSize, GraphicsContext3D::RGBA)) {
+ m_skipsDraw = true;
+ return;
}
+ m_contentsTexture->bindTexture();
+
+ GLC(context, context->texSubImage2D(GraphicsContext3D::TEXTURE_2D, 0, updateRect.x(), updateRect.y(), updateRect.width(), updateRect.height(), GraphicsContext3D::RGBA, GraphicsContext3D::UNSIGNED_BYTE, pixels));
+
m_dirtyRect.setSize(FloatSize());
// Large layers always stay dirty, because they need to update when the content rect changes.
m_contentsDirty = requiresClippedUpdateRect();
@@ -330,21 +338,22 @@ void ContentLayerChromium::draw()
return;
ASSERT(layerRenderer());
+
const ContentLayerChromium::SharedValues* sv = layerRenderer()->contentLayerSharedValues();
ASSERT(sv && sv->initialized());
GraphicsContext3D* context = layerRendererContext();
GLC(context, context->activeTexture(GraphicsContext3D::TEXTURE0));
- GLC(context, context->bindTexture(GraphicsContext3D::TEXTURE_2D, m_contentsTexture));
+ m_contentsTexture->bindTexture();
layerRenderer()->useShader(sv->contentShaderProgram());
GLC(context, context->uniform1i(sv->shaderSamplerLocation(), 0));
if (requiresClippedUpdateRect()) {
float m43 = drawTransform().m43();
TransformationMatrix transform;
- transform.translate3d(m_largeLayerDrawRect.center().x(), m_largeLayerDrawRect.center().y(), m43);
+ transform.translate3d(m_layerCenterInSurfaceCoords.x(), m_layerCenterInSurfaceCoords.y(), m43);
drawTexturedQuad(context, layerRenderer()->projectionMatrix(),
- transform, m_largeLayerDrawRect.width(),
- m_largeLayerDrawRect.height(), drawOpacity(),
+ transform, m_visibleRectInLayerCoords.width(),
+ m_visibleRectInLayerCoords.height(), drawOpacity(),
sv->shaderMatrixLocation(), sv->shaderAlphaLocation());
} else {
drawTexturedQuad(context, layerRenderer()->projectionMatrix(),
@@ -352,6 +361,7 @@ void ContentLayerChromium::draw()
drawOpacity(), sv->shaderMatrixLocation(),
sv->shaderAlphaLocation());
}
+ m_contentsTexture->unreserve();
}
}
diff --git a/WebCore/platform/graphics/chromium/ContentLayerChromium.h b/WebCore/platform/graphics/chromium/ContentLayerChromium.h
index 32c2c49..dc1630b 100644
--- a/WebCore/platform/graphics/chromium/ContentLayerChromium.h
+++ b/WebCore/platform/graphics/chromium/ContentLayerChromium.h
@@ -35,9 +35,12 @@
#if USE(ACCELERATED_COMPOSITING)
#include "LayerChromium.h"
+#include "TextureManager.h"
namespace WebCore {
+class LayerTexture;
+
// A Layer that requires a GraphicsContext to render its contents.
class ContentLayerChromium : public LayerChromium {
friend class LayerRendererChromium;
@@ -46,7 +49,7 @@ public:
virtual ~ContentLayerChromium();
- virtual void updateContents();
+ virtual void updateContentsIfDirty();
virtual void draw();
virtual bool drawsContent() { return m_owner && m_owner->drawsContent(); }
@@ -74,22 +77,20 @@ public:
};
protected:
- ContentLayerChromium(GraphicsLayerChromium* owner);
+ explicit ContentLayerChromium(GraphicsLayerChromium* owner);
- void updateTextureRect(void* pixels, const IntSize& bitmapSize, const IntSize& requiredTextureSize,
- const IntRect& updateRect, unsigned textureId);
+ void updateTextureRect(void* pixels, const IntSize& requiredTextureSize, const IntRect& updateRect);
virtual void cleanupResources();
bool requiresClippedUpdateRect() const;
- unsigned m_contentsTexture;
- IntSize m_allocatedTextureSize;
+ OwnPtr<LayerTexture> m_contentsTexture;
bool m_skipsDraw;
private:
- void calculateClippedUpdateRect(IntRect& dirtyRect, IntRect& drawRect) const;
- IntRect m_largeLayerDrawRect;
- IntRect m_largeLayerDirtyRect;
+
+ IntRect m_visibleRectInLayerCoords;
+ FloatPoint m_layerCenterInSurfaceCoords;
};
}
diff --git a/WebCore/platform/graphics/chromium/DrawingBufferChromium.cpp b/WebCore/platform/graphics/chromium/DrawingBufferChromium.cpp
index 0395bc2..507c227 100644
--- a/WebCore/platform/graphics/chromium/DrawingBufferChromium.cpp
+++ b/WebCore/platform/graphics/chromium/DrawingBufferChromium.cpp
@@ -60,7 +60,7 @@ static unsigned generateColorTexture(GraphicsContext3D* context, const IntSize&
context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_MIN_FILTER, GraphicsContext3D::NEAREST);
context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_WRAP_S, GraphicsContext3D::CLAMP_TO_EDGE);
context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_WRAP_T, GraphicsContext3D::CLAMP_TO_EDGE);
- context->texImage2D(GraphicsContext3D::TEXTURE_2D, 0, GraphicsContext3D::RGBA, size.width(), size.height(), 0, GraphicsContext3D::RGBA, GraphicsContext3D::UNSIGNED_BYTE, 0);
+ context->texImage2DResourceSafe(GraphicsContext3D::TEXTURE_2D, 0, GraphicsContext3D::RGBA, size.width(), size.height(), 0, GraphicsContext3D::RGBA, GraphicsContext3D::UNSIGNED_BYTE);
context->framebufferTexture2D(GraphicsContext3D::FRAMEBUFFER, GraphicsContext3D::COLOR_ATTACHMENT0, GraphicsContext3D::TEXTURE_2D, offscreenColorTexture, 0);
return offscreenColorTexture;
diff --git a/WebCore/platform/graphics/chromium/Extensions3DChromium.h b/WebCore/platform/graphics/chromium/Extensions3DChromium.h
index 5fda020..d120424 100644
--- a/WebCore/platform/graphics/chromium/Extensions3DChromium.h
+++ b/WebCore/platform/graphics/chromium/Extensions3DChromium.h
@@ -42,6 +42,7 @@ public:
// Extensions3D methods.
virtual bool supports(const String&);
+ virtual void ensureEnabled(const String&);
virtual int getGraphicsResetStatusARB();
virtual void blitFramebuffer(long srcX0, long srcY0, long srcX1, long srcY1, long dstX0, long dstY0, long dstX1, long dstY1, unsigned long mask, unsigned long filter) { }
virtual void renderbufferStorageMultisample(unsigned long target, unsigned long samples, unsigned long internalformat, unsigned long width, unsigned long height) { }
diff --git a/WebCore/platform/graphics/chromium/FontCacheChromiumWin.cpp b/WebCore/platform/graphics/chromium/FontCacheChromiumWin.cpp
index 347a3fb..2c79815 100644
--- a/WebCore/platform/graphics/chromium/FontCacheChromiumWin.cpp
+++ b/WebCore/platform/graphics/chromium/FontCacheChromiumWin.cpp
@@ -50,11 +50,6 @@ using std::min;
namespace WebCore
{
-void FontCache::platformInit()
-{
- // Not needed on Windows.
-}
-
// FIXME: consider adding to WebKit String class
static bool charactersAreAllASCII(const String& s)
{
@@ -329,6 +324,86 @@ static bool fontContainsCharacter(const FontPlatformData* fontData,
return cmap->contains(character);
}
+// Tries the given font and save it |outFontFamilyName| if it succeeds.
+static SimpleFontData* fontDataFromDescriptionAndLogFont(FontCache* fontCache, const FontDescription& fontDescription, const LOGFONT& font, wchar_t* outFontFamilyName)
+{
+ SimpleFontData* fontData = fontCache->getCachedFontData(fontDescription, font.lfFaceName);
+ if (fontData)
+ memcpy(outFontFamilyName, font.lfFaceName, sizeof(font.lfFaceName));
+ return fontData;
+}
+
+static LONG toGDIFontWeight(FontWeight fontWeight)
+{
+ static LONG gdiFontWeights[] = {
+ FW_THIN, // FontWeight100
+ FW_EXTRALIGHT, // FontWeight200
+ FW_LIGHT, // FontWeight300
+ FW_NORMAL, // FontWeight400
+ FW_MEDIUM, // FontWeight500
+ FW_SEMIBOLD, // FontWeight600
+ FW_BOLD, // FontWeight700
+ FW_EXTRABOLD, // FontWeight800
+ FW_HEAVY // FontWeight900
+ };
+ return gdiFontWeights[fontWeight];
+}
+
+static void FillLogFont(const FontDescription& fontDescription, LOGFONT* winfont)
+{
+ // The size here looks unusual. The negative number is intentional.
+ // Unlike WebKit trunk, we don't multiply the size by 32. That seems to be
+ // some kind of artifact of their CG backend, or something.
+ winfont->lfHeight = -fontDescription.computedPixelSize();
+ winfont->lfWidth = 0;
+ winfont->lfEscapement = 0;
+ winfont->lfOrientation = 0;
+ winfont->lfUnderline = false;
+ winfont->lfStrikeOut = false;
+ winfont->lfCharSet = DEFAULT_CHARSET;
+ winfont->lfOutPrecision = OUT_TT_ONLY_PRECIS;
+ winfont->lfQuality = ChromiumBridge::layoutTestMode() ? NONANTIALIASED_QUALITY : DEFAULT_QUALITY; // Honor user's desktop settings.
+ winfont->lfPitchAndFamily = DEFAULT_PITCH | FF_DONTCARE;
+ winfont->lfItalic = fontDescription.italic();
+ winfont->lfWeight = toGDIFontWeight(fontDescription.weight());
+}
+
+struct TraitsInFamilyProcData {
+ TraitsInFamilyProcData(const AtomicString& familyName)
+ : m_familyName(familyName)
+ {
+ }
+
+ const AtomicString& m_familyName;
+ HashSet<unsigned> m_traitsMasks;
+};
+
+static int CALLBACK traitsInFamilyEnumProc(CONST LOGFONT* logFont, CONST TEXTMETRIC* metrics, DWORD fontType, LPARAM lParam)
+{
+ TraitsInFamilyProcData* procData = reinterpret_cast<TraitsInFamilyProcData*>(lParam);
+
+ unsigned traitsMask = 0;
+ traitsMask |= logFont->lfItalic ? FontStyleItalicMask : FontStyleNormalMask;
+ traitsMask |= FontVariantNormalMask;
+ LONG weight = logFont->lfWeight;
+ traitsMask |= weight == FW_THIN ? FontWeight100Mask :
+ weight == FW_EXTRALIGHT ? FontWeight200Mask :
+ weight == FW_LIGHT ? FontWeight300Mask :
+ weight == FW_NORMAL ? FontWeight400Mask :
+ weight == FW_MEDIUM ? FontWeight500Mask :
+ weight == FW_SEMIBOLD ? FontWeight600Mask :
+ weight == FW_BOLD ? FontWeight700Mask :
+ weight == FW_EXTRABOLD ? FontWeight800Mask :
+ FontWeight900Mask;
+ procData->m_traitsMasks.add(traitsMask);
+ return 1;
+}
+
+void FontCache::platformInit()
+{
+ // Not needed on Windows.
+}
+
// Given the desired base font, this will create a SimpleFontData for a specific
// font that can be used to render the given range of characters.
const SimpleFontData* FontCache::getFontDataForCharacters(const Font& font, const UChar* characters, int length)
@@ -438,73 +513,43 @@ SimpleFontData* FontCache::getLastResortFallbackFont(const FontDescription& desc
else if (generic == FontDescription::MonospaceFamily)
fontStr = courierStr;
- return getCachedFontData(description, fontStr);
-}
-
-static LONG toGDIFontWeight(FontWeight fontWeight)
-{
- static LONG gdiFontWeights[] = {
- FW_THIN, // FontWeight100
- FW_EXTRALIGHT, // FontWeight200
- FW_LIGHT, // FontWeight300
- FW_NORMAL, // FontWeight400
- FW_MEDIUM, // FontWeight500
- FW_SEMIBOLD, // FontWeight600
- FW_BOLD, // FontWeight700
- FW_EXTRABOLD, // FontWeight800
- FW_HEAVY // FontWeight900
- };
- return gdiFontWeights[fontWeight];
-}
-
-static void FillLogFont(const FontDescription& fontDescription, LOGFONT* winfont)
-{
- // The size here looks unusual. The negative number is intentional.
- // Unlike WebKit trunk, we don't multiply the size by 32. That seems to be
- // some kind of artifact of their CG backend, or something.
- winfont->lfHeight = -fontDescription.computedPixelSize();
- winfont->lfWidth = 0;
- winfont->lfEscapement = 0;
- winfont->lfOrientation = 0;
- winfont->lfUnderline = false;
- winfont->lfStrikeOut = false;
- winfont->lfCharSet = DEFAULT_CHARSET;
- winfont->lfOutPrecision = OUT_TT_ONLY_PRECIS;
- winfont->lfQuality = ChromiumBridge::layoutTestMode() ? NONANTIALIASED_QUALITY : DEFAULT_QUALITY; // Honor user's desktop settings.
- winfont->lfPitchAndFamily = DEFAULT_PITCH | FF_DONTCARE;
- winfont->lfItalic = fontDescription.italic();
- winfont->lfWeight = toGDIFontWeight(fontDescription.weight());
-}
-
-struct TraitsInFamilyProcData {
- TraitsInFamilyProcData(const AtomicString& familyName)
- : m_familyName(familyName)
- {
+ SimpleFontData* simpleFont = getCachedFontData(description, fontStr);
+ if (simpleFont)
+ return simpleFont;
+
+ // Fall back to system fonts as Win Safari does because this function must
+ // return a valid font. Once we find a valid system font, we save its name
+ // to a static variable and use it to prevent trying system fonts again.
+ static wchar_t fallbackFontName[LF_FACESIZE] = {0};
+ if (fallbackFontName[0])
+ return getCachedFontData(description, fallbackFontName);
+
+ // Fall back to the DEFAULT_GUI_FONT if no known Unicode fonts are available.
+ if (HFONT defaultGUIFont = static_cast<HFONT>(GetStockObject(DEFAULT_GUI_FONT))) {
+ LOGFONT defaultGUILogFont;
+ GetObject(defaultGUIFont, sizeof(defaultGUILogFont), &defaultGUILogFont);
+ if (simpleFont = fontDataFromDescriptionAndLogFont(this, description, defaultGUILogFont, fallbackFontName))
+ return simpleFont;
}
- const AtomicString& m_familyName;
- HashSet<unsigned> m_traitsMasks;
-};
-
-static int CALLBACK traitsInFamilyEnumProc(CONST LOGFONT* logFont, CONST TEXTMETRIC* metrics, DWORD fontType, LPARAM lParam)
-{
- TraitsInFamilyProcData* procData = reinterpret_cast<TraitsInFamilyProcData*>(lParam);
+ // Fall back to Non-client metrics fonts.
+ NONCLIENTMETRICS nonClientMetrics = {0};
+ nonClientMetrics.cbSize = sizeof(nonClientMetrics);
+ if (SystemParametersInfo(SPI_GETNONCLIENTMETRICS, sizeof(nonClientMetrics), &nonClientMetrics, 0)) {
+ if (simpleFont = fontDataFromDescriptionAndLogFont(this, description, nonClientMetrics.lfMessageFont, fallbackFontName))
+ return simpleFont;
+ if (simpleFont = fontDataFromDescriptionAndLogFont(this, description, nonClientMetrics.lfMenuFont, fallbackFontName))
+ return simpleFont;
+ if (simpleFont = fontDataFromDescriptionAndLogFont(this, description, nonClientMetrics.lfStatusFont, fallbackFontName))
+ return simpleFont;
+ if (simpleFont = fontDataFromDescriptionAndLogFont(this, description, nonClientMetrics.lfCaptionFont, fallbackFontName))
+ return simpleFont;
+ if (simpleFont = fontDataFromDescriptionAndLogFont(this, description, nonClientMetrics.lfSmCaptionFont, fallbackFontName))
+ return simpleFont;
+ }
- unsigned traitsMask = 0;
- traitsMask |= logFont->lfItalic ? FontStyleItalicMask : FontStyleNormalMask;
- traitsMask |= FontVariantNormalMask;
- LONG weight = logFont->lfWeight;
- traitsMask |= weight == FW_THIN ? FontWeight100Mask :
- weight == FW_EXTRALIGHT ? FontWeight200Mask :
- weight == FW_LIGHT ? FontWeight300Mask :
- weight == FW_NORMAL ? FontWeight400Mask :
- weight == FW_MEDIUM ? FontWeight500Mask :
- weight == FW_SEMIBOLD ? FontWeight600Mask :
- weight == FW_BOLD ? FontWeight700Mask :
- weight == FW_EXTRABOLD ? FontWeight800Mask :
- FontWeight900Mask;
- procData->m_traitsMasks.add(traitsMask);
- return 1;
+ ASSERT_NOT_REACHED();
+ return 0;
}
void FontCache::getTraitsInFamily(const AtomicString& familyName, Vector<unsigned>& traitsMasks)
diff --git a/WebCore/platform/graphics/chromium/FontCacheLinux.cpp b/WebCore/platform/graphics/chromium/FontCacheLinux.cpp
index 4399d35..bd33927 100644
--- a/WebCore/platform/graphics/chromium/FontCacheLinux.cpp
+++ b/WebCore/platform/graphics/chromium/FontCacheLinux.cpp
@@ -150,7 +150,8 @@ FontPlatformData* FontCache::createFontPlatformData(const FontDescription& fontD
name,
fontDescription.computedSize(),
(style & SkTypeface::kBold) && !tf->isBold(),
- (style & SkTypeface::kItalic) && !tf->isItalic());
+ (style & SkTypeface::kItalic) && !tf->isItalic(),
+ fontDescription.orientation());
tf->unref();
return result;
}
diff --git a/WebCore/platform/graphics/chromium/FontChromiumWin.cpp b/WebCore/platform/graphics/chromium/FontChromiumWin.cpp
index 8a77501..1a00833 100644
--- a/WebCore/platform/graphics/chromium/FontChromiumWin.cpp
+++ b/WebCore/platform/graphics/chromium/FontChromiumWin.cpp
@@ -35,6 +35,7 @@
#include "ChromiumBridge.h"
#include "FontFallbackList.h"
#include "GlyphBuffer.h"
+#include "NotImplemented.h"
#include "PlatformContextSkia.h"
#include "SimpleFontData.h"
#include "SkiaFontWin.h"
@@ -276,7 +277,8 @@ bool TransparencyAwareGlyphPainter::drawGlyphs(int numGlyphs,
FloatSize shadowOffset;
float shadowBlur;
Color shadowColor;
- if (m_graphicsContext->getShadow(shadowOffset, shadowBlur, shadowColor)) {
+ ColorSpace shadowColorSpace;
+ if (m_graphicsContext->getShadow(shadowOffset, shadowBlur, shadowColor, shadowColorSpace)) {
// If there is a shadow and this code is reached, windowsCanHandleDrawTextShadow()
// will have already returned true during the ctor initiatization of m_useGDI
ASSERT(shadowColor.alpha() == 255);
@@ -488,7 +490,8 @@ void Font::drawComplexText(GraphicsContext* graphicsContext,
FloatSize shadowOffset;
float shadowBlur;
Color shadowColor;
- if (graphicsContext->getShadow(shadowOffset, shadowBlur, shadowColor) && windowsCanHandleDrawTextShadow(graphicsContext)) {
+ ColorSpace shadowColorSpace;
+ if (graphicsContext->getShadow(shadowOffset, shadowBlur, shadowColor, shadowColorSpace) && windowsCanHandleDrawTextShadow(graphicsContext)) {
COLORREF textColor = skia::SkColorToCOLORREF(SkColorSetARGB(255, shadowColor.red(), shadowColor.green(), shadowColor.blue()));
COLORREF savedTextColor = GetTextColor(hdc);
SetTextColor(hdc, textColor);
@@ -505,6 +508,11 @@ void Font::drawComplexText(GraphicsContext* graphicsContext,
context->canvas()->endPlatformPaint();
}
+void Font::drawEmphasisMarksForComplexText(GraphicsContext* /* context */, const TextRun& /* run */, const AtomicString& /* mark */, const FloatPoint& /* point */, int /* from */, int /* to */) const
+{
+ notImplemented();
+}
+
float Font::floatWidthForComplexText(const TextRun& run, HashSet<const SimpleFontData*>* /* fallbackFonts */, GlyphOverflow* /* glyphOverflow */) const
{
UniscribeHelperTextRun state(run, *this);
diff --git a/WebCore/platform/graphics/chromium/FontLinux.cpp b/WebCore/platform/graphics/chromium/FontLinux.cpp
index 79b2caf..5e3e5b2 100644
--- a/WebCore/platform/graphics/chromium/FontLinux.cpp
+++ b/WebCore/platform/graphics/chromium/FontLinux.cpp
@@ -91,32 +91,50 @@ void Font::drawGlyphs(GraphicsContext* gc, const SimpleFontData* font,
// patches may be upstreamed to WebKit so we always use the slower path
// here.
const GlyphBufferAdvance* adv = glyphBuffer.advances(from);
- SkAutoSTMalloc<32, SkPoint> storage(numGlyphs);
+ SkAutoSTMalloc<32, SkPoint> storage(numGlyphs), storage2(numGlyphs), storage3(numGlyphs);
SkPoint* pos = storage.get();
+ SkPoint* vPosBegin = storage2.get();
+ SkPoint* vPosEnd = storage3.get();
+ bool isVertical = font->orientation() == Vertical;
for (int i = 0; i < numGlyphs; i++) {
+ SkScalar myWidth = SkFloatToScalar(adv[i].width());
pos[i].set(x, y);
- x += SkFloatToScalar(adv[i].width());
+ if (isVertical) {
+ vPosBegin[i].set(x + myWidth, y);
+ vPosEnd[i].set(x + myWidth, y - myWidth);
+ }
+ x += myWidth;
y += SkFloatToScalar(adv[i].height());
}
gc->platformContext()->prepareForSoftwareDraw();
SkCanvas* canvas = gc->platformContext()->canvas();
- int textMode = gc->platformContext()->getTextDrawingMode();
+ TextDrawingModeFlags textMode = gc->platformContext()->getTextDrawingMode();
// We draw text up to two times (once for fill, once for stroke).
- if (textMode & cTextFill) {
+ if (textMode & TextModeFill) {
SkPaint paint;
gc->platformContext()->setupPaintForFilling(&paint);
font->platformData().setupPaint(&paint);
adjustTextRenderMode(&paint, gc->platformContext());
paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
paint.setColor(gc->fillColor().rgb());
- canvas->drawPosText(glyphs, numGlyphs << 1, pos, paint);
+
+ if (isVertical) {
+ SkPath path;
+ for (int i = 0; i < numGlyphs; ++i) {
+ path.reset();
+ path.moveTo(vPosBegin[i]);
+ path.lineTo(vPosEnd[i]);
+ canvas->drawTextOnPath(glyphs + i, 2, path, 0, paint);
+ }
+ } else
+ canvas->drawPosText(glyphs, numGlyphs << 1, pos, paint);
}
- if ((textMode & cTextStroke)
+ if ((textMode & TextModeStroke)
&& gc->platformContext()->getStrokeStyle() != NoStroke
&& gc->platformContext()->getStrokeThickness() > 0) {
@@ -127,13 +145,22 @@ void Font::drawGlyphs(GraphicsContext* gc, const SimpleFontData* font,
paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
paint.setColor(gc->strokeColor().rgb());
- if (textMode & cTextFill) {
+ if (textMode & TextModeFill) {
// If we also filled, we don't want to draw shadows twice.
// See comment in FontChromiumWin.cpp::paintSkiaText() for more details.
SkSafeUnref(paint.setLooper(0));
}
- canvas->drawPosText(glyphs, numGlyphs << 1, pos, paint);
+ if (isVertical) {
+ SkPath path;
+ for (int i = 0; i < numGlyphs; ++i) {
+ path.reset();
+ path.moveTo(vPosBegin[i]);
+ path.lineTo(vPosEnd[i]);
+ canvas->drawTextOnPath(glyphs + i, 2, path, 0, paint);
+ }
+ } else
+ canvas->drawPosText(glyphs, numGlyphs << 1, pos, paint);
}
}
@@ -341,7 +368,6 @@ void TextRunWalker::setPadding(int padding)
// amount to each space. The last space gets the smaller amount, if
// any.
unsigned numWordBreaks = 0;
- bool isRTL = m_iterateBackwards;
for (unsigned i = 0; i < m_item.stringLength; i++) {
if (isWordBreak(i))
@@ -382,7 +408,7 @@ bool TextRunWalker::nextScriptRun()
// (and the glyphs in each A, C and T section are backwards too)
if (!hb_utf16_script_run_prev(&m_numCodePoints, &m_item.item, m_run.characters(), m_run.length(), &m_indexOfNextScriptRun))
return false;
- m_currentFontData = m_font->glyphDataForCharacter(m_item.string[m_item.item.pos], false, false).fontData;
+ m_currentFontData = m_font->glyphDataForCharacter(m_item.string[m_item.item.pos], false).fontData;
} else {
if (!hb_utf16_script_run_next(&m_numCodePoints, &m_item.item, m_run.characters(), m_run.length(), &m_indexOfNextScriptRun))
return false;
@@ -394,10 +420,10 @@ bool TextRunWalker::nextScriptRun()
// in the harfbuzz data structures to e.g. pick the correct script's shaper.
// So we allow that to run first, then do a second pass over the range it
// found and take the largest subregion that stays within a single font.
- m_currentFontData = m_font->glyphDataForCharacter(m_item.string[m_item.item.pos], false, false).fontData;
+ m_currentFontData = m_font->glyphDataForCharacter(m_item.string[m_item.item.pos], false).fontData;
unsigned endOfRun;
for (endOfRun = 1; endOfRun < m_item.item.length; ++endOfRun) {
- const SimpleFontData* nextFontData = m_font->glyphDataForCharacter(m_item.string[m_item.item.pos + endOfRun], false, false).fontData;
+ const SimpleFontData* nextFontData = m_font->glyphDataForCharacter(m_item.string[m_item.item.pos + endOfRun], false).fontData;
if (nextFontData != m_currentFontData)
break;
}
@@ -423,7 +449,7 @@ float TextRunWalker::widthOfFullRun()
void TextRunWalker::setupFontForScriptRun()
{
- const FontData* fontData = m_font->glyphDataForCharacter(m_item.string[m_item.item.pos], false, false).fontData;
+ const FontData* fontData = m_font->glyphDataForCharacter(m_item.string[m_item.item.pos], false).fontData;
const FontPlatformData& platformData = fontData->fontDataForCharacter(' ')->platformData();
m_item.face = platformData.harfbuzzFace();
void* opaquePlatformData = const_cast<FontPlatformData*>(&platformData);
@@ -524,7 +550,7 @@ void TextRunWalker::setGlyphXPositions(bool isRTL)
// Whitespace must be laid out in logical order, so when inserting
// spaces in RTL (but iterating in LTR order) we must insert spaces
// _before_ the next glyph.
- if (i + 1 >= m_item.num_glyphs || m_item.attributes[i + 1].clusterStart)
+ if (static_cast<unsigned>(i + 1) >= m_item.num_glyphs || m_item.attributes[i + 1].clusterStart)
position += m_letterSpacing;
position += determineWordBreakSpacing(logClustersIndex);
@@ -541,7 +567,7 @@ void TextRunWalker::setGlyphXPositions(bool isRTL)
position += truncateFixedPointToInteger(m_item.advances[i]);
}
} else {
- for (int i = 0; i < m_item.num_glyphs; ++i) {
+ for (size_t i = 0; i < m_item.num_glyphs; ++i) {
m_glyphs16[i] = m_item.glyphs[i];
double offsetX = truncateFixedPointToInteger(m_item.offsets[i].x);
m_xPositions[i] = m_offsetX + position + offsetX;
@@ -556,7 +582,7 @@ void TextRunWalker::setGlyphXPositions(bool isRTL)
if (m_item.attributes[i].clusterStart)
advance += m_letterSpacing;
- while (logClustersIndex < m_item.item.length && logClusters()[logClustersIndex] == i)
+ while (static_cast<unsigned>(logClustersIndex) < m_item.item.length && logClusters()[logClustersIndex] == i)
logClustersIndex++;
position += advance;
@@ -652,9 +678,9 @@ void Font::drawComplexText(GraphicsContext* gc, const TextRun& run,
return;
SkCanvas* canvas = gc->platformContext()->canvas();
- int textMode = gc->platformContext()->getTextDrawingMode();
- bool fill = textMode & cTextFill;
- bool stroke = (textMode & cTextStroke)
+ TextDrawingModeFlags textMode = gc->platformContext()->getTextDrawingMode();
+ bool fill = textMode & TextModeFill;
+ bool stroke = (textMode & TextModeStroke)
&& gc->platformContext()->getStrokeStyle() != NoStroke
&& gc->platformContext()->getStrokeThickness() > 0;
@@ -691,6 +717,11 @@ void Font::drawComplexText(GraphicsContext* gc, const TextRun& run,
}
}
+void Font::drawEmphasisMarksForComplexText(GraphicsContext* /* context */, const TextRun& /* run */, const AtomicString& /* mark */, const FloatPoint& /* point */, int /* from */, int /* to */) const
+{
+ notImplemented();
+}
+
float Font::floatWidthForComplexText(const TextRun& run, HashSet<const SimpleFontData*>* /* fallbackFonts */, GlyphOverflow* /* glyphOverflow */) const
{
TextRunWalker walker(run, 0, this);
@@ -708,7 +739,7 @@ static int glyphIndexForXPositionInScriptRun(const TextRunWalker& walker, int x)
for (glyphIndex = walker.length() - 1; glyphIndex >= 0; --glyphIndex) {
// When iterating LTR over RTL text, we must include the whitespace
// _before_ the glyph, so no + 1 here.
- if (x < (walker.length() - glyphIndex) * letterSpacing + truncateFixedPointToInteger(advances[glyphIndex]))
+ if (x < (static_cast<int>(walker.length()) - glyphIndex) * letterSpacing + truncateFixedPointToInteger(advances[glyphIndex]))
break;
x -= truncateFixedPointToInteger(advances[glyphIndex]);
}
diff --git a/WebCore/platform/graphics/chromium/FontPlatformDataLinux.cpp b/WebCore/platform/graphics/chromium/FontPlatformDataLinux.cpp
index 3944775..42942cc 100644
--- a/WebCore/platform/graphics/chromium/FontPlatformDataLinux.cpp
+++ b/WebCore/platform/graphics/chromium/FontPlatformDataLinux.cpp
@@ -73,18 +73,20 @@ FontPlatformData::FontPlatformData(const FontPlatformData& src)
, m_textSize(src.m_textSize)
, m_fakeBold(src.m_fakeBold)
, m_fakeItalic(src.m_fakeItalic)
+ , m_orientation(src.m_orientation)
, m_style(src.m_style)
, m_harfbuzzFace(src.m_harfbuzzFace)
{
SkSafeRef(m_typeface);
}
-FontPlatformData::FontPlatformData(SkTypeface* tf, const char* family, float textSize, bool fakeBold, bool fakeItalic)
+FontPlatformData::FontPlatformData(SkTypeface* tf, const char* family, float textSize, bool fakeBold, bool fakeItalic, FontOrientation orientation)
: m_typeface(tf)
, m_family(family)
, m_textSize(textSize)
, m_fakeBold(fakeBold)
, m_fakeItalic(fakeItalic)
+ , m_orientation(orientation)
{
SkSafeRef(m_typeface);
querySystemForRenderStyle();
@@ -116,6 +118,7 @@ FontPlatformData& FontPlatformData::operator=(const FontPlatformData& src)
m_fakeBold = src.m_fakeBold;
m_fakeItalic = src.m_fakeItalic;
m_harfbuzzFace = src.m_harfbuzzFace;
+ m_orientation = src.m_orientation;
m_style = src.m_style;
return *this;
@@ -179,13 +182,14 @@ bool FontPlatformData::operator==(const FontPlatformData& a) const
&& m_textSize == a.m_textSize
&& m_fakeBold == a.m_fakeBold
&& m_fakeItalic == a.m_fakeItalic
+ && m_orientation == a.m_orientation
&& m_style == a.m_style;
}
unsigned FontPlatformData::hash() const
{
unsigned h = SkTypeface::UniqueID(m_typeface);
- h ^= 0x01010101 * ((static_cast<int>(m_fakeBold) << 1) | static_cast<int>(m_fakeItalic));
+ h ^= 0x01010101 * ((static_cast<int>(m_orientation) << 2) | (static_cast<int>(m_fakeBold) << 1) | static_cast<int>(m_fakeItalic));
// This memcpy is to avoid a reinterpret_cast that breaks strict-aliasing
// rules. Memcpy is generally optimized enough so that performance doesn't
diff --git a/WebCore/platform/graphics/chromium/FontPlatformDataLinux.h b/WebCore/platform/graphics/chromium/FontPlatformDataLinux.h
index 694a945..43771d7 100644
--- a/WebCore/platform/graphics/chromium/FontPlatformDataLinux.h
+++ b/WebCore/platform/graphics/chromium/FontPlatformDataLinux.h
@@ -72,6 +72,7 @@ public:
, m_textSize(0)
, m_fakeBold(false)
, m_fakeItalic(false)
+ , m_orientation(Horizontal)
{ }
FontPlatformData(float textSize, bool fakeBold, bool fakeItalic)
@@ -79,10 +80,11 @@ public:
, m_textSize(textSize)
, m_fakeBold(fakeBold)
, m_fakeItalic(fakeItalic)
+ , m_orientation(Horizontal)
{ }
FontPlatformData(const FontPlatformData&);
- FontPlatformData(SkTypeface*, const char* name, float textSize, bool fakeBold, bool fakeItalic);
+ FontPlatformData(SkTypeface*, const char* name, float textSize, bool fakeBold, bool fakeItalic, FontOrientation orientation = Horizontal);
FontPlatformData(const FontPlatformData& src, float textSize);
~FontPlatformData();
@@ -106,7 +108,7 @@ public:
unsigned hash() const;
float size() const { return m_textSize; }
- FontOrientation orientation() const { return Horizontal; } // FIXME: Implement.
+ FontOrientation orientation() const { return m_orientation; }
bool operator==(const FontPlatformData&) const;
FontPlatformData& operator=(const FontPlatformData&);
@@ -153,6 +155,7 @@ private:
float m_textSize;
bool m_fakeBold;
bool m_fakeItalic;
+ FontOrientation m_orientation;
FontRenderStyle m_style;
mutable RefPtr<RefCountedHarfbuzzFace> m_harfbuzzFace;
diff --git a/WebCore/platform/graphics/chromium/GraphicsLayerChromium.cpp b/WebCore/platform/graphics/chromium/GraphicsLayerChromium.cpp
index 21dcd8e..5e8d148 100644
--- a/WebCore/platform/graphics/chromium/GraphicsLayerChromium.cpp
+++ b/WebCore/platform/graphics/chromium/GraphicsLayerChromium.cpp
@@ -115,11 +115,6 @@ void GraphicsLayerChromium::setName(const String& inName)
GraphicsLayer::setName(name);
}
-NativeLayer GraphicsLayerChromium::nativeLayer() const
-{
- return m_layer.get();
-}
-
bool GraphicsLayerChromium::setChildren(const Vector<GraphicsLayer*>& children)
{
bool childrenChanged = GraphicsLayer::setChildren(children);
diff --git a/WebCore/platform/graphics/chromium/GraphicsLayerChromium.h b/WebCore/platform/graphics/chromium/GraphicsLayerChromium.h
index 214058d..130c25c 100644
--- a/WebCore/platform/graphics/chromium/GraphicsLayerChromium.h
+++ b/WebCore/platform/graphics/chromium/GraphicsLayerChromium.h
@@ -47,9 +47,6 @@ public:
virtual void setName(const String&);
- // for hosting this GraphicsLayer in a native layer hierarchy
- virtual NativeLayer nativeLayer() const;
-
virtual bool setChildren(const Vector<GraphicsLayer*>&);
virtual void addChild(GraphicsLayer*);
virtual void addChildAtIndex(GraphicsLayer*, int index);
diff --git a/WebCore/platform/graphics/chromium/ImageLayerChromium.cpp b/WebCore/platform/graphics/chromium/ImageLayerChromium.cpp
index adcbb82..cd299c1 100644
--- a/WebCore/platform/graphics/chromium/ImageLayerChromium.cpp
+++ b/WebCore/platform/graphics/chromium/ImageLayerChromium.cpp
@@ -36,6 +36,7 @@
#include "Image.h"
#include "LayerRendererChromium.h"
+#include "LayerTexture.h"
#if PLATFORM(SKIA)
#include "NativeImageSkia.h"
@@ -71,7 +72,7 @@ void ImageLayerChromium::setContents(Image* contents)
setNeedsDisplay();
}
-void ImageLayerChromium::updateContents()
+void ImageLayerChromium::updateContentsIfDirty()
{
ASSERT(layerRenderer());
@@ -79,12 +80,11 @@ void ImageLayerChromium::updateContents()
if (requiresClippedUpdateRect()) {
// Use the base version of updateContents which draws a subset of the
// image to a bitmap, as the pixel contents can't be uploaded directly.
- ContentLayerChromium::updateContents();
+ ContentLayerChromium::updateContentsIfDirty();
return;
}
void* pixels = 0;
- IntSize requiredTextureSize;
IntSize bitmapSize;
NativeImagePtr nativeImage = m_contents->nativeImageForCurrentFrame();
@@ -93,22 +93,33 @@ void ImageLayerChromium::updateContents()
// The layer contains an Image.
NativeImageSkia* skiaImage = static_cast<NativeImageSkia*>(nativeImage);
const SkBitmap* skiaBitmap = skiaImage;
- requiredTextureSize = IntSize(skiaBitmap->width(), skiaBitmap->height());
+ bitmapSize = IntSize(skiaBitmap->width(), skiaBitmap->height());
ASSERT(skiaBitmap);
+#elif PLATFORM(CG)
+ // NativeImagePtr is a CGImageRef on Mac OS X.
+ int width = CGImageGetWidth(nativeImage);
+ int height = CGImageGetHeight(nativeImage);
+ bitmapSize = IntSize(width, height);
+#endif
+
+ // Clip the dirty rect to the bitmap dimensions.
+ IntRect dirtyRect(m_dirtyRect);
+ dirtyRect.intersect(IntRect(IntPoint(0, 0), bitmapSize));
+
+ if (!m_contentsTexture || !m_contentsTexture->isValid(bitmapSize, GraphicsContext3D::RGBA))
+ dirtyRect = IntRect(IntPoint(0, 0), bitmapSize);
+ else if (!m_contentsDirty) {
+ m_contentsTexture->reserve(bitmapSize, GraphicsContext3D::RGBA);
+ return;
+ }
+#if PLATFORM(SKIA)
SkAutoLockPixels lock(*skiaBitmap);
SkBitmap::Config skiaConfig = skiaBitmap->config();
// FIXME: do we need to support more image configurations?
- if (skiaConfig == SkBitmap::kARGB_8888_Config) {
+ if (skiaConfig == SkBitmap::kARGB_8888_Config)
pixels = skiaBitmap->getPixels();
- bitmapSize = IntSize(skiaBitmap->width(), skiaBitmap->height());
- }
#elif PLATFORM(CG)
- // NativeImagePtr is a CGImageRef on Mac OS X.
- int width = CGImageGetWidth(nativeImage);
- int height = CGImageGetHeight(nativeImage);
- requiredTextureSize = IntSize(width, height);
- bitmapSize = requiredTextureSize;
// FIXME: we should get rid of this temporary copy where possible.
int tempRowBytes = width * 4;
Vector<uint8_t> tempVector;
@@ -145,16 +156,8 @@ void ImageLayerChromium::updateContents()
#error "Need to implement for your platform."
#endif
- unsigned textureId = m_contentsTexture;
- if (!textureId)
- textureId = layerRenderer()->createLayerTexture();
-
- // Clip the dirty rect to the bitmap dimensions.
- IntRect dirtyRect(m_dirtyRect);
- dirtyRect.intersect(IntRect(IntPoint(0, 0), bitmapSize));
-
if (pixels)
- updateTextureRect(pixels, bitmapSize, requiredTextureSize, dirtyRect, textureId);
+ updateTextureRect(pixels, bitmapSize, dirtyRect);
}
}
diff --git a/WebCore/platform/graphics/chromium/ImageLayerChromium.h b/WebCore/platform/graphics/chromium/ImageLayerChromium.h
index b91f04a..a5c1450 100644
--- a/WebCore/platform/graphics/chromium/ImageLayerChromium.h
+++ b/WebCore/platform/graphics/chromium/ImageLayerChromium.h
@@ -49,7 +49,7 @@ class ImageLayerChromium : public ContentLayerChromium {
public:
static PassRefPtr<ImageLayerChromium> create(GraphicsLayerChromium* owner = 0);
- virtual void updateContents();
+ virtual void updateContentsIfDirty();
virtual bool drawsContent() { return m_contents; }
void setContents(Image* image);
diff --git a/WebCore/platform/graphics/chromium/LayerChromium.cpp b/WebCore/platform/graphics/chromium/LayerChromium.cpp
index fab5d7b..b7ab098 100644
--- a/WebCore/platform/graphics/chromium/LayerChromium.cpp
+++ b/WebCore/platform/graphics/chromium/LayerChromium.cpp
@@ -59,7 +59,7 @@ static unsigned loadShader(GraphicsContext3D* context, unsigned type, const char
String sourceString(shaderSource);
GLC(context, context->shaderSource(shader, sourceString));
GLC(context, context->compileShader(shader));
- int compiled;
+ int compiled = 0;
GLC(context, context->getShaderiv(shader, GraphicsContext3D::COMPILE_STATUS, &compiled));
if (!compiled) {
GLC(context, context->deleteShader(shader));
@@ -228,7 +228,7 @@ unsigned LayerChromium::createShaderProgram(GraphicsContext3D* context, const ch
GLC(context, context->bindAttribLocation(programObject, s_texCoordAttribLocation, "a_texCoord"));
GLC(context, context->linkProgram(programObject));
- int linked;
+ int linked = 0;
GLC(context, context->getProgramiv(programObject, GraphicsContext3D::LINK_STATUS, &linked));
if (!linked) {
LOG_ERROR("Failed to link shader program");
diff --git a/WebCore/platform/graphics/chromium/LayerChromium.h b/WebCore/platform/graphics/chromium/LayerChromium.h
index 86f3580..ac95285 100644
--- a/WebCore/platform/graphics/chromium/LayerChromium.h
+++ b/WebCore/platform/graphics/chromium/LayerChromium.h
@@ -151,15 +151,13 @@ public:
void setOwner(GraphicsLayerChromium* owner) { m_owner = owner; }
- bool contentsDirty() { return m_contentsDirty; }
-
// Returns the rect containtaining this layer in the current view's coordinate system.
const IntRect getDrawRect() const;
// These methods typically need to be overwritten by derived classes.
virtual bool drawsContent() { return false; }
- virtual void updateContents() { };
- virtual void draw() { };
+ virtual void updateContentsIfDirty() { }
+ virtual void draw() { }
void drawDebugBorder();
@@ -197,6 +195,12 @@ public:
LayerRendererChromium* layerRenderer() const { return m_layerRenderer.get(); }
+ static unsigned createShaderProgram(GraphicsContext3D*, const char* vertexShaderSource, const char* fragmentShaderSource);
+
+ static void drawTexturedQuad(GraphicsContext3D*, const TransformationMatrix& projectionMatrix, const TransformationMatrix& layerMatrix,
+ float width, float height, float opacity,
+ int matrixLocation, int alphaLocation);
+
protected:
GraphicsLayerChromium* m_owner;
LayerChromium(GraphicsLayerChromium* owner);
@@ -211,14 +215,8 @@ protected:
// Returns true if any of the layer's descendants has content to draw.
bool descendantsDrawContent();
- static void drawTexturedQuad(GraphicsContext3D*, const TransformationMatrix& projectionMatrix, const TransformationMatrix& layerMatrix,
- float width, float height, float opacity,
- int matrixLocation, int alphaLocation);
-
static void toGLMatrix(float*, const TransformationMatrix&);
- static unsigned createShaderProgram(GraphicsContext3D*, const char* vertexShaderSource, const char* fragmentShaderSource);
-
IntSize m_bounds;
FloatRect m_dirtyRect;
bool m_contentsDirty;
diff --git a/WebCore/platform/graphics/chromium/LayerRendererChromium.cpp b/WebCore/platform/graphics/chromium/LayerRendererChromium.cpp
index 91580cc..882baae 100644
--- a/WebCore/platform/graphics/chromium/LayerRendererChromium.cpp
+++ b/WebCore/platform/graphics/chromium/LayerRendererChromium.cpp
@@ -37,7 +37,9 @@
#include "Canvas2DLayerChromium.h"
#include "GraphicsContext3D.h"
#include "LayerChromium.h"
+#include "LayerTexture.h"
#include "NotImplemented.h"
+#include "TextureManager.h"
#include "WebGLLayerChromium.h"
#if PLATFORM(SKIA)
#include "NativeImageSkia.h"
@@ -48,6 +50,9 @@
namespace WebCore {
+// FIXME: Make this limit adjustable and give it a useful value.
+static size_t textureMemoryLimitBytes = 64 * 1024 * 1024;
+
static TransformationMatrix orthoMatrix(float left, float right, float bottom, float top)
{
float deltaX = right - left;
@@ -98,7 +103,6 @@ LayerRendererChromium::LayerRendererChromium(PassRefPtr<GraphicsContext3D> conte
: m_rootLayerTextureId(0)
, m_rootLayerTextureWidth(0)
, m_rootLayerTextureHeight(0)
- , m_textureLayerShaderProgram(0)
, m_rootLayer(0)
, m_scrollPosition(IntPoint(-1, -1))
, m_currentShader(0)
@@ -164,7 +168,7 @@ void LayerRendererChromium::setRootLayerCanvasSize(const IntSize& size)
void LayerRendererChromium::useShader(unsigned programId)
{
if (programId != m_currentShader) {
- GLC(m_context, m_context->useProgram(programId));
+ GLC(m_context.get(), m_context->useProgram(programId));
m_currentShader = programId;
}
}
@@ -173,7 +177,7 @@ void LayerRendererChromium::useShader(unsigned programId)
// root layer texture. It resizes the root layer texture and scrolls its
// contents as needed. It also sets up common GL state used by the rest
// of the layer drawing code.
-void LayerRendererChromium::prepareToDrawLayers(const IntRect& visibleRect, const IntRect& contentRect,
+void LayerRendererChromium::prepareToDrawLayers(const IntRect& visibleRect, const IntRect& contentRect,
const IntPoint& scrollPosition)
{
ASSERT(m_hardwareCompositing);
@@ -183,8 +187,8 @@ void LayerRendererChromium::prepareToDrawLayers(const IntRect& visibleRect, cons
makeContextCurrent();
- GLC(m_context, m_context->bindTexture(GraphicsContext3D::TEXTURE_2D, m_rootLayerTextureId));
-
+ GLC(m_context.get(), m_context->bindTexture(GraphicsContext3D::TEXTURE_2D, m_rootLayerTextureId));
+
bool skipScroll = false;
// If the size of the visible area has changed then allocate a new texture
@@ -195,8 +199,7 @@ void LayerRendererChromium::prepareToDrawLayers(const IntRect& visibleRect, cons
if (visibleRectWidth != m_rootLayerTextureWidth || visibleRectHeight != m_rootLayerTextureHeight) {
m_rootLayerTextureWidth = visibleRectWidth;
m_rootLayerTextureHeight = visibleRectHeight;
-
- GLC(m_context, m_context->texImage2D(GraphicsContext3D::TEXTURE_2D, 0, GraphicsContext3D::RGBA, m_rootLayerTextureWidth, m_rootLayerTextureHeight, 0, GraphicsContext3D::RGBA, GraphicsContext3D::UNSIGNED_BYTE, 0));
+ GLC(m_context.get(), m_context->texImage2DResourceSafe(GraphicsContext3D::TEXTURE_2D, 0, GraphicsContext3D::RGBA, m_rootLayerTextureWidth, m_rootLayerTextureHeight, 0, GraphicsContext3D::RGBA, GraphicsContext3D::UNSIGNED_BYTE));
// Reset the current render surface to force an update of the viewport and
// projection matrix next time useRenderSurface is called.
@@ -208,17 +211,17 @@ void LayerRendererChromium::prepareToDrawLayers(const IntRect& visibleRect, cons
}
// The GL viewport covers the entire visible area, including the scrollbars.
- GLC(m_context, m_context->viewport(0, 0, visibleRectWidth, visibleRectHeight));
+ GLC(m_context.get(), m_context->viewport(0, 0, visibleRectWidth, visibleRectHeight));
// Bind the common vertex attributes used for drawing all the layers.
LayerChromium::prepareForDraw(layerSharedValues());
// FIXME: These calls can be made once, when the compositor context is initialized.
- GLC(m_context, m_context->disable(GraphicsContext3D::DEPTH_TEST));
- GLC(m_context, m_context->disable(GraphicsContext3D::CULL_FACE));
+ GLC(m_context.get(), m_context->disable(GraphicsContext3D::DEPTH_TEST));
+ GLC(m_context.get(), m_context->disable(GraphicsContext3D::CULL_FACE));
- // Blending disabled by default. Root layer alpha channel on Windows is incorrect when Skia uses ClearType.
- GLC(m_context, m_context->disable(GraphicsContext3D::BLEND));
+ // Blending disabled by default. Root layer alpha channel on Windows is incorrect when Skia uses ClearType.
+ GLC(m_context.get(), m_context->disable(GraphicsContext3D::BLEND));
if (m_scrollPosition == IntPoint(-1, -1)) {
m_scrollPosition = scrollPosition;
@@ -244,13 +247,14 @@ void LayerRendererChromium::prepareToDrawLayers(const IntRect& visibleRect, cons
0.5 * visibleRect.height() + scrollDelta.y(), 0);
scrolledLayerMatrix.scale3d(1, -1, 1);
- useShader(m_textureLayerShaderProgram);
- GLC(m_context, m_context->uniform1i(m_textureLayerShaderSamplerLocation, 0));
+ const RenderSurfaceChromium::SharedValues* rsv = renderSurfaceSharedValues();
+ useShader(rsv->shaderProgram());
+ GLC(m_context.get(), m_context->uniform1i(rsv->shaderSamplerLocation(), 0));
LayerChromium::drawTexturedQuad(m_context.get(), m_projectionMatrix, scrolledLayerMatrix,
visibleRect.width(), visibleRect.height(), 1,
- m_textureLayerShaderMatrixLocation, m_textureLayerShaderAlphaLocation);
+ rsv->shaderMatrixLocation(), rsv->shaderAlphaLocation());
- GLC(m_context, m_context->copyTexSubImage2D(GraphicsContext3D::TEXTURE_2D, 0, 0, 0, 0, 0, contentRect.width(), contentRect.height()));
+ GLC(m_context.get(), m_context->copyTexSubImage2D(GraphicsContext3D::TEXTURE_2D, 0, 0, 0, 0, 0, contentRect.width(), contentRect.height()));
}
m_scrollPosition = scrollPosition;
@@ -263,7 +267,7 @@ void LayerRendererChromium::updateRootLayerTextureRect(const IntRect& updateRect
if (!m_rootLayer)
return;
- GLC(m_context, m_context->bindTexture(GraphicsContext3D::TEXTURE_2D, m_rootLayerTextureId));
+ GLC(m_context.get(), m_context->bindTexture(GraphicsContext3D::TEXTURE_2D, m_rootLayerTextureId));
// Update the root layer texture.
ASSERT((updateRect.right() <= m_rootLayerTextureWidth)
@@ -282,7 +286,7 @@ void LayerRendererChromium::updateRootLayerTextureRect(const IntRect& updateRect
#error "Need to implement for your platform."
#endif
// Copy the contents of the updated rect to the root layer texture.
- GLC(m_context, m_context->texSubImage2D(GraphicsContext3D::TEXTURE_2D, 0, updateRect.x(), updateRect.y(), updateRect.width(), updateRect.height(), GraphicsContext3D::RGBA, GraphicsContext3D::UNSIGNED_BYTE, pixels));
+ GLC(m_context.get(), m_context->texSubImage2D(GraphicsContext3D::TEXTURE_2D, 0, updateRect.x(), updateRect.y(), updateRect.width(), updateRect.height(), GraphicsContext3D::RGBA, GraphicsContext3D::UNSIGNED_BYTE, pixels));
}
void LayerRendererChromium::drawLayers(const IntRect& visibleRect, const IntRect& contentRect)
@@ -300,22 +304,22 @@ void LayerRendererChromium::drawLayers(const IntRect& visibleRect, const IntRect
m_context->clearColor(0, 0, 1, 1);
m_context->clear(GraphicsContext3D::COLOR_BUFFER_BIT);
- GLC(m_context, m_context->bindTexture(GraphicsContext3D::TEXTURE_2D, m_rootLayerTextureId));
+ GLC(m_context.get(), m_context->bindTexture(GraphicsContext3D::TEXTURE_2D, m_rootLayerTextureId));
// Render the root layer using a quad that takes up the entire visible area of the window.
// We reuse the shader program used by ContentLayerChromium.
const ContentLayerChromium::SharedValues* contentLayerValues = contentLayerSharedValues();
useShader(contentLayerValues->contentShaderProgram());
- GLC(m_context, m_context->uniform1i(contentLayerValues->shaderSamplerLocation(), 0));
+ GLC(m_context.get(), m_context->uniform1i(contentLayerValues->shaderSamplerLocation(), 0));
// Mask out writes to alpha channel: ClearType via Skia results in invalid
// zero alpha values on text glyphs. The root layer is always opaque.
- GLC(m_context, m_context->colorMask(true, true, true, false));
+ GLC(m_context.get(), m_context->colorMask(true, true, true, false));
TransformationMatrix layerMatrix;
layerMatrix.translate3d(visibleRect.width() * 0.5f, visibleRect.height() * 0.5f, 0);
LayerChromium::drawTexturedQuad(m_context.get(), m_projectionMatrix, layerMatrix,
visibleRect.width(), visibleRect.height(), 1,
contentLayerValues->shaderMatrixLocation(), contentLayerValues->shaderAlphaLocation());
- GLC(m_context, m_context->colorMask(true, true, true, true));
+ GLC(m_context.get(), m_context->colorMask(true, true, true, true));
// Set the root visible/content rects --- used by subsequent drawLayers calls.
m_rootVisibleRect = visibleRect;
@@ -336,9 +340,9 @@ void LayerRendererChromium::drawLayers(const IntRect& visibleRect, const IntRect
// The shader used to render layers returns pre-multiplied alpha colors
// so we need to send the blending mode appropriately.
- GLC(m_context, m_context->enable(GraphicsContext3D::BLEND));
- GLC(m_context, m_context->blendFunc(GraphicsContext3D::ONE, GraphicsContext3D::ONE_MINUS_SRC_ALPHA));
- GLC(m_context, m_context->enable(GraphicsContext3D::SCISSOR_TEST));
+ GLC(m_context.get(), m_context->enable(GraphicsContext3D::BLEND));
+ GLC(m_context.get(), m_context->blendFunc(GraphicsContext3D::ONE, GraphicsContext3D::ONE_MINUS_SRC_ALPHA));
+ GLC(m_context.get(), m_context->enable(GraphicsContext3D::SCISSOR_TEST));
// Update the contents of the render surfaces. We traverse the array from
// back to front to guarantee that nested render surfaces get rendered in the
@@ -352,22 +356,23 @@ void LayerRendererChromium::drawLayers(const IntRect& visibleRect, const IntRect
if (!renderSurfaceLayer->m_renderSurface->m_layerList.size())
continue;
- useRenderSurface(renderSurfaceLayer->m_renderSurface.get());
- if (renderSurfaceLayer != m_rootLayer) {
- GLC(m_context, m_context->disable(GraphicsContext3D::SCISSOR_TEST));
- GLC(m_context, m_context->clearColor(0, 0, 0, 0));
- GLC(m_context, m_context->clear(GraphicsContext3D::COLOR_BUFFER_BIT));
- GLC(m_context, m_context->enable(GraphicsContext3D::SCISSOR_TEST));
+ if (useRenderSurface(renderSurfaceLayer->m_renderSurface.get())) {
+ if (renderSurfaceLayer != m_rootLayer) {
+ GLC(m_context.get(), m_context->disable(GraphicsContext3D::SCISSOR_TEST));
+ GLC(m_context.get(), m_context->clearColor(0, 0, 0, 0));
+ GLC(m_context.get(), m_context->clear(GraphicsContext3D::COLOR_BUFFER_BIT));
+ GLC(m_context.get(), m_context->enable(GraphicsContext3D::SCISSOR_TEST));
+ }
+
+ Vector<LayerChromium*>& layerList = renderSurfaceLayer->m_renderSurface->m_layerList;
+ ASSERT(layerList.size());
+ for (unsigned layerIndex = 0; layerIndex < layerList.size(); ++layerIndex)
+ drawLayer(layerList[layerIndex], renderSurfaceLayer->m_renderSurface.get());
}
-
- Vector<LayerChromium*>& layerList = renderSurfaceLayer->m_renderSurface->m_layerList;
- ASSERT(layerList.size());
- for (unsigned layerIndex = 0; layerIndex < layerList.size(); ++layerIndex)
- drawLayer(layerList[layerIndex], renderSurfaceLayer->m_renderSurface.get());
}
- GLC(m_context, m_context->disable(GraphicsContext3D::SCISSOR_TEST));
- GLC(m_context, m_context->disable(GraphicsContext3D::BLEND));
+ GLC(m_context.get(), m_context->disable(GraphicsContext3D::SCISSOR_TEST));
+ GLC(m_context.get(), m_context->disable(GraphicsContext3D::BLEND));
}
void LayerRendererChromium::finish()
@@ -394,7 +399,7 @@ void LayerRendererChromium::getFramebufferPixels(void *pixels, const IntRect& re
makeContextCurrent();
- GLC(m_context, m_context->readPixels(rect.x(), rect.y(), rect.width(), rect.height(),
+ GLC(m_context.get(), m_context->readPixels(rect.x(), rect.y(), rect.width(), rect.height(),
GraphicsContext3D::RGBA, GraphicsContext3D::UNSIGNED_BYTE, pixels));
}
@@ -402,14 +407,14 @@ void LayerRendererChromium::getFramebufferPixels(void *pixels, const IntRect& re
unsigned LayerRendererChromium::createLayerTexture()
{
unsigned textureId = 0;
- GLC(m_context, textureId = m_context->createTexture());
- GLC(m_context, m_context->bindTexture(GraphicsContext3D::TEXTURE_2D, textureId));
+ GLC(m_context.get(), textureId = m_context->createTexture());
+ GLC(m_context.get(), m_context->bindTexture(GraphicsContext3D::TEXTURE_2D, textureId));
// Do basic linear filtering on resize.
- GLC(m_context, m_context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_MIN_FILTER, GraphicsContext3D::LINEAR));
- GLC(m_context, m_context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_MAG_FILTER, GraphicsContext3D::LINEAR));
+ GLC(m_context.get(), m_context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_MIN_FILTER, GraphicsContext3D::LINEAR));
+ GLC(m_context.get(), m_context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_MAG_FILTER, GraphicsContext3D::LINEAR));
// NPOT textures in GL ES only work when the wrap mode is set to GraphicsContext3D::CLAMP_TO_EDGE.
- GLC(m_context, m_context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_WRAP_S, GraphicsContext3D::CLAMP_TO_EDGE));
- GLC(m_context, m_context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_WRAP_T, GraphicsContext3D::CLAMP_TO_EDGE));
+ GLC(m_context.get(), m_context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_WRAP_S, GraphicsContext3D::CLAMP_TO_EDGE));
+ GLC(m_context.get(), m_context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_WRAP_T, GraphicsContext3D::CLAMP_TO_EDGE));
return textureId;
}
@@ -418,7 +423,7 @@ void LayerRendererChromium::deleteLayerTexture(unsigned textureId)
if (!textureId)
return;
- GLC(m_context, m_context->deleteTexture(textureId));
+ GLC(m_context.get(), m_context->deleteTexture(textureId));
}
// Returns true if any part of the layer falls within the visibleRect
@@ -507,7 +512,7 @@ void LayerRendererChromium::updateLayersRecursive(LayerChromium* layer, const Tr
// Layer's opacity will be applied when drawing the render surface.
renderSurface->m_drawOpacity = layer->opacity();
if (layer->superlayer()->preserves3D())
- renderSurface->m_drawOpacity *= layer->superlayer()->m_drawOpacity;
+ renderSurface->m_drawOpacity *= layer->superlayer()->drawOpacity();
layer->m_drawOpacity = 1;
TransformationMatrix layerOriginTransform = combinedTransform;
@@ -598,7 +603,7 @@ void LayerRendererChromium::updateLayersRecursive(LayerChromium* layer, const Tr
if (sublayer->m_renderSurface) {
RenderSurfaceChromium* sublayerRenderSurface = sublayer->m_renderSurface.get();
- const IntRect& contentRect = sublayerRenderSurface->m_contentRect;
+ const IntRect& contentRect = sublayerRenderSurface->contentRect();
FloatRect sublayerRect(-0.5 * contentRect.width(), -0.5 * contentRect.height(),
contentRect.width(), contentRect.height());
layer->m_drawableContentRect.unite(enclosingIntRect(sublayerRenderSurface->m_drawTransform.mapRect(sublayerRect)));
@@ -664,17 +669,17 @@ bool LayerRendererChromium::useRenderSurface(RenderSurfaceChromium* renderSurfac
m_currentRenderSurface = renderSurface;
if (renderSurface == m_defaultRenderSurface) {
- GLC(m_context, m_context->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, 0));
+ GLC(m_context.get(), m_context->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, 0));
setDrawViewportRect(renderSurface->m_contentRect, true);
return true;
}
- GLC(m_context, m_context->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, m_offscreenFramebufferId));
+ GLC(m_context.get(), m_context->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, m_offscreenFramebufferId));
- renderSurface->prepareContentsTexture();
+ if (!renderSurface->prepareContentsTexture())
+ return false;
- GLC(m_context, m_context->framebufferTexture2D(GraphicsContext3D::FRAMEBUFFER, GraphicsContext3D::COLOR_ATTACHMENT0,
- GraphicsContext3D::TEXTURE_2D, renderSurface->m_contentsTextureId, 0));
+ renderSurface->m_contentsTexture->framebufferTexture2D();
#if !defined ( NDEBUG )
if (m_context->checkFramebufferStatus(GraphicsContext3D::FRAMEBUFFER) != GraphicsContext3D::FRAMEBUFFER_COMPLETE) {
@@ -690,15 +695,7 @@ bool LayerRendererChromium::useRenderSurface(RenderSurfaceChromium* renderSurfac
void LayerRendererChromium::drawLayer(LayerChromium* layer, RenderSurfaceChromium* targetSurface)
{
if (layer->m_renderSurface && layer->m_renderSurface != targetSurface) {
- GLC(m_context, m_context->bindTexture(GraphicsContext3D::TEXTURE_2D, layer->m_renderSurface->m_contentsTextureId));
- useShader(m_textureLayerShaderProgram);
-
- setScissorToRect(layer->m_renderSurface->m_scissorRect);
-
- IntRect contentRect = layer->m_renderSurface->m_contentRect;
- LayerChromium::drawTexturedQuad(m_context.get(), m_projectionMatrix, layer->m_renderSurface->m_drawTransform,
- contentRect.width(), contentRect.height(), layer->m_renderSurface->m_drawOpacity,
- m_textureLayerShaderMatrixLocation, m_textureLayerShaderAlphaLocation);
+ layer->m_renderSurface->draw();
return;
}
@@ -721,12 +718,8 @@ void LayerRendererChromium::drawLayer(LayerChromium* layer, RenderSurfaceChromiu
if (layer->drawsContent()) {
// Update the contents of the layer if necessary.
- if (layer->contentsDirty()) {
- // Update the backing texture contents for any dirty portion of the layer.
- layer->updateContents();
- m_context->makeContextCurrent();
- }
-
+ layer->updateContentsIfDirty();
+ m_context->makeContextCurrent();
layer->draw();
}
@@ -748,7 +741,7 @@ void LayerRendererChromium::setScissorToRect(const IntRect& scissorRect)
scissorY = m_currentRenderSurface->m_contentRect.height() - (scissorRect.bottom() - m_currentRenderSurface->m_contentRect.y());
else
scissorY = scissorRect.y() - m_currentRenderSurface->m_contentRect.y();
- GLC(m_context, m_context->scissor(scissorX, scissorY, scissorRect.width(), scissorRect.height()));
+ GLC(m_context.get(), m_context->scissor(scissorX, scissorY, scissorRect.width(), scissorRect.height()));
}
bool LayerRendererChromium::makeContextCurrent()
@@ -774,7 +767,7 @@ void LayerRendererChromium::setDrawViewportRect(const IntRect& drawRect, bool fl
m_projectionMatrix = orthoMatrix(drawRect.x(), drawRect.right(), drawRect.bottom(), drawRect.y());
else
m_projectionMatrix = orthoMatrix(drawRect.x(), drawRect.right(), drawRect.y(), drawRect.bottom());
- GLC(m_context, m_context->viewport(0, 0, drawRect.width(), drawRect.height()));
+ GLC(m_context.get(), m_context->viewport(0, 0, drawRect.width(), drawRect.height()));
}
@@ -789,46 +782,6 @@ bool LayerRendererChromium::initializeSharedObjects()
{
makeContextCurrent();
- // The following program composites layers whose contents are the results of a previous
- // render operation and therefore doesn't perform any color swizzling. It is used
- // in scrolling and for compositing offscreen textures.
- char textureLayerVertexShaderString[] =
- "attribute vec4 a_position; \n"
- "attribute vec2 a_texCoord; \n"
- "uniform mat4 matrix; \n"
- "varying vec2 v_texCoord; \n"
- "void main() \n"
- "{ \n"
- " gl_Position = matrix * a_position; \n"
- " v_texCoord = a_texCoord; \n"
- "} \n";
- char textureLayerFragmentShaderString[] =
- "precision mediump float; \n"
- "varying vec2 v_texCoord; \n"
- "uniform sampler2D s_texture; \n"
- "uniform float alpha; \n"
- "void main() \n"
- "{ \n"
- " vec4 texColor = texture2D(s_texture, v_texCoord); \n"
- " gl_FragColor = vec4(texColor.x, texColor.y, texColor.z, texColor.w) * alpha; \n"
- "} \n";
-
- m_textureLayerShaderProgram = LayerChromium::createShaderProgram(m_context.get(), textureLayerVertexShaderString, textureLayerFragmentShaderString);
- if (!m_textureLayerShaderProgram) {
- LOG_ERROR("LayerRendererChromium: Failed to create scroll shader program");
- cleanupSharedObjects();
- return false;
- }
-
- GLC(m_context, m_textureLayerShaderSamplerLocation = m_context->getUniformLocation(m_textureLayerShaderProgram, "s_texture"));
- GLC(m_context, m_textureLayerShaderMatrixLocation = m_context->getUniformLocation(m_textureLayerShaderProgram, "matrix"));
- GLC(m_context, m_textureLayerShaderAlphaLocation = m_context->getUniformLocation(m_textureLayerShaderProgram, "alpha"));
- if (m_textureLayerShaderSamplerLocation == -1 || m_textureLayerShaderMatrixLocation == -1 || m_textureLayerShaderAlphaLocation == -1) {
- LOG_ERROR("Failed to initialize texture layer shader.");
- cleanupSharedObjects();
- return false;
- }
-
// Create a texture object to hold the contents of the root layer.
m_rootLayerTextureId = createLayerTexture();
if (!m_rootLayerTextureId) {
@@ -838,28 +791,31 @@ bool LayerRendererChromium::initializeSharedObjects()
}
// Turn off filtering for the root layer to avoid blurring from the repeated
// writes and reads to the framebuffer that happen while scrolling.
- GLC(m_context, m_context->bindTexture(GraphicsContext3D::TEXTURE_2D, m_rootLayerTextureId));
- GLC(m_context, m_context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_MIN_FILTER, GraphicsContext3D::NEAREST));
- GLC(m_context, m_context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_MAG_FILTER, GraphicsContext3D::NEAREST));
+ GLC(m_context.get(), m_context->bindTexture(GraphicsContext3D::TEXTURE_2D, m_rootLayerTextureId));
+ GLC(m_context.get(), m_context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_MIN_FILTER, GraphicsContext3D::NEAREST));
+ GLC(m_context.get(), m_context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_MAG_FILTER, GraphicsContext3D::NEAREST));
// Get the max texture size supported by the system.
- GLC(m_context, m_context->getIntegerv(GraphicsContext3D::MAX_TEXTURE_SIZE, &m_maxTextureSize));
+ m_maxTextureSize = 0;
+ GLC(m_context.get(), m_context->getIntegerv(GraphicsContext3D::MAX_TEXTURE_SIZE, &m_maxTextureSize));
// Create an FBO for doing offscreen rendering.
- GLC(m_context, m_offscreenFramebufferId = m_context->createFramebuffer());
+ GLC(m_context.get(), m_offscreenFramebufferId = m_context->createFramebuffer());
m_layerSharedValues = adoptPtr(new LayerChromium::SharedValues(m_context.get()));
m_contentLayerSharedValues = adoptPtr(new ContentLayerChromium::SharedValues(m_context.get()));
m_canvasLayerSharedValues = adoptPtr(new CanvasLayerChromium::SharedValues(m_context.get()));
m_videoLayerSharedValues = adoptPtr(new VideoLayerChromium::SharedValues(m_context.get()));
m_pluginLayerSharedValues = adoptPtr(new PluginLayerChromium::SharedValues(m_context.get()));
+ m_renderSurfaceSharedValues = adoptPtr(new RenderSurfaceChromium::SharedValues(m_context.get()));
if (!m_layerSharedValues->initialized() || !m_contentLayerSharedValues->initialized() || !m_canvasLayerSharedValues->initialized()
- || !m_videoLayerSharedValues->initialized() || !m_pluginLayerSharedValues->initialized()) {
+ || !m_videoLayerSharedValues->initialized() || !m_pluginLayerSharedValues->initialized() || !m_renderSurfaceSharedValues->initialized()) {
cleanupSharedObjects();
return false;
}
+ m_textureManager = TextureManager::create(m_context.get(), textureMemoryLimitBytes, m_maxTextureSize);
return true;
}
@@ -872,11 +828,7 @@ void LayerRendererChromium::cleanupSharedObjects()
m_canvasLayerSharedValues.clear();
m_videoLayerSharedValues.clear();
m_pluginLayerSharedValues.clear();
-
- if (m_textureLayerShaderProgram) {
- GLC(m_context, m_context->deleteProgram(m_textureLayerShaderProgram));
- m_textureLayerShaderProgram = 0;
- }
+ m_renderSurfaceSharedValues.clear();
if (m_rootLayerTextureId) {
deleteLayerTexture(m_rootLayerTextureId);
@@ -884,7 +836,9 @@ void LayerRendererChromium::cleanupSharedObjects()
}
if (m_offscreenFramebufferId)
- GLC(m_context, m_context->deleteFramebuffer(m_offscreenFramebufferId));
+ GLC(m_context.get(), m_context->deleteFramebuffer(m_offscreenFramebufferId));
+
+ m_textureManager.clear();
}
} // namespace WebCore
diff --git a/WebCore/platform/graphics/chromium/LayerRendererChromium.h b/WebCore/platform/graphics/chromium/LayerRendererChromium.h
index 531d652..c0e610a 100644
--- a/WebCore/platform/graphics/chromium/LayerRendererChromium.h
+++ b/WebCore/platform/graphics/chromium/LayerRendererChromium.h
@@ -108,6 +108,7 @@ public:
const CanvasLayerChromium::SharedValues* canvasLayerSharedValues() const { return m_canvasLayerSharedValues.get(); }
const VideoLayerChromium::SharedValues* videoLayerSharedValues() const { return m_videoLayerSharedValues.get(); }
const PluginLayerChromium::SharedValues* pluginLayerSharedValues() const { return m_pluginLayerSharedValues.get(); }
+ const RenderSurfaceChromium::SharedValues* renderSurfaceSharedValues() const { return m_renderSurfaceSharedValues.get(); }
void resizeOnscreenContent(const IntSize&);
@@ -115,6 +116,10 @@ public:
IntRect rootLayerContentRect() const { return m_rootContentRect; }
void getFramebufferPixels(void *pixels, const IntRect& rect);
+ TextureManager* textureManager() const { return m_textureManager.get(); }
+
+ void setScissorToRect(const IntRect&);
+
private:
explicit LayerRendererChromium(PassRefPtr<GraphicsContext3D> graphicsContext3D);
void updateLayersRecursive(LayerChromium* layer, const TransformationMatrix& parentMatrix, Vector<LayerChromium*>& renderSurfaceLayerList, Vector<LayerChromium*>& layerList);
@@ -123,8 +128,6 @@ private:
bool isLayerVisible(LayerChromium*, const TransformationMatrix&, const IntRect& visibleRect);
- void setScissorToRect(const IntRect&);
-
void setDrawViewportRect(const IntRect&, bool flipY);
bool useRenderSurface(RenderSurfaceChromium*);
@@ -140,13 +143,6 @@ private:
int m_rootLayerTextureWidth;
int m_rootLayerTextureHeight;
- // Shader uniform locations used by layers whose contents are the results of a
- // previous rendering operation.
- unsigned m_textureLayerShaderProgram;
- int m_textureLayerShaderSamplerLocation;
- int m_textureLayerShaderMatrixLocation;
- int m_textureLayerShaderAlphaLocation;
-
TransformationMatrix m_projectionMatrix;
RefPtr<LayerChromium> m_rootLayer;
@@ -186,6 +182,9 @@ private:
OwnPtr<CanvasLayerChromium::SharedValues> m_canvasLayerSharedValues;
OwnPtr<VideoLayerChromium::SharedValues> m_videoLayerSharedValues;
OwnPtr<PluginLayerChromium::SharedValues> m_pluginLayerSharedValues;
+ OwnPtr<RenderSurfaceChromium::SharedValues> m_renderSurfaceSharedValues;
+
+ OwnPtr<TextureManager> m_textureManager;
RefPtr<GraphicsContext3D> m_context;
diff --git a/WebCore/platform/graphics/chromium/LayerTexture.cpp b/WebCore/platform/graphics/chromium/LayerTexture.cpp
new file mode 100644
index 0000000..32bfa0b
--- /dev/null
+++ b/WebCore/platform/graphics/chromium/LayerTexture.cpp
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) 2010, Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#if USE(ACCELERATED_COMPOSITING)
+
+#include "LayerTexture.h"
+
+#include "GraphicsContext3D.h"
+#include "TextureManager.h"
+
+namespace WebCore {
+
+LayerTexture::LayerTexture(GraphicsContext3D* context, TextureManager* manager)
+ : m_context(context)
+ , m_textureManager(manager)
+ , m_token(0)
+ , m_format(0)
+ , m_textureId(0)
+{
+}
+
+LayerTexture::~LayerTexture()
+{
+ if (m_token)
+ m_textureManager->releaseToken(m_token);
+}
+
+bool LayerTexture::isValid(const IntSize& size, unsigned format)
+{
+ return m_token && size == m_size && format == m_format && m_textureManager->hasTexture(m_token);
+}
+
+bool LayerTexture::reserve(const IntSize& size, unsigned format)
+{
+ if (!m_token)
+ m_token = m_textureManager->getToken();
+
+ if (size == m_size && format == m_format && m_textureManager->hasTexture(m_token))
+ m_textureManager->protectTexture(m_token);
+ else {
+ m_textureId = m_textureManager->requestTexture(m_token, size, format);
+ if (m_textureId) {
+ m_size = size;
+ m_format = format;
+ }
+ }
+
+ return m_textureId;
+}
+
+void LayerTexture::unreserve()
+{
+ if (m_token)
+ m_textureManager->unprotectTexture(m_token);
+}
+
+void LayerTexture::bindTexture()
+{
+ m_context->bindTexture(GraphicsContext3D::TEXTURE_2D, m_textureId);
+}
+
+void LayerTexture::framebufferTexture2D()
+{
+ m_context->framebufferTexture2D(GraphicsContext3D::FRAMEBUFFER, GraphicsContext3D::COLOR_ATTACHMENT0, GraphicsContext3D::TEXTURE_2D, m_textureId, 0);
+}
+
+}
+
+#endif // USE(ACCELERATED_COMPOSITING)
+
diff --git a/WebCore/platform/graphics/chromium/LayerTexture.h b/WebCore/platform/graphics/chromium/LayerTexture.h
new file mode 100644
index 0000000..312adfa
--- /dev/null
+++ b/WebCore/platform/graphics/chromium/LayerTexture.h
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2010, Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef LayerTexture_h
+#define LayerTexture_h
+
+#include "IntSize.h"
+#include "TextureManager.h"
+
+#include <wtf/Noncopyable.h>
+#include <wtf/PassOwnPtr.h>
+#include <wtf/RefPtr.h>
+
+namespace WebCore {
+
+class GraphicsContext3D;
+class TextureManager;
+
+class LayerTexture : public Noncopyable {
+public:
+ static PassOwnPtr<LayerTexture> create(GraphicsContext3D* context, TextureManager* manager)
+ {
+ return adoptPtr(new LayerTexture(context, manager));
+ }
+ ~LayerTexture();
+
+ bool isValid(const IntSize&, unsigned format);
+ bool reserve(const IntSize&, unsigned format);
+ void unreserve();
+
+ void bindTexture();
+ void framebufferTexture2D();
+
+private:
+ LayerTexture(GraphicsContext3D*, TextureManager*);
+
+ RefPtr<GraphicsContext3D> m_context;
+ TextureManager* m_textureManager;
+ TextureToken m_token;
+ IntSize m_size;
+ unsigned m_format;
+ unsigned m_textureId;
+};
+
+}
+
+#endif
+
diff --git a/WebCore/platform/graphics/chromium/PluginLayerChromium.cpp b/WebCore/platform/graphics/chromium/PluginLayerChromium.cpp
index 2d1852f..878c142 100644
--- a/WebCore/platform/graphics/chromium/PluginLayerChromium.cpp
+++ b/WebCore/platform/graphics/chromium/PluginLayerChromium.cpp
@@ -102,7 +102,7 @@ void PluginLayerChromium::setTextureId(unsigned id)
m_textureId = id;
}
-void PluginLayerChromium::updateContents()
+void PluginLayerChromium::updateContentsIfDirty()
{
}
diff --git a/WebCore/platform/graphics/chromium/PluginLayerChromium.h b/WebCore/platform/graphics/chromium/PluginLayerChromium.h
index 44a6cc9..853b328 100644
--- a/WebCore/platform/graphics/chromium/PluginLayerChromium.h
+++ b/WebCore/platform/graphics/chromium/PluginLayerChromium.h
@@ -38,7 +38,7 @@ class PluginLayerChromium : public LayerChromium {
public:
static PassRefPtr<PluginLayerChromium> create(GraphicsLayerChromium* owner = 0);
virtual bool drawsContent() { return true; }
- virtual void updateContents();
+ virtual void updateContentsIfDirty();
virtual void draw();
void setTextureId(unsigned textureId);
diff --git a/WebCore/platform/graphics/chromium/RenderSurfaceChromium.cpp b/WebCore/platform/graphics/chromium/RenderSurfaceChromium.cpp
index 816fd3d..e8b9a12 100644
--- a/WebCore/platform/graphics/chromium/RenderSurfaceChromium.cpp
+++ b/WebCore/platform/graphics/chromium/RenderSurfaceChromium.cpp
@@ -31,12 +31,67 @@
#include "GraphicsContext3D.h"
#include "LayerRendererChromium.h"
+#include "LayerTexture.h"
namespace WebCore {
+RenderSurfaceChromium::SharedValues::SharedValues(GraphicsContext3D* context)
+ : m_context(context)
+ , m_shaderProgram(0)
+ , m_shaderSamplerLocation(-1)
+ , m_shaderMatrixLocation(-1)
+ , m_shaderAlphaLocation(-1)
+ , m_initialized(false)
+{
+ // The following program composites layers whose contents are the results of a previous
+ // render operation and therefore doesn't perform any color swizzling. It is used
+ // in scrolling and for compositing offscreen textures.
+ char renderSurfaceVertexShaderString[] =
+ "attribute vec4 a_position; \n"
+ "attribute vec2 a_texCoord; \n"
+ "uniform mat4 matrix; \n"
+ "varying vec2 v_texCoord; \n"
+ "void main() \n"
+ "{ \n"
+ " gl_Position = matrix * a_position; \n"
+ " v_texCoord = a_texCoord; \n"
+ "} \n";
+ char renderSurfaceFragmentShaderString[] =
+ "precision mediump float; \n"
+ "varying vec2 v_texCoord; \n"
+ "uniform sampler2D s_texture; \n"
+ "uniform float alpha; \n"
+ "void main() \n"
+ "{ \n"
+ " vec4 texColor = texture2D(s_texture, v_texCoord); \n"
+ " gl_FragColor = vec4(texColor.x, texColor.y, texColor.z, texColor.w) * alpha; \n"
+ "} \n";
+
+ m_shaderProgram = LayerChromium::createShaderProgram(m_context, renderSurfaceVertexShaderString, renderSurfaceFragmentShaderString);
+ if (!m_shaderProgram) {
+ LOG_ERROR("RenderSurfaceChromium: Failed to create shader program");
+ return;
+ }
+
+ GLC(m_context, m_shaderSamplerLocation = m_context->getUniformLocation(m_shaderProgram, "s_texture"));
+ GLC(m_context, m_shaderMatrixLocation = m_context->getUniformLocation(m_shaderProgram, "matrix"));
+ GLC(m_context, m_shaderAlphaLocation = m_context->getUniformLocation(m_shaderProgram, "alpha"));
+ if (m_shaderSamplerLocation == -1 || m_shaderMatrixLocation == -1 || m_shaderAlphaLocation == -1) {
+ LOG_ERROR("Failed to initialize texture layer shader.");
+ return;
+ }
+ m_initialized = true;
+}
+
+RenderSurfaceChromium::SharedValues::~SharedValues()
+{
+ if (m_shaderProgram)
+ GLC(m_context, m_context->deleteProgram(m_shaderProgram));
+}
+
RenderSurfaceChromium::RenderSurfaceChromium(LayerChromium* owningLayer)
: m_owningLayer(owningLayer)
- , m_contentsTextureId(0)
+ , m_skipsDraw(false)
{
}
@@ -47,14 +102,12 @@ RenderSurfaceChromium::~RenderSurfaceChromium()
void RenderSurfaceChromium::cleanupResources()
{
- if (!m_contentsTextureId)
+ if (!m_contentsTexture)
return;
ASSERT(layerRenderer());
- layerRenderer()->deleteLayerTexture(m_contentsTextureId);
- m_contentsTextureId = 0;
- m_allocatedTextureSize = IntSize();
+ m_contentsTexture.clear();
}
LayerRendererChromium* RenderSurfaceChromium::layerRenderer()
@@ -63,25 +116,41 @@ LayerRendererChromium* RenderSurfaceChromium::layerRenderer()
return m_owningLayer->layerRenderer();
}
-void RenderSurfaceChromium::prepareContentsTexture()
+bool RenderSurfaceChromium::prepareContentsTexture()
{
- ASSERT(m_owningLayer);
+ IntSize requiredSize(m_contentRect.size());
+ TextureManager* textureManager = layerRenderer()->textureManager();
- if (!m_contentsTextureId) {
- m_contentsTextureId = layerRenderer()->createLayerTexture();
- ASSERT(m_contentsTextureId);
- m_allocatedTextureSize = IntSize();
- }
+ if (!m_contentsTexture)
+ m_contentsTexture = LayerTexture::create(layerRenderer()->context(), textureManager);
- IntSize requiredSize(m_contentRect.width(), m_contentRect.height());
- if (m_allocatedTextureSize != requiredSize) {
- GraphicsContext3D* context = m_owningLayer->layerRenderer()->context();
- GLC(context, context->bindTexture(GraphicsContext3D::TEXTURE_2D, m_contentsTextureId));
- GLC(context, context->texImage2D(GraphicsContext3D::TEXTURE_2D, 0, GraphicsContext3D::RGBA,
- requiredSize.width(), requiredSize.height(), 0, GraphicsContext3D::RGBA,
- GraphicsContext3D::UNSIGNED_BYTE, 0));
- m_allocatedTextureSize = requiredSize;
+ if (!m_contentsTexture->reserve(requiredSize, GraphicsContext3D::RGBA)) {
+ m_skipsDraw = true;
+ return false;
}
+
+ m_skipsDraw = false;
+ return true;
+}
+
+void RenderSurfaceChromium::draw()
+{
+ if (m_skipsDraw || !m_contentsTexture)
+ return;
+
+ m_contentsTexture->bindTexture();
+
+ const RenderSurfaceChromium::SharedValues* sv = layerRenderer()->renderSurfaceSharedValues();
+ ASSERT(sv && sv->initialized());
+
+ layerRenderer()->useShader(sv->shaderProgram());
+ layerRenderer()->setScissorToRect(m_scissorRect);
+
+ LayerChromium::drawTexturedQuad(layerRenderer()->context(), layerRenderer()->projectionMatrix(), m_drawTransform,
+ m_contentRect.width(), m_contentRect.height(), m_drawOpacity,
+ sv->shaderMatrixLocation(), sv->shaderAlphaLocation());
+
+ m_contentsTexture->unreserve();
}
}
diff --git a/WebCore/platform/graphics/chromium/RenderSurfaceChromium.h b/WebCore/platform/graphics/chromium/RenderSurfaceChromium.h
index 1f33527..a93218f 100644
--- a/WebCore/platform/graphics/chromium/RenderSurfaceChromium.h
+++ b/WebCore/platform/graphics/chromium/RenderSurfaceChromium.h
@@ -31,13 +31,15 @@
#include "FloatRect.h"
#include "IntRect.h"
+#include "TextureManager.h"
#include "TransformationMatrix.h"
#include <wtf/Noncopyable.h>
namespace WebCore {
-class LayerRendererChromium;
class LayerChromium;
+class LayerRendererChromium;
+class LayerTexture;
class RenderSurfaceChromium : public Noncopyable {
friend class LayerRendererChromium;
@@ -45,20 +47,45 @@ public:
explicit RenderSurfaceChromium(LayerChromium*);
~RenderSurfaceChromium();
- void prepareContentsTexture();
+ bool prepareContentsTexture();
void cleanupResources();
+ void draw();
FloatPoint contentRectCenter() const { return FloatRect(m_contentRect).center(); }
IntRect contentRect() const { return m_contentRect; }
+ // Stores values that are shared between instances of this class that are
+ // associated with the same LayerRendererChromium (and hence the same GL
+ // context).
+ class SharedValues {
+ public:
+ explicit SharedValues(GraphicsContext3D*);
+ ~SharedValues();
+
+ unsigned shaderProgram() const { return m_shaderProgram; }
+ int shaderSamplerLocation() const { return m_shaderSamplerLocation; }
+ int shaderMatrixLocation() const { return m_shaderMatrixLocation; }
+ int shaderAlphaLocation() const { return m_shaderAlphaLocation; }
+ bool initialized() const { return m_initialized; }
+
+ private:
+ GraphicsContext3D* m_context;
+
+ unsigned m_shaderProgram;
+ int m_shaderSamplerLocation;
+ int m_shaderMatrixLocation;
+ int m_shaderAlphaLocation;
+ bool m_initialized;
+ };
+
private:
LayerRendererChromium* layerRenderer();
LayerChromium* m_owningLayer;
IntRect m_contentRect;
- unsigned m_contentsTextureId;
+ bool m_skipsDraw;
+ OwnPtr<LayerTexture> m_contentsTexture;
float m_drawOpacity;
- IntSize m_allocatedTextureSize;
TransformationMatrix m_drawTransform;
TransformationMatrix m_originTransform;
IntRect m_scissorRect;
diff --git a/WebCore/platform/graphics/chromium/SimpleFontDataChromiumWin.cpp b/WebCore/platform/graphics/chromium/SimpleFontDataChromiumWin.cpp
index bcef1fe..204c565 100644
--- a/WebCore/platform/graphics/chromium/SimpleFontDataChromiumWin.cpp
+++ b/WebCore/platform/graphics/chromium/SimpleFontDataChromiumWin.cpp
@@ -112,20 +112,34 @@ void SimpleFontData::platformDestroy()
{
}
+SimpleFontData* SimpleFontData::scaledFontData(const FontDescription& fontDescription, float scaleFactor) const
+{
+ LOGFONT winFont;
+ GetObject(m_platformData.hfont(), sizeof(LOGFONT), &winFont);
+ float scaledSize = scaleFactor * fontDescription.computedSize();
+ winFont.lfHeight = -lroundf(scaledSize);
+ HFONT hfont = CreateFontIndirect(&winFont);
+ return new SimpleFontData(FontPlatformData(hfont, scaledSize), isCustomFont(), false);
+}
+
SimpleFontData* SimpleFontData::smallCapsFontData(const FontDescription& fontDescription) const
{
- if (!m_smallCapsFontData) {
- LOGFONT winFont;
- GetObject(m_platformData.hfont(), sizeof(LOGFONT), &winFont);
- float smallCapsSize = 0.70f * fontDescription.computedSize();
- // Unlike WebKit trunk, we don't multiply the size by 32. That seems
- // to be some kind of artifact of their CG backend, or something.
- winFont.lfHeight = -lroundf(smallCapsSize);
- HFONT hfont = CreateFontIndirect(&winFont);
- m_smallCapsFontData =
- new SimpleFontData(FontPlatformData(hfont, smallCapsSize), isCustomFont(), false);
- }
- return m_smallCapsFontData;
+ if (!m_derivedFontData)
+ m_derivedFontData = DerivedFontData::create(isCustomFont());
+ if (!m_derivedFontData->smallCaps)
+ m_derivedFontData->smallCaps = scaledFontData(fontDescription, .7);
+
+ return m_derivedFontData->smallCaps.get();
+}
+
+SimpleFontData* SimpleFontData::emphasisMarkFontData(const FontDescription& fontDescription) const
+{
+ if (!m_derivedFontData)
+ m_derivedFontData = DerivedFontData::create(isCustomFont());
+ if (!m_derivedFontData->emphasisMark)
+ m_derivedFontData->emphasisMark = scaledFontData(fontDescription, .5);
+
+ return m_derivedFontData->emphasisMark.get();
}
bool SimpleFontData::containsCharacters(const UChar* characters, int length) const
diff --git a/WebCore/platform/graphics/chromium/SimpleFontDataLinux.cpp b/WebCore/platform/graphics/chromium/SimpleFontDataLinux.cpp
index c5190fc..355d837 100644
--- a/WebCore/platform/graphics/chromium/SimpleFontDataLinux.cpp
+++ b/WebCore/platform/graphics/chromium/SimpleFontDataLinux.cpp
@@ -48,6 +48,7 @@ namespace WebCore {
// Smallcaps versions of fonts are 70% the size of the normal font.
static const float smallCapsFraction = 0.7f;
+static const float emphasisMarkFraction = .5;
// This is the largest VDMX table which we'll try to load and parse.
static const size_t maxVDMXTableSize = 1024 * 1024; // 1 MB
@@ -108,6 +109,15 @@ void SimpleFontData::platformInit()
m_lineGap = SkScalarRound(metrics.fLeading);
m_lineSpacing = m_ascent + m_descent + m_lineGap;
+ if (m_orientation == Vertical) {
+ static const uint32_t vheaTag = SkSetFourByteTag('v', 'h', 'e', 'a');
+ static const uint32_t vorgTag = SkSetFourByteTag('V', 'O', 'R', 'G');
+ size_t vheaSize = SkFontHost::GetTableSize(fontID, vheaTag);
+ size_t vorgSize = SkFontHost::GetTableSize(fontID, vorgTag);
+ if ((vheaSize <= 0) && (vorgSize <= 0))
+ m_orientation = Horizontal;
+ }
+
// In WebKit/WebCore/platform/graphics/SimpleFontData.cpp, m_spaceWidth is
// calculated for us, but we need to calculate m_maxCharWidth and
// m_avgCharWidth in order for text entry widgets to be sized correctly.
@@ -141,14 +151,30 @@ void SimpleFontData::platformDestroy()
{
}
+SimpleFontData* SimpleFontData::scaledFontData(const FontDescription& fontDescription, float scaleFactor) const
+{
+ const float scaledSize = lroundf(fontDescription.computedSize() * scaleFactor);
+ return new SimpleFontData(FontPlatformData(m_platformData, scaledSize), isCustomFont(), false);
+}
+
SimpleFontData* SimpleFontData::smallCapsFontData(const FontDescription& fontDescription) const
{
- if (!m_smallCapsFontData) {
- const float smallCapsSize = lroundf(fontDescription.computedSize() * smallCapsFraction);
- m_smallCapsFontData = new SimpleFontData(FontPlatformData(m_platformData, smallCapsSize), isCustomFont(), false);
- }
+ if (!m_derivedFontData)
+ m_derivedFontData = DerivedFontData::create(isCustomFont());
+ if (!m_derivedFontData->smallCaps)
+ m_derivedFontData->smallCaps = scaledFontData(fontDescription, smallCapsFraction);
+
+ return m_derivedFontData->smallCaps.get();
+}
+
+SimpleFontData* SimpleFontData::emphasisMarkFontData(const FontDescription& fontDescription) const
+{
+ if (!m_derivedFontData)
+ m_derivedFontData = DerivedFontData::create(isCustomFont());
+ if (!m_derivedFontData->emphasisMark)
+ m_derivedFontData->emphasisMark = scaledFontData(fontDescription, emphasisMarkFraction);
- return m_smallCapsFontData;
+ return m_derivedFontData->emphasisMark.get();
}
bool SimpleFontData::containsCharacters(const UChar* characters, int length) const
diff --git a/WebCore/platform/graphics/chromium/TextureManager.cpp b/WebCore/platform/graphics/chromium/TextureManager.cpp
new file mode 100644
index 0000000..9579ef9
--- /dev/null
+++ b/WebCore/platform/graphics/chromium/TextureManager.cpp
@@ -0,0 +1,171 @@
+/*
+ * Copyright (C) 2010, Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#if USE(ACCELERATED_COMPOSITING)
+
+#include "TextureManager.h"
+
+#include "LayerRendererChromium.h"
+
+namespace WebCore {
+
+static size_t memoryUseBytes(IntSize size, unsigned textureFormat)
+{
+ // FIXME: This assumes all textures are 4 bytes/pixel, like RGBA.
+ return size.width() * size.height() * 4;
+}
+
+TextureManager::TextureManager(GraphicsContext3D* context, size_t memoryLimitBytes, int maxTextureSize)
+ : m_context(context)
+ , m_memoryLimitBytes(memoryLimitBytes)
+ , m_memoryUseBytes(0)
+ , m_maxTextureSize(maxTextureSize)
+ , m_nextToken(1)
+{
+}
+
+TextureToken TextureManager::getToken()
+{
+ return m_nextToken++;
+}
+
+void TextureManager::releaseToken(TextureToken token)
+{
+ TextureMap::iterator it = m_textures.find(token);
+ if (it != m_textures.end())
+ removeTexture(token, it->second);
+}
+
+bool TextureManager::hasTexture(TextureToken token)
+{
+ if (m_textures.contains(token)) {
+ // If someone asks about a texture put it at the end of the LRU list.
+ m_textureLRUSet.remove(token);
+ m_textureLRUSet.add(token);
+ return true;
+ }
+ return false;
+}
+
+void TextureManager::protectTexture(TextureToken token)
+{
+ ASSERT(hasTexture(token));
+ ASSERT(!m_textures.get(token).isProtected);
+ TextureInfo info = m_textures.take(token);
+ info.isProtected = true;
+ m_textures.add(token, info);
+}
+
+void TextureManager::unprotectTexture(TextureToken token)
+{
+ TextureMap::iterator it = m_textures.find(token);
+ if (it != m_textures.end()) {
+ TextureInfo info = it->second;
+ if (info.isProtected) {
+ info.isProtected = false;
+ m_textures.remove(it);
+ m_textures.add(token, info);
+ }
+ }
+}
+
+bool TextureManager::reduceMemoryToLimit(size_t limit)
+{
+ while (m_memoryUseBytes > limit) {
+ ASSERT(!m_textureLRUSet.isEmpty());
+ bool foundCandidate = false;
+ for (ListHashSet<TextureToken>::iterator lruIt = m_textureLRUSet.begin(); lruIt != m_textureLRUSet.end(); ++lruIt) {
+ TextureToken token = *lruIt;
+ TextureInfo info = m_textures.get(token);
+ if (info.isProtected)
+ continue;
+ removeTexture(token, info);
+ foundCandidate = true;
+ break;
+ }
+ if (!foundCandidate)
+ return false;
+ }
+ return true;
+}
+
+void TextureManager::addTexture(TextureToken token, TextureInfo info)
+{
+ ASSERT(!m_textureLRUSet.contains(token));
+ ASSERT(!m_textures.contains(token));
+ m_memoryUseBytes += memoryUseBytes(info.size, info.format);
+ m_textures.set(token, info);
+ m_textureLRUSet.add(token);
+}
+
+void TextureManager::removeTexture(TextureToken token, TextureInfo info)
+{
+ ASSERT(m_textureLRUSet.contains(token));
+ ASSERT(m_textures.contains(token));
+ m_memoryUseBytes -= memoryUseBytes(info.size, info.format);
+ m_textures.remove(token);
+ ASSERT(m_textureLRUSet.contains(token));
+ m_textureLRUSet.remove(token);
+ GLC(m_context.get(), m_context->deleteTexture(info.textureId));
+}
+
+unsigned TextureManager::requestTexture(TextureToken token, IntSize size, unsigned format, bool* newTexture)
+{
+ if (size.width() > m_maxTextureSize || size.height() > m_maxTextureSize)
+ return 0;
+
+ TextureMap::iterator it = m_textures.find(token);
+ if (it != m_textures.end()) {
+ ASSERT(it->second.size != size || it->second.format != format);
+ removeTexture(token, it->second);
+ }
+
+ size_t memoryRequiredBytes = memoryUseBytes(size, format);
+ if (memoryRequiredBytes > m_memoryLimitBytes || !reduceMemoryToLimit(m_memoryLimitBytes - memoryRequiredBytes))
+ return 0;
+
+ unsigned textureId = m_context->createTexture();
+ GLC(m_context.get(), textureId = m_context->createTexture());
+ GLC(m_context.get(), m_context->bindTexture(GraphicsContext3D::TEXTURE_2D, textureId));
+ // Do basic linear filtering on resize.
+ GLC(m_context.get(), m_context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_MIN_FILTER, GraphicsContext3D::LINEAR));
+ GLC(m_context.get(), m_context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_MAG_FILTER, GraphicsContext3D::LINEAR));
+ // NPOT textures in GL ES only work when the wrap mode is set to GraphicsContext3D::CLAMP_TO_EDGE.
+ GLC(m_context.get(), m_context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_WRAP_S, GraphicsContext3D::CLAMP_TO_EDGE));
+ GLC(m_context.get(), m_context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_WRAP_T, GraphicsContext3D::CLAMP_TO_EDGE));
+ GLC(m_context.get(), m_context->texImage2DResourceSafe(GraphicsContext3D::TEXTURE_2D, 0, format, size.width(), size.height(), 0, format, GraphicsContext3D::UNSIGNED_BYTE));
+ TextureInfo info;
+ info.size = size;
+ info.format = format;
+ info.textureId = textureId;
+ info.isProtected = true;
+ addTexture(token, info);
+ return textureId;
+}
+
+}
+
+#endif // USE(ACCELERATED_COMPOSITING)
diff --git a/WebCore/platform/graphics/chromium/TextureManager.h b/WebCore/platform/graphics/chromium/TextureManager.h
new file mode 100644
index 0000000..1e850cd
--- /dev/null
+++ b/WebCore/platform/graphics/chromium/TextureManager.h
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2010, Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef TextureManager_h
+#define TextureManager_h
+
+#include "GraphicsContext3D.h"
+#include "IntRect.h"
+#include "IntSize.h"
+
+#include <wtf/HashMap.h>
+#include <wtf/ListHashSet.h>
+
+namespace WebCore {
+
+typedef int TextureToken;
+
+class TextureManager : public Noncopyable {
+public:
+ static PassOwnPtr<TextureManager> create(GraphicsContext3D* context, size_t memoryLimitBytes, int maxTextureSize)
+ {
+ return adoptPtr(new TextureManager(context, memoryLimitBytes, maxTextureSize));
+ }
+
+ TextureToken getToken();
+ void releaseToken(TextureToken);
+ bool hasTexture(TextureToken);
+
+ unsigned requestTexture(TextureToken, IntSize, unsigned textureFormat, bool* newTexture = 0);
+
+ void protectTexture(TextureToken);
+ void unprotectTexture(TextureToken);
+
+private:
+ TextureManager(GraphicsContext3D*, size_t memoryLimitBytes, int maxTextureSize);
+
+ struct TextureInfo {
+ IntSize size;
+ unsigned format;
+ unsigned textureId;
+ bool isProtected;
+ };
+
+ bool reduceMemoryToLimit(size_t);
+ void addTexture(TextureToken, TextureInfo);
+ void removeTexture(TextureToken, TextureInfo);
+
+ RefPtr<GraphicsContext3D> m_context;
+
+ typedef HashMap<TextureToken, TextureInfo> TextureMap;
+ TextureMap m_textures;
+ ListHashSet<TextureToken> m_textureLRUSet;
+
+ size_t m_memoryLimitBytes;
+ size_t m_memoryUseBytes;
+ int m_maxTextureSize;
+ TextureToken m_nextToken;
+};
+
+}
+
+#endif
diff --git a/WebCore/platform/graphics/chromium/VideoLayerChromium.cpp b/WebCore/platform/graphics/chromium/VideoLayerChromium.cpp
index feb7ebc..24fd732 100644
--- a/WebCore/platform/graphics/chromium/VideoLayerChromium.cpp
+++ b/WebCore/platform/graphics/chromium/VideoLayerChromium.cpp
@@ -200,8 +200,11 @@ void VideoLayerChromium::cleanupResources()
}
}
-void VideoLayerChromium::updateContents()
+void VideoLayerChromium::updateContentsIfDirty()
{
+ if (!m_contentsDirty)
+ return;
+
RenderLayerBacking* backing = static_cast<RenderLayerBacking*>(m_owner->client());
if (!backing || backing->paintingGoesToWindow())
return;
@@ -297,7 +300,7 @@ bool VideoLayerChromium::allocateTexturesIfNeeded(GraphicsContext3D* context, Vi
void VideoLayerChromium::allocateTexture(GraphicsContext3D* context, unsigned textureId, const IntSize& dimensions, unsigned textureFormat)
{
GLC(context, context->bindTexture(GraphicsContext3D::TEXTURE_2D, textureId));
- GLC(context, context->texImage2D(GraphicsContext3D::TEXTURE_2D, 0, textureFormat, dimensions.width(), dimensions.height(), 0, textureFormat, GraphicsContext3D::UNSIGNED_BYTE, 0));
+ GLC(context, context->texImage2DResourceSafe(GraphicsContext3D::TEXTURE_2D, 0, textureFormat, dimensions.width(), dimensions.height(), 0, textureFormat, GraphicsContext3D::UNSIGNED_BYTE));
}
void VideoLayerChromium::updateTexture(GraphicsContext3D* context, unsigned textureId, const IntSize& dimensions, unsigned format, const void* data)
diff --git a/WebCore/platform/graphics/chromium/VideoLayerChromium.h b/WebCore/platform/graphics/chromium/VideoLayerChromium.h
index 05b6578..0992ab7 100644
--- a/WebCore/platform/graphics/chromium/VideoLayerChromium.h
+++ b/WebCore/platform/graphics/chromium/VideoLayerChromium.h
@@ -45,7 +45,7 @@ public:
static PassRefPtr<VideoLayerChromium> create(GraphicsLayerChromium* owner = 0,
VideoFrameProvider* = 0);
virtual ~VideoLayerChromium();
- virtual void updateContents();
+ virtual void updateContentsIfDirty();
virtual bool drawsContent() { return true; }
virtual void draw();
diff --git a/WebCore/platform/graphics/chromium/WebGLLayerChromium.cpp b/WebCore/platform/graphics/chromium/WebGLLayerChromium.cpp
index 2055ae6..5b34bb9 100644
--- a/WebCore/platform/graphics/chromium/WebGLLayerChromium.cpp
+++ b/WebCore/platform/graphics/chromium/WebGLLayerChromium.cpp
@@ -50,8 +50,11 @@ WebGLLayerChromium::WebGLLayerChromium(GraphicsLayerChromium* owner)
{
}
-void WebGLLayerChromium::updateContents()
+void WebGLLayerChromium::updateContentsIfDirty()
{
+ if (!m_contentsDirty)
+ return;
+
GraphicsContext3D* rendererContext = layerRendererContext();
ASSERT(m_context);
if (m_textureChanged) {
diff --git a/WebCore/platform/graphics/chromium/WebGLLayerChromium.h b/WebCore/platform/graphics/chromium/WebGLLayerChromium.h
index 11b8db7..c67cc2c 100644
--- a/WebCore/platform/graphics/chromium/WebGLLayerChromium.h
+++ b/WebCore/platform/graphics/chromium/WebGLLayerChromium.h
@@ -45,7 +45,7 @@ class WebGLLayerChromium : public CanvasLayerChromium {
public:
static PassRefPtr<WebGLLayerChromium> create(GraphicsLayerChromium* owner = 0);
virtual bool drawsContent() { return m_context; }
- virtual void updateContents();
+ virtual void updateContentsIfDirty();
void setContext(const GraphicsContext3D* context);