diff options
Diffstat (limited to 'WebCore/platform/graphics/chromium')
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); |