diff options
Diffstat (limited to 'WebCore')
21 files changed, 469 insertions, 148 deletions
diff --git a/WebCore/bridge/c/c_utility.cpp b/WebCore/bridge/c/c_utility.cpp index e786896..ea970eb 100644 --- a/WebCore/bridge/c/c_utility.cpp +++ b/WebCore/bridge/c/c_utility.cpp @@ -94,9 +94,15 @@ void convertValueToNPVariant(ExecState* exec, JSValue value, NPVariant* result) OBJECT_TO_NPVARIANT(obj, *result); } } else { +#ifdef ANDROID + RootObject* rootObject = findRootObject(exec->dynamicGlobalObject()); + if (!rootObject) + rootObject = findRootObject(exec->lexicalGlobalObject()); +#else JSGlobalObject* globalObject = exec->dynamicGlobalObject(); RootObject* rootObject = findRootObject(globalObject); +#endif if (rootObject) { NPObject* npObject = _NPN_CreateScriptObject(0, object, rootObject); OBJECT_TO_NPVARIANT(npObject, *result); diff --git a/WebCore/bridge/jni/v8/JavaNPObjectV8.cpp b/WebCore/bridge/jni/v8/JavaNPObjectV8.cpp index 7aa55b5..3bb8e27 100644 --- a/WebCore/bridge/jni/v8/JavaNPObjectV8.cpp +++ b/WebCore/bridge/jni/v8/JavaNPObjectV8.cpp @@ -68,9 +68,7 @@ static NPClass JavaNPObjectClass = { 0 // construct }; -// ANDROID-specific change. TODO: Upstream -NPObject* JavaInstanceToNPObject(PassRefPtr<JavaInstance> instance) -// END ANDROID-specific change +NPObject* JavaInstanceToNPObject(JavaInstance* instance) { JavaNPObject* object = reinterpret_cast<JavaNPObject*>(_NPN_CreateObject(0, &JavaNPObjectClass)); object->m_instance = instance; diff --git a/WebCore/bridge/jni/v8/JavaNPObjectV8.h b/WebCore/bridge/jni/v8/JavaNPObjectV8.h index e68a5aa..31b0ac7 100644 --- a/WebCore/bridge/jni/v8/JavaNPObjectV8.h +++ b/WebCore/bridge/jni/v8/JavaNPObjectV8.h @@ -41,9 +41,7 @@ struct JavaNPObject { RefPtr<JavaInstance> m_instance; }; -// ANDROID-specific change. TODO: Upstream -NPObject* JavaInstanceToNPObject(PassRefPtr<JavaInstance>); -// END ANDROID-specific change +NPObject* JavaInstanceToNPObject(JavaInstance*); JavaInstance* ExtractJavaInstance(NPObject*); bool JavaNPObjectHasMethod(NPObject*, NPIdentifier name); diff --git a/WebCore/platform/graphics/android/AndroidAnimation.cpp b/WebCore/platform/graphics/android/AndroidAnimation.cpp index e01bf55..3280d07 100644 --- a/WebCore/platform/graphics/android/AndroidAnimation.cpp +++ b/WebCore/platform/graphics/android/AndroidAnimation.cpp @@ -54,7 +54,8 @@ long AndroidAnimation::instancesCount() return gDebugAndroidAnimationInstances; } -AndroidAnimation::AndroidAnimation(const Animation* animation, +AndroidAnimation::AndroidAnimation(AndroidAnimationType type, + const Animation* animation, double beginTime) : m_beginTime(beginTime) , m_duration(animation->duration()) @@ -63,6 +64,7 @@ AndroidAnimation::AndroidAnimation(const Animation* animation, , m_direction(animation->direction()) , m_currentDirection(false) , m_timingFunction(animation->timingFunction()) + , m_type(type) { ASSERT(m_timingFunction); @@ -80,6 +82,7 @@ AndroidAnimation::AndroidAnimation(AndroidAnimation* anim) , m_direction(anim->m_direction) , m_currentDirection(false) , m_timingFunction(anim->m_timingFunction) + , m_type(anim->m_type) { gDebugAndroidAnimationInstances++; } @@ -136,28 +139,25 @@ bool AndroidAnimation::checkIterationsAndProgress(double time, float* finalProgr } PassRefPtr<AndroidOpacityAnimation> AndroidOpacityAnimation::create( - float fromValue, - float toValue, const Animation* animation, + KeyframeValueList* operations, double beginTime) { - return adoptRef(new AndroidOpacityAnimation(fromValue, toValue, - animation, beginTime)); + return adoptRef(new AndroidOpacityAnimation(animation, operations, + beginTime)); } -AndroidOpacityAnimation::AndroidOpacityAnimation(float fromValue, float toValue, - const Animation* animation, +AndroidOpacityAnimation::AndroidOpacityAnimation(const Animation* animation, + KeyframeValueList* operations, double beginTime) - : AndroidAnimation(animation, beginTime) - , m_fromValue(fromValue) - , m_toValue(toValue) + : AndroidAnimation(AndroidAnimation::OPACITY, animation, beginTime) + , m_operations(operations) { } AndroidOpacityAnimation::AndroidOpacityAnimation(AndroidOpacityAnimation* anim) : AndroidAnimation(anim) - , m_fromValue(anim->m_fromValue) - , m_toValue(anim->m_toValue) + , m_operations(anim->m_operations) { } @@ -175,8 +175,51 @@ bool AndroidOpacityAnimation::evaluate(LayerAndroid* layer, double time) if (progress < 0) // we still want to be evaluated until we get progress > 0 return true; - float value = m_fromValue + ((m_toValue - m_fromValue) * progress); + // First, we need to get the from and to values + + FloatAnimationValue* fromValue = 0; + FloatAnimationValue* toValue = 0; + + float distance = 0; + unsigned int foundAt = 0; + for (unsigned int i = 0; i < m_operations->size(); i++) { + FloatAnimationValue* value = (FloatAnimationValue*) m_operations->at(i); + float opacity = (float) value->value(); + float key = value->keyTime(); + float d = progress - key; + XLOG("[%d] Key %.2f, opacity %.4f", i, key, opacity); + if (!fromValue || (d > 0 && d < distance && i + 1 < m_operations->size())) { + fromValue = value; + distance = d; + foundAt = i; + } + } + + if (foundAt + 1 < m_operations->size()) + toValue = (FloatAnimationValue*) m_operations->at(foundAt + 1); + else + toValue = fromValue; + + XLOG("[layer %d] fromValue %x, key %.2f, toValue %x, key %.2f for progress %.2f", + layer->uniqueId(), + fromValue, fromValue->keyTime(), + toValue, toValue->keyTime(), progress); + + // We now have the correct two values to work with, let's compute the + // progress value + + float delta = toValue->keyTime() - fromValue->keyTime(); + float rprogress = (progress - fromValue->keyTime()) / delta; + XLOG("We picked keys %.2f to %.2f for progress %.2f, real progress %.2f", + fromValue->keyTime(), toValue->keyTime(), progress, rprogress); + progress = rprogress; + + float from = (float) fromValue->value(); + float to = (float) toValue->value(); + float value = from + ((to - from) * progress); + layer->setOpacity(value); + XLOG("AndroidOpacityAnimation::evaluate(%p, %p, %L) value=%.6f", this, layer, time, value); return true; } @@ -191,7 +234,7 @@ PassRefPtr<AndroidTransformAnimation> AndroidTransformAnimation::create( AndroidTransformAnimation::AndroidTransformAnimation(const Animation* animation, KeyframeValueList* operations, double beginTime) - : AndroidAnimation(animation, beginTime) + : AndroidAnimation(AndroidAnimation::TRANSFORM, animation, beginTime) , m_operations(operations) { } @@ -235,9 +278,9 @@ bool AndroidTransformAnimation::evaluate(LayerAndroid* layer, double time) TransformAnimationValue* value = (TransformAnimationValue*) m_operations->at(i); TransformOperations* values = (TransformOperations*) value->value(); float key = value->keyTime(); - float d = fabs(progress - key); + float d = progress - key; XLOG("[%d] Key %.2f, %d values", i, key, values->size()); - if (!fromValue || (d < distance && i + 1 < m_operations->size())) { + if (!fromValue || (d > 0 && d < distance && i + 1 < m_operations->size())) { fromValue = value; distance = d; foundAt = i; diff --git a/WebCore/platform/graphics/android/AndroidAnimation.h b/WebCore/platform/graphics/android/AndroidAnimation.h index 3cc1608..d682103 100644 --- a/WebCore/platform/graphics/android/AndroidAnimation.h +++ b/WebCore/platform/graphics/android/AndroidAnimation.h @@ -35,7 +35,13 @@ class TimingFunction; class AndroidAnimation : public RefCounted<AndroidAnimation> { public: - AndroidAnimation(const Animation* animation, + enum AndroidAnimationType { + UNDEFINED, + OPACITY, + TRANSFORM + }; + AndroidAnimation(AndroidAnimationType type, + const Animation* animation, double beginTime); AndroidAnimation(AndroidAnimation* anim); @@ -48,6 +54,7 @@ class AndroidAnimation : public RefCounted<AndroidAnimation> { static long instancesCount(); void setName(const String& name) { m_name = name; } String name() { return m_name; } + AndroidAnimationType type() { return m_type; } protected: double m_beginTime; @@ -59,16 +66,16 @@ class AndroidAnimation : public RefCounted<AndroidAnimation> { bool m_currentDirection; RefPtr<TimingFunction> m_timingFunction; String m_name; + AndroidAnimationType m_type; }; class AndroidOpacityAnimation : public AndroidAnimation { public: - static PassRefPtr<AndroidOpacityAnimation> create(float fromValue, - float toValue, - const Animation* animation, - double beginTime); - AndroidOpacityAnimation(float fromValue, float toValue, - const Animation* animation, + static PassRefPtr<AndroidOpacityAnimation> create(const Animation* animation, + KeyframeValueList* operations, + double beginTime); + AndroidOpacityAnimation(const Animation* animation, + KeyframeValueList* operations, double beginTime); AndroidOpacityAnimation(AndroidOpacityAnimation* anim); virtual PassRefPtr<AndroidAnimation> copy(); @@ -76,8 +83,7 @@ class AndroidOpacityAnimation : public AndroidAnimation { virtual bool evaluate(LayerAndroid* layer, double time); private: - float m_fromValue; - float m_toValue; + KeyframeValueList* m_operations; }; class AndroidTransformAnimation : public AndroidAnimation { diff --git a/WebCore/platform/graphics/android/BackedDoubleBufferedTexture.cpp b/WebCore/platform/graphics/android/BackedDoubleBufferedTexture.cpp index 7cfa480..470ecf1 100644 --- a/WebCore/platform/graphics/android/BackedDoubleBufferedTexture.cpp +++ b/WebCore/platform/graphics/android/BackedDoubleBufferedTexture.cpp @@ -42,8 +42,6 @@ BackedDoubleBufferedTexture::BackedDoubleBufferedTexture(uint32_t w, uint32_t h, SkBitmap* bitmap, SkBitmap::Config config) : DoubleBufferedTexture(eglGetCurrentContext()) - , m_x(-1) - , m_y(-1) , m_usedLevel(-1) , m_config(config) , m_owner(0) @@ -147,6 +145,21 @@ bool BackedDoubleBufferedTexture::busy() return m_busy; } +bool BackedDoubleBufferedTexture::textureExist(TextureInfo* textureInfo) +{ + if (!m_bitmap) + return false; + + if (!m_bitmap->width() || !m_bitmap->height()) + return false; + + if (textureInfo->m_width == m_bitmap->width() && + textureInfo->m_height == m_bitmap->height()) + return true; + + return false; +} + void BackedDoubleBufferedTexture::producerUpdate(TextureInfo* textureInfo) { if (!m_bitmap) @@ -158,7 +171,7 @@ void BackedDoubleBufferedTexture::producerUpdate(TextureInfo* textureInfo) return; } - if (textureInfo->m_width == m_bitmap->width() && textureInfo->m_height == m_bitmap->height()) + if (textureExist(textureInfo)) GLUtils::updateTextureWithBitmap(textureInfo->m_textureId, *m_bitmap); else { GLUtils::createTextureWithBitmap(textureInfo->m_textureId, *m_bitmap); @@ -227,4 +240,31 @@ bool BackedDoubleBufferedTexture::release(TextureOwner* owner) return false; } +void BackedDoubleBufferedTexture::setTile(TextureInfo* info, int x, int y, + float scale, unsigned int pictureCount) +{ + TextureTileInfo* textureInfo = m_texturesInfo.get(getWriteableTexture()); + if (!textureInfo) { + textureInfo = new TextureTileInfo(); + } + textureInfo->m_x = x; + textureInfo->m_y = y; + textureInfo->m_scale = scale; + textureInfo->m_picture = pictureCount; + m_texturesInfo.set(getWriteableTexture(), textureInfo); +} + +bool BackedDoubleBufferedTexture::readyFor(BaseTile* baseTile) +{ + TextureTileInfo* info = m_texturesInfo.get(getReadableTexture()); + if (info && + (info->m_x == baseTile->x()) && + (info->m_y == baseTile->y()) && + (info->m_scale == baseTile->scale()) && + (info->m_picture == baseTile->lastPaintedPicture())) { + return true; + } + return false; +} + } // namespace WebCore diff --git a/WebCore/platform/graphics/android/BackedDoubleBufferedTexture.h b/WebCore/platform/graphics/android/BackedDoubleBufferedTexture.h index b1f170b..9c1d245 100644 --- a/WebCore/platform/graphics/android/BackedDoubleBufferedTexture.h +++ b/WebCore/platform/graphics/android/BackedDoubleBufferedTexture.h @@ -37,6 +37,23 @@ namespace WebCore { class BaseTile; +class TextureTileInfo { + public: + TextureTileInfo() + : m_x(-1) + , m_y(-1) + , m_scale(0) + , m_texture(0) + , m_picture(0) + { + } + int m_x; + int m_y; + float m_scale; + TextureInfo* m_texture; + unsigned int m_picture; +}; + // DoubleBufferedTexture using a SkBitmap as backing mechanism class BackedDoubleBufferedTexture : public DoubleBufferedTexture { public: @@ -55,6 +72,8 @@ public: // updates the texture with current bitmap and releases (and if needed also // swaps) the texture. virtual void producerUpdate(TextureInfo* textureInfo); + void producerUpdate(TextureInfo* textureInfo, SkBitmap* bitmap, SkIRect& rect); + bool textureExist(TextureInfo* textureInfo); // The level can be one of the following values: // * -1 for an unused texture. @@ -76,21 +95,21 @@ public: // private member accessor functions TextureOwner* owner() { return m_owner; } // only used by the consumer thread SkCanvas* canvas(); // only used by the producer thread + SkBitmap* bitmap() { return m_bitmap; } bool busy(); void setNotBusy(); const SkSize& getSize() const { return m_size; } - int x() { return m_x; } - int y() { return m_y; } - void setTile(int x, int y) { m_x = x; m_y = y; } + void setTile(TextureInfo* info, int x, int y, float scale, unsigned int pictureCount); + bool readyFor(BaseTile* baseTile); private: void destroyTextures(SharedTexture** textures); - int m_x; - int m_y; + HashMap<SharedTexture*, TextureTileInfo*> m_texturesInfo; + SkBitmap* m_bitmap; bool m_sharedBitmap; SkSize m_size; diff --git a/WebCore/platform/graphics/android/BaseLayerAndroid.cpp b/WebCore/platform/graphics/android/BaseLayerAndroid.cpp index 584add1..1f969be 100644 --- a/WebCore/platform/graphics/android/BaseLayerAndroid.cpp +++ b/WebCore/platform/graphics/android/BaseLayerAndroid.cpp @@ -159,7 +159,7 @@ bool BaseLayerAndroid::drawBasePictureInGL(SkRect& viewport, float scale, double bool zooming = false; if (m_glWebViewState->scaleRequestState() != GLWebViewState::kNoScaleRequest) { - m_glWebViewState->unlockBaseLayerUpdate(); + prepareNextTiledPage = true; zooming = true; } @@ -168,7 +168,7 @@ bool BaseLayerAndroid::drawBasePictureInGL(SkRect& viewport, float scale, double TiledPage* nextTiledPage = m_glWebViewState->backPage(); nextTiledPage->setScale(scale); m_glWebViewState->setFutureViewport(viewportTileBounds); - m_glWebViewState->unlockBaseLayerUpdate(); + m_glWebViewState->lockBaseLayerUpdate(); nextTiledPage->prepare(goingDown, goingLeft, viewportTileBounds); } @@ -212,7 +212,7 @@ bool BaseLayerAndroid::drawBasePictureInGL(SkRect& viewport, float scale, double TiledPage* nextTiledPage = m_glWebViewState->backPage(); - // We are now using an hybrid model -- during zooming or scrolling, + // We are now using an hybrid model -- during scrolling, // we will display the current tiledPage even if some tiles are // out of date. When standing still on the other hand, we wait until // the back page is ready before swapping the pages, ensuring that the @@ -232,7 +232,9 @@ bool BaseLayerAndroid::drawBasePictureInGL(SkRect& viewport, float scale, double } } else { // Ask for the tiles and draw -- tiles may be out of date. - m_glWebViewState->unlockBaseLayerUpdate(); + if (!zooming) + m_glWebViewState->unlockBaseLayerUpdate(); + tiledPage->prepare(goingDown, goingLeft, preZoomBounds); tiledPage->draw(transparency, preZoomBounds); } @@ -245,6 +247,7 @@ bool BaseLayerAndroid::drawBasePictureInGL(SkRect& viewport, float scale, double if (doSwap) { m_glWebViewState->setCurrentScale(scale); m_glWebViewState->swapPages(); + m_glWebViewState->unlockBaseLayerUpdate(); } return ret; @@ -260,8 +263,8 @@ bool BaseLayerAndroid::drawGL(IntRect& viewRect, SkRect& visibleRect, int top = viewRect.y(); int width = viewRect.width(); int height = viewRect.height(); - XLOG("drawBasePicture drawGL() viewRect: %d, %d, %d, %d", - left, top, width, height); + XLOG("drawBasePicture drawGL() viewRect: %d, %d, %d, %d - %.2f", + left, top, width, height, scale); m_glWebViewState->setBackgroundColor(color); glClearColor((float)m_color.red() / 255.0, diff --git a/WebCore/platform/graphics/android/BaseTile.cpp b/WebCore/platform/graphics/android/BaseTile.cpp index 9499870..47be13b 100644 --- a/WebCore/platform/graphics/android/BaseTile.cpp +++ b/WebCore/platform/graphics/android/BaseTile.cpp @@ -67,11 +67,15 @@ BaseTile::BaseTile() , m_dirty(true) , m_usable(true) , m_lastDirtyPicture(0) + , m_fullRepaintA(true) + , m_fullRepaintB(true) + , m_painting(false) , m_lastPaintedPicture(0) { #ifdef DEBUG_COUNT ClassTracker::instance()->increment("BaseTile"); #endif + m_currentDirtyArea = &m_dirtyAreaA; } BaseTile::~BaseTile() @@ -100,11 +104,12 @@ void BaseTile::reserveTexture() BackedDoubleBufferedTexture* texture = TilesManager::instance()->getAvailableTexture(this); android::AutoMutex lock(m_atomicSync); - if (m_texture != texture) { + if (texture && !m_painting && + m_texture != texture) { m_lastPaintedPicture = 0; - m_dirty = true; + fullInval(); + m_texture = texture; } - m_texture = texture; } bool BaseTile::removeTexture(BackedDoubleBufferedTexture* texture) @@ -112,25 +117,39 @@ bool BaseTile::removeTexture(BackedDoubleBufferedTexture* texture) XLOG("%x removeTexture res: %x... page %x", this, m_texture, m_page); // We update atomically, so paintBitmap() can see the correct value android::AutoMutex lock(m_atomicSync); + if (m_painting) + return false; if (m_texture == texture) m_texture = 0; return true; } +void BaseTile::fullInval() +{ + m_dirtyAreaA.setEmpty(); + m_dirtyAreaB.setEmpty(); + m_fullRepaintA = true; + m_fullRepaintB = true; + m_dirty = true; +} + void BaseTile::setScale(float scale) { android::AutoMutex lock(m_atomicSync); - if (m_scale != scale) - m_dirty = true; - m_scale = scale; + if (m_scale != scale) { + m_scale = scale; + fullInval(); + } } -void BaseTile::markAsDirty(int unsigned pictureCount) +void BaseTile::markAsDirty(int unsigned pictureCount, + const SkRegion& dirtyArea) { android::AutoMutex lock(m_atomicSync); m_lastDirtyPicture = pictureCount; - if (m_lastPaintedPicture < m_lastDirtyPicture) - m_dirty = true; + m_dirtyAreaA.op(dirtyArea, SkRegion::kUnion_Op); + m_dirtyAreaB.op(dirtyArea, SkRegion::kUnion_Op); + m_dirty = true; } void BaseTile::setUsable(bool usable) @@ -154,6 +173,9 @@ void BaseTile::setUsedLevel(int usedLevel) void BaseTile::draw(float transparency, SkRect& rect) { + if (m_x < 0 || m_y < 0) + return; + // No need to mutex protect reads of m_texture as it is only written to by // the consumer thread. if (!m_texture) { @@ -175,9 +197,6 @@ void BaseTile::draw(float transparency, SkRect& rect) return; } - if (m_texture->x() != m_x || m_texture->y() != m_y) - return; - TextureInfo* textureInfo = m_texture->consumerLock(); if (!textureInfo) { XLOG("%x (%d, %d) trying to draw, but no textureInfo!", this, x(), y()); @@ -185,9 +204,11 @@ void BaseTile::draw(float transparency, SkRect& rect) return; } - TilesManager::instance()->shader()->drawQuad(rect, textureInfo->m_textureId, - transparency); - + if (m_texture->readyFor(this)) { + XLOG("draw tile %d, %d, %.2f with texture %x", x(), y(), scale(), m_texture); + TilesManager::instance()->shader()->drawQuad(rect, textureInfo->m_textureId, + transparency); + } m_texture->consumerRelease(); } @@ -199,21 +220,33 @@ bool BaseTile::isTileReady() return false; android::AutoMutex lock(m_atomicSync); - return !m_dirty; + if (m_dirty) + return false; + + m_texture->consumerLock(); + bool ready = m_texture->readyFor(this); + m_texture->consumerRelease(); + + if (ready) + return true; + + m_dirty = true; + return false; } void BaseTile::drawTileInfo(SkCanvas* canvas, BackedDoubleBufferedTexture* texture, - int x, int y, float scale) + int x, int y, float scale, + int pictureCount) { SkPaint paint; char str[256]; - snprintf(str, 256, "(%d,%d) %.2f, tile %x, texture: %x", - x, y, scale, this, texture); + snprintf(str, 256, "(%d,%d) %.2f, tl%x tx%x p%x c%x", + x, y, scale, this, texture, m_page, pictureCount); paint.setARGB(255, 0, 0, 0); - canvas->drawText(str, strlen(str), 50, 100, paint); + canvas->drawText(str, strlen(str), 0, 10, paint); paint.setARGB(255, 255, 0, 0); - canvas->drawText(str, strlen(str), 51, 101, paint); + canvas->drawText(str, strlen(str), 0, 11, paint); } // This is called from the texture generation thread @@ -226,11 +259,15 @@ void BaseTile::paintBitmap() m_atomicSync.lock(); bool dirty = m_dirty; BackedDoubleBufferedTexture* texture = m_texture; + SkRegion dirtyArea = *m_currentDirtyArea; + m_painting = true; float scale = m_scale; m_atomicSync.unlock(); - if (!dirty || !texture) + if (!dirty || !texture) { + m_painting = false; return; + } const int x = m_x; const int y = m_y; @@ -243,6 +280,7 @@ void BaseTile::paintBitmap() // transferred to another BaseTile under us) if (texture->owner() != this || texture->usedLevel() > 1) { texture->producerRelease(); + m_painting = false; return; } @@ -255,70 +293,160 @@ void BaseTile::paintBitmap() float h = tileHeight * invScale; SkCanvas* canvas; + unsigned int pictureCount = 0; + + SkRegion::Iterator cliperator(dirtyArea); + + bool fullRepaint = false; + if (((m_currentDirtyArea == &m_dirtyAreaA) && m_fullRepaintA) || + ((m_currentDirtyArea == &m_dirtyAreaB) && m_fullRepaintB)) + fullRepaint = true; + + if (fullRepaint) { + SkIRect rect; + pictureCount = paintPartialBitmap(rect, 0, 0, scale, texture, + textureInfo, tiledPage, true); + } else { + while (!cliperator.done()) { + SkRect dirtyRect; + dirtyRect.set(cliperator.rect()); + + SkRect tileRect; + tileRect.fLeft = x * tileWidth / scale; + tileRect.fTop = y * tileHeight / scale; + tileRect.fRight = tileRect.fLeft + (tileWidth / scale); + tileRect.fBottom = tileRect.fTop + (tileHeight / scale); + + if (!tileRect.intersect(dirtyRect)) { + cliperator.next(); + continue; + } + + // recompute the rect to corresponds to pixels + SkRect realTileRect; + realTileRect.fLeft = floorf(tileRect.fLeft * scale); + realTileRect.fTop = floorf(tileRect.fTop * scale); + realTileRect.fRight = ceilf(tileRect.fRight * scale); + realTileRect.fBottom = ceilf(tileRect.fBottom * scale); + + SkIRect finalRealRect; + finalRealRect.fLeft = static_cast<int>(realTileRect.fLeft) % static_cast<int>(tileWidth); + finalRealRect.fTop = static_cast<int>(realTileRect.fTop) % static_cast<int>(tileHeight); + finalRealRect.fRight = finalRealRect.fLeft + realTileRect.width(); + finalRealRect.fBottom = finalRealRect.fTop + realTileRect.height(); + + // the canvas translate can be recomputed accounting for the scale + float tx = - realTileRect.fLeft / scale; + float ty = - realTileRect.fTop / scale; + + pictureCount = paintPartialBitmap(finalRealRect, tx, ty, scale, texture, + textureInfo, tiledPage); + + cliperator.next(); + } + } + XLOG("%x update texture %x for tile %d, %d scale %.2f (m_scale: %.2f)", this, textureInfo, x, y, scale, m_scale); -#ifdef USE_SKIA_GPU - GLuint fboId; - glGenFramebuffersEXT(1, &fboId); - glBindFramebuffer(GL_FRAMEBUFFER, fboId); - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, textureInfo->m_textureId, 0); - glCheckFramebufferStatus(GL_FRAMEBUFFER)); // should return GL_FRAMEBUFFER_COMPLETE - - //Do I need to assign a width/height/format? - - GrContext* context = gr_get_global_ctx(); - context->resetContext(); - GrRenderTarget* target = context->createPlatformRenderTarget(fboId, tileWidth, tileHeight); - SkCanvas tmpCanvas; - SkDevice* device = new SkGpuDevice(context, bm, target); - tmpCanvas.setDevice(device)->unref(); - canvas = &tmpCanvas; -#else - canvas = texture->canvas(); -#endif + m_atomicSync.lock(); + texture->setTile(textureInfo, x, y, scale, pictureCount); + texture->producerReleaseAndSwap(); + + m_lastPaintedPicture = pictureCount; - canvas->save(); - canvas->drawColor(tiledPage->glWebViewState()->getBackgroundColor()); - canvas->scale(scale, scale); - canvas->translate(-x * w, -y * h); + // set the fullrepaint flags - unsigned int pictureCount = tiledPage->paintBaseLayerContent(canvas); + if ((m_currentDirtyArea == &m_dirtyAreaA) && m_fullRepaintA) + m_fullRepaintA = false; - canvas->restore(); + if ((m_currentDirtyArea == &m_dirtyAreaB) && m_fullRepaintB) + m_fullRepaintB = false; + + // The various checks to see if we are still dirty... + + m_dirty = false; + + if (m_scale != scale) + m_dirty = true; + + if (!fullRepaint) + m_currentDirtyArea->op(dirtyArea, SkRegion::kDifference_Op); + + if (!m_currentDirtyArea->isEmpty()) + m_dirty = true; + + // Now we can swap the dirty areas + + m_currentDirtyArea = m_currentDirtyArea == &m_dirtyAreaA ? &m_dirtyAreaB : &m_dirtyAreaA; + + if (!m_currentDirtyArea->isEmpty()) + m_dirty = true; + + m_painting = false; + + m_atomicSync.unlock(); +} + +int BaseTile::paintPartialBitmap(SkIRect r, float ptx, float pty, + float scale, BackedDoubleBufferedTexture* texture, + TextureInfo* textureInfo, + TiledPage* tiledPage, bool fullRepaint) +{ + SkIRect rect = r; + float tx = ptx; + float ty = pty; + if (!texture->textureExist(textureInfo)) { + fullRepaint = true; + } + + if (fullRepaint) { + rect.set(0, 0, TilesManager::instance()->tileWidth(), + TilesManager::instance()->tileHeight()); + tx = - x() * TilesManager::instance()->tileWidth() / scale; + ty = - y() * TilesManager::instance()->tileHeight() / scale; + } + + SkBitmap bitmap; + bitmap.setConfig(SkBitmap::kARGB_8888_Config, rect.width(), rect.height()); + bitmap.allocPixels(); + bitmap.eraseColor(0); + + SkCanvas canvas(bitmap); + canvas.drawARGB(255, 255, 255, 255); + + canvas.save(); + canvas.scale(scale, scale); + canvas.translate(tx, ty); + int pictureCount = tiledPage->paintBaseLayerContent(&canvas); + canvas.restore(); if (TilesManager::instance()->getShowVisualIndicator()) { + int color = 20 + pictureCount % 100; + canvas.drawARGB(color, 0, 255, 0); + SkPaint paint; paint.setARGB(128, 255, 0, 0); paint.setStrokeWidth(3); - canvas->drawLine(0, 0, tileWidth, tileHeight, paint); + canvas.drawLine(0, 0, rect.width(), rect.height(), paint); paint.setARGB(128, 0, 255, 0); - canvas->drawLine(0, tileHeight, tileWidth, 0, paint); + canvas.drawLine(0, rect.height(), rect.width(), 0, paint); paint.setARGB(128, 0, 0, 255); - canvas->drawLine(0, 0, tileWidth, 0, paint); - canvas->drawLine(tileWidth, 0, tileWidth, tileHeight, paint); - drawTileInfo(canvas, texture, x, y, scale); - } + canvas.drawLine(0, 0, rect.width(), 0, paint); + canvas.drawLine(rect.width(), 0, rect.width(), rect.height(), paint); - texture->setTile(x, y); + drawTileInfo(&canvas, texture, x(), y(), scale, pictureCount); + } -#ifdef USE_SKIA_GPU - // set the texture info w/h/format - textureInfo->m_width = tileWidth; - textureInfo->m_height = tileHeight; - texture->producerReleaseAndSwap(); + if (!texture->textureExist(textureInfo)) { + GLUtils::createTextureWithBitmap(textureInfo->m_textureId, bitmap); + textureInfo->m_width = rect.width(); + textureInfo->m_height = rect.height(); + } else { + GLUtils::updateTextureWithBitmap(textureInfo->m_textureId, rect.fLeft, rect.fTop, bitmap); + } - glBindFramebuffer(GL_FRAMEBUFFER, 0); // rebind the standard FBO - glDeleteFramebuffers(1, &fboId); -#else - texture->producerUpdate(textureInfo); -#endif + bitmap.reset(); - m_atomicSync.lock(); - m_lastPaintedPicture = pictureCount; - if (m_lastPaintedPicture >= m_lastDirtyPicture) { - m_dirty = false; - m_usable = true; - } - m_atomicSync.unlock(); + return pictureCount; } } // namespace WebCore diff --git a/WebCore/platform/graphics/android/BaseTile.h b/WebCore/platform/graphics/android/BaseTile.h index af7df3a..c50f6f5 100644 --- a/WebCore/platform/graphics/android/BaseTile.h +++ b/WebCore/platform/graphics/android/BaseTile.h @@ -29,9 +29,11 @@ #if USE(ACCELERATED_COMPOSITING) #include "HashMap.h" +#include "SharedTexture.h" #include "SkBitmap.h" #include "SkCanvas.h" #include "SkRect.h" +#include "SkRegion.h" #include "TextureOwner.h" #include <EGL/egl.h> @@ -75,18 +77,26 @@ public: // the only thread-safe function called by the background thread void paintBitmap(); + int paintPartialBitmap(SkIRect rect, float tx, float ty, + float scale, BackedDoubleBufferedTexture* texture, + TextureInfo* textureInfo, + TiledPage* tiledPage, + bool fullRepaint = false); void drawTileInfo(SkCanvas* canvas, BackedDoubleBufferedTexture* texture, - int x, int y, float scale); + int x, int y, float scale, int pictureCount); - void markAsDirty(const unsigned int pictureCount); + void markAsDirty(const unsigned int pictureCount, + const SkRegion& dirtyArea); bool isDirty(); void setUsable(bool usable); float scale() const { return m_scale; } void setScale(float scale); + void fullInval(); int x() const { return m_x; } int y() const { return m_y; } + unsigned int lastPaintedPicture() const { return m_lastPaintedPicture; } BackedDoubleBufferedTexture* texture() { return m_texture; } // TextureOwner implementation @@ -110,6 +120,15 @@ private: // become dirty. A tile is no longer dirty when it has been painted with a // picture that is newer than this value. unsigned int m_lastDirtyPicture; + + // store the dirty region + SkRegion m_dirtyAreaA; + SkRegion m_dirtyAreaB; + bool m_fullRepaintA; + bool m_fullRepaintB; + SkRegion* m_currentDirtyArea; + bool m_painting; + // stores the id of the latest picture painted to the tile. If the id is 0 // then we know that the picture has not yet been painted an there is nothing // to display (dirty or otherwise). diff --git a/WebCore/platform/graphics/android/DoubleBufferedTexture.h b/WebCore/platform/graphics/android/DoubleBufferedTexture.h index b611c2e..5016332 100644 --- a/WebCore/platform/graphics/android/DoubleBufferedTexture.h +++ b/WebCore/platform/graphics/android/DoubleBufferedTexture.h @@ -48,12 +48,13 @@ public: void consumerRelease(); protected: + SharedTexture* getReadableTexture(); + SharedTexture* getWriteableTexture(); + SharedTexture m_textureA; SharedTexture m_textureB; private: - SharedTexture* getReadableTexture(); - SharedTexture* getWriteableTexture(); SharedTexture* m_writeableTexture; SharedTexture* m_lockedConsumerTexture; // only used by the consumer diff --git a/WebCore/platform/graphics/android/GLUtils.cpp b/WebCore/platform/graphics/android/GLUtils.cpp index de794cb..23bf525 100644 --- a/WebCore/platform/graphics/android/GLUtils.cpp +++ b/WebCore/platform/graphics/android/GLUtils.cpp @@ -361,6 +361,27 @@ void GLUtils::updateTextureWithBitmap(GLuint texture, SkBitmap& bitmap, GLint fi glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filter); } +void GLUtils::updateTextureWithBitmap(GLuint texture, int x, int y, SkBitmap& bitmap, GLint filter) +{ + glPixelStorei(GL_UNPACK_ALIGNMENT, 1); + glBindTexture(GL_TEXTURE_2D, texture); + GLUtils::checkGlError("glBindTexture"); + SkBitmap::Config config = bitmap.getConfig(); + int internalformat = getInternalFormat(config); + int type = getType(config); + bitmap.lockPixels(); + glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, bitmap.width(), bitmap.height(), + internalformat, type, bitmap.getPixels()); + bitmap.unlockPixels(); + if (GLUtils::checkGlError("glTexSubImage2D")) { + XLOG("GL ERROR: glTexSubImage2D parameters are : bitmap.width() %d, bitmap.height() %d," + " internalformat 0x%x, type 0x%x, bitmap.getPixels() %p", + bitmap.width(), bitmap.height(), internalformat, type, bitmap.getPixels()); + } + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filter); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filter); +} + void GLUtils::createEGLImageFromTexture(GLuint texture, EGLImageKHR* image) { EGLClientBuffer buffer = reinterpret_cast<EGLClientBuffer>(texture); diff --git a/WebCore/platform/graphics/android/GLUtils.h b/WebCore/platform/graphics/android/GLUtils.h index 3e7b800..64aedbb 100644 --- a/WebCore/platform/graphics/android/GLUtils.h +++ b/WebCore/platform/graphics/android/GLUtils.h @@ -62,6 +62,7 @@ public: static GLuint createSampleTexture(); static void createTextureWithBitmap(GLuint texture, SkBitmap& bitmap, GLint filter = GL_LINEAR); static void updateTextureWithBitmap(GLuint texture, SkBitmap& bitmap, GLint filter = GL_LINEAR); + static void updateTextureWithBitmap(GLuint texture, int x, int y, SkBitmap& bitmap, GLint filter = GL_LINEAR); static void createEGLImageFromTexture(GLuint texture, EGLImageKHR* image); static void createTextureFromEGLImage(GLuint texture, EGLImageKHR image, GLint filter = GL_LINEAR); }; diff --git a/WebCore/platform/graphics/android/GLWebViewState.cpp b/WebCore/platform/graphics/android/GLWebViewState.cpp index 20a231c..444ff17 100644 --- a/WebCore/platform/graphics/android/GLWebViewState.cpp +++ b/WebCore/platform/graphics/android/GLWebViewState.cpp @@ -110,7 +110,7 @@ GLWebViewState::~GLWebViewState() #endif } -void GLWebViewState::setBaseLayer(BaseLayerAndroid* layer, const IntRect& rect, +void GLWebViewState::setBaseLayer(BaseLayerAndroid* layer, const SkRegion& inval, bool showVisualIndicator) { android::Mutex::Autolock lock(m_baseLayerLock); @@ -131,7 +131,7 @@ void GLWebViewState::setBaseLayer(BaseLayerAndroid* layer, const IntRect& rect, SkSafeUnref(m_currentBaseLayer); m_currentBaseLayer = layer; } - inval(rect); + invalRegion(inval); #ifdef MEASURES_PERF if (m_measurePerfs && !showVisualIndicator) @@ -142,15 +142,29 @@ void GLWebViewState::setBaseLayer(BaseLayerAndroid* layer, const IntRect& rect, TilesManager::instance()->setShowVisualIndicator(showVisualIndicator); } +void GLWebViewState::invalRegion(const SkRegion& region) +{ + SkRegion::Iterator iterator(region); + while (!iterator.done()) { + SkIRect r = iterator.rect(); + IntRect ir(r.fLeft, r.fTop, r.width(), r.height()); + inval(ir); + iterator.next(); + } +} + void GLWebViewState::unlockBaseLayerUpdate() { + if (m_baseLayerUpdate) + return; + m_baseLayerUpdate = true; android::Mutex::Autolock lock(m_baseLayerLock); SkSafeRef(m_baseLayer); SkSafeUnref(m_currentBaseLayer); m_currentBaseLayer = m_baseLayer; - inval(m_invalidateRect); - IntRect empty; - m_invalidateRect = empty; + + invalRegion(m_invalidateRegion); + m_invalidateRegion.setEmpty(); } void GLWebViewState::setExtra(BaseLayerAndroid* layer, SkPicture& picture, @@ -182,7 +196,7 @@ void GLWebViewState::inval(const IntRect& rect) m_tiledPageB->invalidateRect(rect, m_currentPictureCounter); } } else { - m_invalidateRect.unite(rect); + m_invalidateRegion.op(rect.x(), rect.y(), rect.right(), rect.bottom(), SkRegion::kUnion_Op); } } diff --git a/WebCore/platform/graphics/android/GLWebViewState.h b/WebCore/platform/graphics/android/GLWebViewState.h index b8194f4..3f68757 100644 --- a/WebCore/platform/graphics/android/GLWebViewState.h +++ b/WebCore/platform/graphics/android/GLWebViewState.h @@ -32,6 +32,7 @@ #include "IntRect.h" #include "SkCanvas.h" #include "SkRect.h" +#include "SkRegion.h" #include "TiledPage.h" #include <utils/threads.h> @@ -174,7 +175,7 @@ public: void resetTransitionTime() { m_transitionTime = -1; } unsigned int paintBaseLayerContent(SkCanvas* canvas); - void setBaseLayer(BaseLayerAndroid* layer, const IntRect& rect, bool showVisualIndicator); + void setBaseLayer(BaseLayerAndroid* layer, const SkRegion& inval, bool showVisualIndicator); void setExtra(BaseLayerAndroid*, SkPicture&, const IntRect&, bool allowSame); void scheduleUpdate(const double& currentTime, const SkIRect& viewport, float scale); @@ -223,6 +224,7 @@ public: private: void inval(const IntRect& rect); // caller must hold m_baseLayerLock + void invalRegion(const SkRegion& region); // Delay between scheduling a new page when the scale // factor changes (i.e. zooming in or out) @@ -259,7 +261,7 @@ private: android::Mutex* m_globalButtonMutex; bool m_baseLayerUpdate; - IntRect m_invalidateRect; + SkRegion m_invalidateRegion; SkColor m_backgroundColor; double m_prevDrawTime; diff --git a/WebCore/platform/graphics/android/GraphicsLayerAndroid.cpp b/WebCore/platform/graphics/android/GraphicsLayerAndroid.cpp index 4cd48a8..54346e5 100644 --- a/WebCore/platform/graphics/android/GraphicsLayerAndroid.cpp +++ b/WebCore/platform/graphics/android/GraphicsLayerAndroid.cpp @@ -728,15 +728,21 @@ bool GraphicsLayerAndroid::createAnimationFromKeyframes(const KeyframeValueList& case AnimatedPropertyInvalid: break; case AnimatedPropertyWebkitTransform: break; case AnimatedPropertyBackgroundColor: break; + case AnimatedPropertyOpacity: { MLOG("ANIMATEDPROPERTYOPACITY"); - const FloatAnimationValue* startVal = - static_cast<const FloatAnimationValue*>(valueList.at(0)); - const FloatAnimationValue* endVal = - static_cast<const FloatAnimationValue*>(valueList.at(1)); - RefPtr<AndroidOpacityAnimation> anim = AndroidOpacityAnimation::create(startVal->value(), - endVal->value(), - animation, + + KeyframeValueList* operationsList = new KeyframeValueList(AnimatedPropertyOpacity); + for (unsigned int i = 0; i < valueList.size(); i++) { + FloatAnimationValue* originalValue = (FloatAnimationValue*)valueList.at(i); + FloatAnimationValue* value = new FloatAnimationValue(originalValue->keyTime(), + originalValue->value(), 0); + // TODO: pass the timing function originalValue->timingFunction()); + operationsList->insert(value); + } + + RefPtr<AndroidOpacityAnimation> anim = AndroidOpacityAnimation::create(animation, + operationsList, beginTime); if (keyframesName.isEmpty()) anim->setName(propertyIdToString(valueList.property())); diff --git a/WebCore/platform/graphics/android/LayerAndroid.cpp b/WebCore/platform/graphics/android/LayerAndroid.cpp index 842637a..7d68f03 100644 --- a/WebCore/platform/graphics/android/LayerAndroid.cpp +++ b/WebCore/platform/graphics/android/LayerAndroid.cpp @@ -243,7 +243,8 @@ bool LayerAndroid::evaluateAnimations(double time) const void LayerAndroid::addAnimation(PassRefPtr<AndroidAnimation> prpAnim) { RefPtr<AndroidAnimation> anim = prpAnim; - if (m_animations.get(anim->name())) + RefPtr<AndroidAnimation> currentAnim = m_animations.get(anim->name()); + if (currentAnim && currentAnim->type() == anim->type()) removeAnimation(anim->name()); m_animations.add(anim->name(), anim); } @@ -741,9 +742,9 @@ void LayerAndroid::showLayers(int indent) bool outside = outsideViewport(); if (needsTexture() && !outside) { - XLOGC("%s Layer %d (%d, %d), cropped to (%d, %d), using %d Mb", + XLOGC("%s Layer %d (%.2f, %.2f), cropped to (%d, %d, %d, %d), using %d Mb", space, uniqueId(), getWidth(), getHeight(), - cr.width(), cr.height(), size / 1024 / 1024); + cr.x(), cr.y(), cr.width(), cr.height(), size / 1024 / 1024); } else if (needsTexture() && outside) { XLOGC("%s Layer %d is outside the viewport", space, uniqueId()); } else { diff --git a/WebCore/platform/graphics/android/TileSet.h b/WebCore/platform/graphics/android/TileSet.h index 0cb16d0..aa0f2ed 100644 --- a/WebCore/platform/graphics/android/TileSet.h +++ b/WebCore/platform/graphics/android/TileSet.h @@ -58,6 +58,11 @@ public: return m_tiledPage; } + unsigned int size() + { + return m_tiles.size(); + } + private: Vector<BaseTile*> m_tiles; diff --git a/WebCore/platform/graphics/android/TiledPage.cpp b/WebCore/platform/graphics/android/TiledPage.cpp index 36988dd..a400a4a 100644 --- a/WebCore/platform/graphics/android/TiledPage.cpp +++ b/WebCore/platform/graphics/android/TiledPage.cpp @@ -129,6 +129,7 @@ void TiledPage::invalidateRect(const IntRect& inval, const unsigned int pictureC // We defer marking the tile as dirty until the next time we need to prepare // to draw. m_invalRegion.op(firstDirtyTileX, firstDirtyTileY, lastDirtyTileX, lastDirtyTileY, SkRegion::kUnion_Op); + m_invalTilesRegion.op(inval.x(), inval.y(), inval.right(), inval.bottom(), SkRegion::kUnion_Op); m_latestPictureInval = pictureCount; } @@ -183,11 +184,12 @@ void TiledPage::updateTileState(const SkIRect& tileBounds) { if (!m_glWebViewState || tileBounds.isEmpty()) { m_invalRegion.setEmpty(); + m_invalTilesRegion.setEmpty(); return; } - const int nbTilesWidth = tileBounds.width(); - const int nbTilesHeight = tileBounds.height(); + const int nbTilesWidth = tileBounds.width() - 1; + const int nbTilesHeight = tileBounds.height() - 1; const int lastTileX = tileBounds.fRight - 1; const int lastTileY = tileBounds.fBottom - 1; @@ -196,14 +198,14 @@ void TiledPage::updateTileState(const SkIRect& tileBounds) BaseTile& tile = m_baseTiles[x]; + // if the tile is in the dirty region then we must invalidate it + if (m_invalRegion.contains(tile.x(), tile.y())) + tile.markAsDirty(m_latestPictureInval, m_invalTilesRegion); + // if the tile no longer has a texture then proceed to the next tile if (tile.isAvailable()) continue; - // if the tile is in the dirty region then we must invalidate it - if (m_invalRegion.contains(tile.x(), tile.y())) - tile.markAsDirty(m_latestPictureInval); - // set the used level of the tile (e.g. distance from the viewport) int dx = 0; int dy = 0; @@ -226,6 +228,7 @@ void TiledPage::updateTileState(const SkIRect& tileBounds) // clear the invalidated region as all tiles within that region have now // been marked as dirty. m_invalRegion.setEmpty(); + m_invalTilesRegion.setEmpty(); } void TiledPage::prepare(bool goingDown, bool goingLeft, const SkIRect& tileBounds) diff --git a/WebCore/platform/graphics/android/TiledPage.h b/WebCore/platform/graphics/android/TiledPage.h index e449107..9eb9f11 100644 --- a/WebCore/platform/graphics/android/TiledPage.h +++ b/WebCore/platform/graphics/android/TiledPage.h @@ -97,6 +97,9 @@ private: // terms of the (x,y) coordinates used to determine the location of the tile // within the page, not in content/view pixel coordinates. SkRegion m_invalRegion; + + // inval regions in content coordinates + SkRegion m_invalTilesRegion; unsigned int m_latestPictureInval; bool m_prepare; }; diff --git a/WebCore/platform/graphics/android/TilesManager.cpp b/WebCore/platform/graphics/android/TilesManager.cpp index 16fb782..0cb30d2 100644 --- a/WebCore/platform/graphics/android/TilesManager.cpp +++ b/WebCore/platform/graphics/android/TilesManager.cpp @@ -56,10 +56,10 @@ // second page used when scaling. // In our case, we use 300x300 textures. On the tablet, this equates to // at least 5 * 3 = 15 textures. We also enable offscreen textures to a maximum -// of 154 textures used (i.e. ~106Mb max, accounting for the double buffer textures) +// of 101 textures used (i.e. ~70Mb max, accounting for the double buffer textures) #define EXPANDED_TILE_BOUNDS_X 1 -#define EXPANDED_TILE_BOUNDS_Y 4 -#define MAX_TEXTURE_ALLOCATION (5+EXPANDED_TILE_BOUNDS_X*2)*(3+EXPANDED_TILE_BOUNDS_Y*2)*2 +#define EXPANDED_TILE_BOUNDS_Y 2 +#define MAX_TEXTURE_ALLOCATION 3+(5+EXPANDED_TILE_BOUNDS_X*2)*(3+EXPANDED_TILE_BOUNDS_Y*2)*2 #define TILE_WIDTH 300 #define TILE_HEIGHT 300 @@ -162,7 +162,8 @@ BackedDoubleBufferedTexture* TilesManager::getAvailableTexture(BaseTile* owner) // Sanity check that the tile does not already own a texture if (owner->texture() && owner->texture()->owner() == owner) { owner->texture()->setUsedLevel(0); - XLOG("same owner, getAvailableTexture(%x) => texture %x", owner, owner->texture()); + XLOG("same owner (%d, %d), getAvailableTexture(%x) => texture %x", + owner->x(), owner->y(), owner, owner->texture()); return owner->texture(); } @@ -314,8 +315,10 @@ void TilesManager::cleanupLayersTextures(LayerAndroid* layer, bool forceCleanup) i++; } } +#ifdef DEBUG printLayersTextures("after cleanup"); XLOG("after cleanup, memory %d", m_layersMemoryUsage); +#endif } LayerTexture* TilesManager::createTextureForLayer(LayerAndroid* layer, const IntRect& rect) @@ -414,6 +417,7 @@ TilesManager* TilesManager::instance() { if (!gInstance) { gInstance = new TilesManager(); + XLOG("instance(), new gInstance is %x", gInstance); XLOG("Waiting for the generator..."); gInstance->waitForGenerator(); XLOG("Generator ready!"); |