Changeset 53949 in webkit
- Timestamp:
- Jan 27, 2010 1:14:03 PM (14 years ago)
- Location:
- trunk/WebCore
- Files:
-
- 6 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/WebCore/ChangeLog
r53947 r53949 1 2010-01-27 Oliver Hunt <oliver@apple.com> 2 3 Reviewed by Simon Fraser. 4 5 Animated scaling of background-image is too slow 6 https://bugs.webkit.org/show_bug.cgi?id=33808 7 8 Implement a version of the RenderImage animated scaling optimisation 9 for background images. Due to the possibility of arbitrary transforms 10 being applied to containing elements we explicitly check the current 11 CTM of the context for scaling or rotation. 12 13 * platform/graphics/GraphicsContext.cpp: 14 (WebCore::GraphicsContext::drawTiledImage): 15 * platform/graphics/GraphicsContext.h: 16 * platform/graphics/transforms/TransformationMatrix.h: 17 (WebCore::TransformationMatrix::isIdentityOrTranslation): 18 * rendering/RenderBoxModelObject.cpp: 19 (WebCore::RenderBoxModelScaleData::RenderBoxModelScaleData): 20 (WebCore::RenderBoxModelScaleData::~RenderBoxModelScaleData): 21 (WebCore::RenderBoxModelScaleData::size): 22 (WebCore::RenderBoxModelScaleData::time): 23 (WebCore::RenderBoxModelScaleData::useLowQualityScale): 24 (WebCore::RenderBoxModelScaleData::hiqhQualityRepaintTimer): 25 (WebCore::RenderBoxModelScaleData::setSize): 26 (WebCore::RenderBoxModelScaleData::setTime): 27 (WebCore::RenderBoxModelScaleData::setUseLowQualityScale): 28 (WebCore::RenderBoxModelScaleObserver::boxModelObjectDestroyed): 29 (WebCore::RenderBoxModelScaleObserver::highQualityRepaintTimerFired): 30 (WebCore::RenderBoxModelScaleObserver::shouldPaintBackgroundAtLowQuality): 31 (WebCore::RenderBoxModelObject::highQualityRepaintTimerFired): 32 (WebCore::RenderBoxModelObject::~RenderBoxModelObject): 33 (WebCore::RenderBoxModelObject::paintFillLayerExtended): 34 * rendering/RenderBoxModelObject.h: 35 1 36 2010-01-27 Yael Aharon <yael.aharon@nokia.com> 2 37 -
trunk/WebCore/platform/graphics/GraphicsContext.cpp
r52791 r53949 412 412 } 413 413 414 void GraphicsContext::drawTiledImage(Image* image, ColorSpace styleColorSpace, const IntRect& rect, const IntPoint& srcPoint, const IntSize& tileSize, CompositeOperator op )414 void GraphicsContext::drawTiledImage(Image* image, ColorSpace styleColorSpace, const IntRect& rect, const IntPoint& srcPoint, const IntSize& tileSize, CompositeOperator op, bool useLowQualityScale) 415 415 { 416 416 if (paintingDisabled() || !image) 417 417 return; 418 418 if (useLowQualityScale) { 419 save(); 420 setImageInterpolationQuality(InterpolationLow); 421 } 419 422 image->drawTiled(this, rect, srcPoint, tileSize, styleColorSpace, op); 420 } 421 422 void GraphicsContext::drawTiledImage(Image* image, ColorSpace styleColorSpace, const IntRect& dest, const IntRect& srcRect, Image::TileRule hRule, Image::TileRule vRule, CompositeOperator op) 423 if (useLowQualityScale) 424 restore(); 425 } 426 427 void GraphicsContext::drawTiledImage(Image* image, ColorSpace styleColorSpace, const IntRect& dest, const IntRect& srcRect, Image::TileRule hRule, Image::TileRule vRule, CompositeOperator op, bool useLowQualityScale) 423 428 { 424 429 if (paintingDisabled() || !image) 425 430 return; 426 431 432 if (useLowQualityScale) { 433 save(); 434 setImageInterpolationQuality(InterpolationLow); 435 } 427 436 if (hRule == Image::StretchTile && vRule == Image::StretchTile) 428 437 // Just do a scale. 429 return drawImage(image, styleColorSpace, dest, srcRect, op); 430 431 image->drawTiled(this, dest, srcRect, hRule, vRule, styleColorSpace, op); 438 drawImage(image, styleColorSpace, dest, srcRect, op); 439 else 440 image->drawTiled(this, dest, srcRect, hRule, vRule, styleColorSpace, op); 441 if (useLowQualityScale) 442 restore(); 432 443 } 433 444 -
trunk/WebCore/platform/graphics/GraphicsContext.h
r53857 r53949 221 221 CompositeOperator = CompositeSourceOver, bool useLowQualityScale = false); 222 222 void drawTiledImage(Image*, ColorSpace styleColorSpace, const IntRect& destRect, const IntPoint& srcPoint, const IntSize& tileSize, 223 CompositeOperator = CompositeSourceOver );223 CompositeOperator = CompositeSourceOver, bool useLowQualityScale = false); 224 224 void drawTiledImage(Image*, ColorSpace styleColorSpace, const IntRect& destRect, const IntRect& srcRect, 225 225 Image::TileRule hRule = Image::StretchTile, Image::TileRule vRule = Image::StretchTile, 226 CompositeOperator = CompositeSourceOver );226 CompositeOperator = CompositeSourceOver, bool useLowQualityScale = false); 227 227 228 228 void setImageInterpolationQuality(InterpolationQuality); -
trunk/WebCore/platform/graphics/transforms/TransformationMatrix.h
r53485 r53949 320 320 #endif 321 321 322 bool isIdentityOrTranslation() const 323 { 324 return m_matrix[0][0] == 1 && m_matrix[0][1] == 0 && m_matrix[0][2] == 0 && m_matrix[0][3] == 0 325 && m_matrix[1][0] == 0 && m_matrix[1][1] == 1 && m_matrix[1][2] == 0 && m_matrix[1][3] == 0 326 && m_matrix[2][0] == 0 && m_matrix[2][1] == 0 && m_matrix[2][2] == 1 && m_matrix[2][3] == 0 327 && m_matrix[3][3] == 1; 328 } 329 322 330 private: 323 331 // multiply passed 2D point by matrix (assume z=0) 324 332 void multVecMatrix(double x, double y, double& dstX, double& dstY) const; 325 333 326 334 // multiply passed 3D point by matrix 327 335 void multVecMatrix(double x, double y, double z, double& dstX, double& dstY, double& dstZ) const; 328 336 329 337 void setMatrix(const Matrix4 m) 330 338 { … … 332 340 memcpy(m_matrix, m, sizeof(Matrix4)); 333 341 } 334 335 bool isIdentityOrTranslation() const 336 { 337 return m_matrix[0][0] == 1 && m_matrix[0][1] == 0 && m_matrix[0][2] == 0 && m_matrix[0][3] == 0 && 338 m_matrix[1][0] == 0 && m_matrix[1][1] == 1 && m_matrix[1][2] == 0 && m_matrix[1][3] == 0 && 339 m_matrix[2][0] == 0 && m_matrix[2][1] == 0 && m_matrix[2][2] == 1 && m_matrix[2][3] == 0 && 340 m_matrix[3][3] == 1; 341 } 342 342 343 343 Matrix4 m_matrix; 344 344 }; -
trunk/WebCore/rendering/RenderBoxModelObject.cpp
r53476 r53949 45 45 bool RenderBoxModelObject::s_layerWasSelfPainting = false; 46 46 47 static const double cInterpolationCutoff = 800. * 800.; 48 static const double cLowQualityTimeThreshold = 0.500; // 500 ms 49 50 class RenderBoxModelScaleData : public Noncopyable { 51 public: 52 RenderBoxModelScaleData(RenderBoxModelObject* object, const IntSize& size, double time, bool lowQualityScale) 53 : m_size(size) 54 , m_lastPaintTime(time) 55 , m_lowQualityScale(lowQualityScale) 56 , m_highQualityRepaintTimer(object, &RenderBoxModelObject::highQualityRepaintTimerFired) 57 { 58 } 59 60 ~RenderBoxModelScaleData() 61 { 62 m_highQualityRepaintTimer.stop(); 63 } 64 65 Timer<RenderBoxModelObject>& hiqhQualityRepaintTimer() { return m_highQualityRepaintTimer; } 66 67 const IntSize& size() const { return m_size; } 68 void setSize(const IntSize& s) { m_size = s; } 69 double lastPaintTime() const { return m_lastPaintTime; } 70 void setLastPaintTime(double t) { m_lastPaintTime = t; } 71 bool useLowQualityScale() const { return m_lowQualityScale; } 72 void setUseLowQualityScale(bool b) 73 { 74 m_highQualityRepaintTimer.stop(); 75 m_lowQualityScale = b; 76 if (b) 77 m_highQualityRepaintTimer.startOneShot(cLowQualityTimeThreshold); 78 } 79 80 private: 81 IntSize m_size; 82 double m_lastPaintTime; 83 bool m_lowQualityScale; 84 Timer<RenderBoxModelObject> m_highQualityRepaintTimer; 85 }; 86 87 class RenderBoxModelScaleObserver { 88 public: 89 static bool shouldPaintBackgroundAtLowQuality(GraphicsContext*, RenderBoxModelObject*, Image*, const IntSize&); 90 91 static void boxModelObjectDestroyed(RenderBoxModelObject* object) 92 { 93 if (gBoxModelObjects) { 94 RenderBoxModelScaleData* data = gBoxModelObjects->take(object); 95 delete data; 96 if (!gBoxModelObjects->size()) { 97 delete gBoxModelObjects; 98 gBoxModelObjects = 0; 99 } 100 } 101 } 102 103 static void highQualityRepaintTimerFired(RenderBoxModelObject* object) 104 { 105 RenderBoxModelScaleObserver::boxModelObjectDestroyed(object); 106 object->repaint(); 107 } 108 109 static HashMap<RenderBoxModelObject*, RenderBoxModelScaleData*>* gBoxModelObjects; 110 }; 111 112 bool RenderBoxModelScaleObserver::shouldPaintBackgroundAtLowQuality(GraphicsContext* context, RenderBoxModelObject* object, Image* image, const IntSize& size) 113 { 114 // If the image is not a bitmap image, then none of this is relevant and we just paint at high 115 // quality. 116 if (!image->isBitmapImage()) 117 return false; 118 119 // Make sure to use the unzoomed image size, since if a full page zoom is in effect, the image 120 // is actually being scaled. 121 IntSize imageSize(image->width(), image->height()); 122 123 // Look ourselves up in the hashtable. 124 RenderBoxModelScaleData* data = 0; 125 if (gBoxModelObjects) 126 data = gBoxModelObjects->get(object); 127 128 bool contextIsScaled = !context->getCTM().isIdentityOrTranslation(); 129 if (!contextIsScaled && imageSize == size) { 130 // There is no scale in effect. If we had a scale in effect before, we can just delete this data. 131 if (data) { 132 gBoxModelObjects->remove(object); 133 delete data; 134 } 135 return false; 136 } 137 138 // There is no need to hash scaled images that always use low quality mode when the page demands it. This is the iChat case. 139 if (object->document()->page()->inLowQualityImageInterpolationMode()) { 140 double totalPixels = static_cast<double>(image->width()) * static_cast<double>(image->height()); 141 if (totalPixels > cInterpolationCutoff) 142 return true; 143 } 144 145 // If there is no data yet, we will paint the first scale at high quality and record the paint time in case a second scale happens 146 // very soon. 147 if (!data) { 148 data = new RenderBoxModelScaleData(object, size, currentTime(), false); 149 if (!gBoxModelObjects) 150 gBoxModelObjects = new HashMap<RenderBoxModelObject*, RenderBoxModelScaleData*>; 151 gBoxModelObjects->set(object, data); 152 return false; 153 } 154 155 // We are scaled, but we painted already at this size, so just keep using whatever mode we last painted with. 156 if (!contextIsScaled && data->size() == size) 157 return data->useLowQualityScale(); 158 159 // We have data and our size just changed. If this change happened quickly, go into low quality mode and then set a repaint 160 // timer to paint in high quality mode. Otherwise it is ok to just paint in high quality mode. 161 double newTime = currentTime(); 162 data->setUseLowQualityScale(newTime - data->lastPaintTime() < cLowQualityTimeThreshold); 163 data->setLastPaintTime(newTime); 164 data->setSize(size); 165 return data->useLowQualityScale(); 166 } 167 168 HashMap<RenderBoxModelObject*, RenderBoxModelScaleData*>* RenderBoxModelScaleObserver::gBoxModelObjects = 0; 169 170 void RenderBoxModelObject::highQualityRepaintTimerFired(Timer<RenderBoxModelObject>*) 171 { 172 RenderBoxModelScaleObserver::highQualityRepaintTimerFired(this); 173 } 174 47 175 RenderBoxModelObject::RenderBoxModelObject(Node* node) 48 176 : RenderObject(node) … … 56 184 ASSERT(!hasLayer()); 57 185 ASSERT(!m_layer); 186 RenderBoxModelScaleObserver::boxModelObjectDestroyed(this); 58 187 } 59 188 … … 308 437 { 309 438 GraphicsContext* context = paintInfo.context; 439 if (context->paintingDisabled()) 440 return; 441 310 442 bool includeLeftEdge = box ? box->includeLeftEdge() : true; 311 443 bool includeRightEdge = box ? box->includeRightEdge() : true; … … 465 597 CompositeOperator compositeOp = op == CompositeSourceOver ? bgLayer->composite() : op; 466 598 RenderObject* clientForBackgroundImage = backgroundObject ? backgroundObject : this; 467 context->drawTiledImage(bg->image(clientForBackgroundImage, tileSize), style()->colorSpace(), destRect, phase, tileSize, compositeOp); 599 Image* image = bg->image(clientForBackgroundImage, tileSize); 600 bool useLowQualityScaling = RenderBoxModelScaleObserver::shouldPaintBackgroundAtLowQuality(context, this, image, destRect.size()); 601 context->drawTiledImage(image, style()->colorSpace(), destRect, phase, tileSize, compositeOp, useLowQualityScaling); 468 602 } 469 603 } -
trunk/WebCore/rendering/RenderBoxModelObject.h
r53291 r53949 99 99 void destroyLayer(); 100 100 101 void highQualityRepaintTimerFired(Timer<RenderBoxModelObject>*); 102 101 103 protected: 102 104 void calculateBackgroundImageGeometry(const FillLayer*, int tx, int ty, int w, int h, IntRect& destRect, IntPoint& phase, IntSize& tileSize);
Note: See TracChangeset
for help on using the changeset viewer.