size_t WaitableEvent::waitMultiple(const WTF::Vector<WaitableEvent*>& events) { std::vector<base::WaitableEvent*> baseEvents; for (size_t i = 0; i < events.size(); ++i) baseEvents.push_back(events[i]->m_impl.get()); size_t idx = base::WaitableEvent::WaitMany(baseEvents.data(), baseEvents.size()); DCHECK_LT(idx, events.size()); return idx; }
void MediaConstraints::getOptionalConstraints(std::vector<MediaConstraint>& constraints) const { ASSERT(!isNull()); WTF::Vector<WebCore::MediaConstraint> optionalConstraints; m_private->getOptionalConstraints(optionalConstraints); std::vector<MediaConstraint> result(optionalConstraints.size()); for (size_t i = 0; i < optionalConstraints.size(); ++i) result[i] = toNixMediaConstraint(optionalConstraints[i]); constraints.swap(result); }
jbyteArray WebHistory::Flatten(JNIEnv* env, WTF::Vector<char>& v, WebCore::HistoryItem* item) { if (!item) return NULL; // Reserve a vector of chars with an initial size of HISTORY_MIN_SIZE. v.reserveCapacity(HISTORY_MIN_SIZE); // Write the top-level history item and then write all the children // recursively. LOG_ASSERT(item->bridge(), "Why don't we have a bridge object here?"); write_item(v, item); write_children_recursive(v, item); //SAMSUNG - CRASH FIX BEGIN int size = v.size(); if (size > 0) { long availableMemory = GetVmAvailableMemory(env); if(size > availableMemory) { LOGV("WebHistory::Flatten(): load size=%d, availableMemory=%ld, still larger, return NULL", size, availableMemory); return NULL; } checkException(env); } //SAMSUNG - CRASH FIX END // Try to create a new java byte array. jbyteArray b = env->NewByteArray(v.size()); if (!b) { //SAMSUNG - CRASH FIX BEGIN if (checkException(env)) { LOGV("WebHistory::Flatten(): env exception happened while allocating %d bytes, clear pending exception", v.size()); env->ExceptionClear(); } //SAMSUNG - CRASH FIX END return NULL; } // Write our flattened data to the java array. env->SetByteArrayRegion(b, 0, v.size(), (const jbyte*)v.data()); return b; }
void SpellCheckerClientImpl::checkGrammarOfString(const String& text, WTF::Vector<GrammarDetail>& details, int* badGrammarLocation, int* badGrammarLength) { if (badGrammarLocation) *badGrammarLocation = -1; if (badGrammarLength) *badGrammarLength = 0; if (!m_webView->spellCheckClient()) return; WebVector<WebTextCheckingResult> webResults; m_webView->spellCheckClient()->checkTextOfParagraph(text, WebTextCheckingTypeGrammar, &webResults); if (!webResults.size()) return; // Convert a list of WebTextCheckingResults to a list of GrammarDetails. If // the converted vector of GrammarDetails has grammar errors, we set // badGrammarLocation and badGrammarLength to tell WebKit that the input // text has grammar errors. for (size_t i = 0; i < webResults.size(); ++i) { if (webResults[i].decoration == WebTextDecorationTypeGrammar) { GrammarDetail detail; detail.location = webResults[i].location; detail.length = webResults[i].length; detail.userDescription = webResults[i].replacement; details.append(detail); } } if (!details.size()) return; if (badGrammarLocation) *badGrammarLocation = 0; if (badGrammarLength) *badGrammarLength = text.length(); }
static void write_string(WTF::Vector<char>& v, const WebCore::String& str) { unsigned strLen = str.length(); // Only do work if the string has data. if (strLen) { // Determine how much to grow the vector. Use the worst case for utf8 to // avoid reading the string twice. Add sizeof(unsigned) to hold the // string length in utf8. unsigned vectorLen = v.size() + sizeof(unsigned); unsigned length = (strLen << 2) + vectorLen; // Grow the vector. This will change the value of v.size() but we // remember the original size above. v.grow(length); // Grab the position to write to. char* data = v.begin() + vectorLen; // Write the actual string int l = SkUTF16_ToUTF8(str.characters(), strLen, data); LOGV("Writing string %d %.*s", l, l, data); // Go back and write the utf8 length. Subtract sizeof(unsigned) from // data to get the position to write the length. memcpy(data - sizeof(unsigned), (char*)&l, sizeof(unsigned)); // Shrink the internal state of the vector so we match what was // actually written. v.shrink(vectorLen + l); } else v.append((char*)&strLen, sizeof(unsigned)); }
void GLExtras::drawFindOnPage(SkRect& viewport) { WTF::Vector<MatchInfo>* matches = m_findOnPage->matches(); XLOG("drawFindOnPage, matches: %p", matches); if (!matches || !m_findOnPage->isCurrentLocationValid()) return; int count = matches->size(); int current = m_findOnPage->currentMatchIndex(); XLOG("match count: %d", count); if (count < MAX_NUMBER_OF_MATCHES_TO_DRAW) for (int i = 0; i < count; i++) { MatchInfo& info = matches->at(i); const SkRegion& region = info.getLocation(); SkIRect rect = region.getBounds(); if (rect.intersect(viewport.fLeft, viewport.fTop, viewport.fRight, viewport.fBottom)) drawRegion(region, i == current, false, true); #ifdef DEBUG else XLOG("Quick rejecting [%dx%d, %d, %d", rect.fLeft, rect.fTop, rect.width(), rect.height()); #endif // DEBUG } else { MatchInfo& info = matches->at(current); drawRegion(info.getLocation(), true, false, true); } }
void TilesManager::dirtyTexturesVector(WTF::Vector<TileTexture*>& textures) { for (unsigned int i = 0; i < textures.size(); i++) { Tile* currentOwner = static_cast<Tile*>(textures[i]->owner()); if (currentOwner) currentOwner->markAsDirty(); } }
void PepperPluginImpl::updateGeometry(const WebCore::IntRect& window_rect, const WebCore::IntRect& clip_rect, const WTF::Vector<WebCore::IntRect>& cut_outs_rects, bool is_visible){ plugin_rect_ = window_rect; if (!instance_->FlashIsFullscreenOrPending()) { std::vector<IntRect> cut_outs; for (size_t i = 0; i < cut_outs_rects.size(); ++i) cut_outs.push_back(cut_outs_rects[i]); instance_->ViewChanged(plugin_rect_, clip_rect, cut_outs); } }
void TilesManager::discardTexturesVector(unsigned long long sparedDrawCount, WTF::Vector<TileTexture*>& textures, bool deallocateGLTextures) { const unsigned int max = textures.size(); int dealloc = 0; WTF::Vector<int> discardedIndex; for (unsigned int i = 0; i < max; i++) { TextureOwner* owner = textures[i]->owner(); if (!owner || owner->drawCount() < sparedDrawCount) { if (deallocateGLTextures) { // deallocate textures' gl memory textures[i]->discardGLTexture(); discardedIndex.append(i); } else if (owner) { // simply detach textures from owner static_cast<Tile*>(owner)->discardTextures(); } dealloc++; } } bool base = textures == m_textures; // Clean up the vector of TileTextures and reset the max texture count. if (discardedIndex.size()) { android::Mutex::Autolock lock(m_texturesLock); for (int i = discardedIndex.size() - 1; i >= 0; i--) textures.remove(discardedIndex[i]); int remainedTextureNumber = textures.size(); int* countPtr = base ? &m_currentTextureCount : &m_currentLayerTextureCount; if (remainedTextureNumber < *countPtr) { ALOGV("reset currentTextureCount for %s tiles from %d to %d", base ? "base" : "layer", *countPtr, remainedTextureNumber); *countPtr = remainedTextureNumber; } } ALOGV("Discarded %d %s textures (out of %d %s tiles)", dealloc, (deallocateGLTextures ? "gl" : ""), max, base ? "base" : "layer"); }
void MaskNode::OnSelfOrChildStateChange() { m_bChildNeedDraw = true; m_bBoundingDirty = true; // 不需要调用SetBoundingDirty(),因为不需要通知父节点 WTF::Vector<UINode*>* owners = m_pManager->GetEffectsResOwnerNodes(this); if (!owners) return; // 子节点绘图消息被转发到拥有者节点上 for (size_t i = 0; i < owners->size(); ++i) owners->at(i)->SetNeedLayout(); }
void applyAntiAliasedClipPaths(WTF::Vector<SkPath>& paths) { // Anti-aliased clipping: // // Refer to PlatformContextSkia.cpp's applyAntiAliasedClipPaths() for more details if (m_platformGfxCtx && m_platformGfxCtx->mCanvas) m_platformGfxCtx->mCanvas->restore(); SkPaint paint; paint.setXfermodeMode(SkXfermode::kClear_Mode); paint.setAntiAlias(true); paint.setStyle(SkPaint::kFill_Style); if (m_platformGfxCtx && m_platformGfxCtx->mCanvas) { for (size_t i = paths.size() - 1; i < paths.size(); --i) { paths[i].setFillType(SkPath::kInverseWinding_FillType); m_platformGfxCtx->mCanvas->drawPath(paths[i], paint); } m_platformGfxCtx->mCanvas->restore(); } else ASSERT(0); }
jbyteArray WebHistory::Flatten(JNIEnv* env, WTF::Vector<char>& v, WebCore::HistoryItem* item) { if (!item) return NULL; // Reserve a vector of chars with an initial size of HISTORY_MIN_SIZE. v.reserveCapacity(HISTORY_MIN_SIZE); // Write the top-level history item and then write all the children // recursively. LOG_ASSERT(item->bridge(), "Why don't we have a bridge object here?"); write_item(v, item); write_children_recursive(v, item); // Try to create a new java byte array. jbyteArray b = env->NewByteArray(v.size()); if (!b) return NULL; // Write our flattened data to the java array. env->SetByteArrayRegion(b, 0, v.size(), (const jbyte*)v.data()); return b; }
void PlatformContextSkia::applyAntiAliasedClipPaths(WTF::Vector<SkPath>& paths) { // Anti-aliased clipping: // // Skia's clipping is 1-bit only. Consider what would happen if it were 8-bit: // We have a square canvas, filled with white and we declare a circular // clipping path. Then we fill twice with a black rectangle. The fractional // pixels would first get the correct color (white * alpha + black * (1 - // alpha)), but the second fill would apply the alpha to the already // modified color and the result would be too dark. // // This, anti-aliased clipping needs to be performed after the drawing has // been done. In order to do this, we create a new layer of the canvas in // clipPathAntiAliased and store the clipping path. All drawing is done to // the layer's bitmap while it's in effect. When WebKit calls restore() to // undo the clipping, this function is called. // // Here, we walk the list of clipping paths backwards and, for each, we // clear outside of the clipping path. We only need a single extra layer // for any number of clipping paths. // // When we call restore on the SkCanvas, the layer's bitmap is composed // into the layer below and we end up with correct, anti-aliased clipping. SkPaint paint; paint.setXfermodeMode(SkXfermode::kClear_Mode); paint.setAntiAlias(true); paint.setStyle(SkPaint::kFill_Style); for (size_t i = paths.size() - 1; i < paths.size(); --i) { paths[i].setFillType(SkPath::kInverseWinding_FillType); m_canvas->drawPath(paths[i], paint); } m_canvas->restore(); }
void TilesManager::deallocateTexturesVector(unsigned long long sparedDrawCount, WTF::Vector<BaseTileTexture*>& textures) { const unsigned int max = textures.size(); int dealloc = 0; for (unsigned int i = 0; i < max; i++) { TextureOwner* owner = textures[i]->owner(); if (!owner || owner->drawCount() < sparedDrawCount) { textures[i]->discardGLTexture(); dealloc++; } } XLOG("Deallocated %d gl textures (out of %d base tiles and %d layer tiles)", dealloc, max, maxLayer); }
// ReverseBidi is a trimmed-down version of GraphicsContext::drawBidiText() void ReverseBidi(UChar* chars, int len) { using namespace WTF::Unicode; WTF::Vector<UChar> result; result.reserveCapacity(len); TextRun run(chars, len); BidiResolver<TextRunIterator, BidiCharacterRun> bidiResolver; BidiRunList<BidiCharacterRun>& bidiRuns = bidiResolver.runs(); bidiResolver.setStatus(BidiStatus(LeftToRight, LeftToRight, LeftToRight, BidiContext::create(0, LeftToRight, false))); bidiResolver.setPosition(TextRunIterator(&run, 0)); bidiResolver.createBidiRunsForLine(TextRunIterator(&run, len)); if (!bidiRuns.runCount()) return; BidiCharacterRun* bidiRun = bidiRuns.firstRun(); while (bidiRun) { int bidiStart = bidiRun->start(); int bidiStop = bidiRun->stop(); int size = result.size(); int bidiCount = bidiStop - bidiStart; result.append(chars + bidiStart, bidiCount); if (bidiRun->level() % 2) { UChar* start = &result[size]; UChar* end = start + bidiCount; // reverse the order of any RTL substrings while (start < end) { UChar temp = *start; *start++ = *--end; *end = temp; } start = &result[size]; end = start + bidiCount - 1; // if the RTL substring had a surrogate pair, restore its order while (start < end) { UChar trail = *start++; if (!U16_IS_SURROGATE(trail)) continue; start[-1] = *start; // lead *start++ = trail; } } bidiRun = bidiRun->next(); } bidiRuns.deleteRuns(); memcpy(chars, &result[0], len * sizeof(UChar)); }
void TilesManager::paintedSurfacesCleanup(GLWebViewState* state) { // PaintedSurfaces are created by LayerAndroid with a refcount of 1, // and just transferred to new (corresponding) layers when a new layer tree // is received. // PaintedSurface also keep a reference on the Layer it currently has, so // when we unref the tree of layer, those layers with a PaintedSurface will // still be around if we do nothing. // Here, if the surface does not have any associated layer, it means that we // received a new layer tree without a corresponding layer (i.e. a layer // using a texture has been removed by webkit). // In that case, we remove the PaintedSurface from our list, and unref it. // If the surface does have a layer, but the GLWebViewState associated to // that layer is different from the one passed in parameter, it means we can // also remove the surface (and we also remove/unref any layer that surface // has). We do this when we deallocate GLWebViewState (i.e. the webview has // been destroyed) and also when we switch to a page without // composited layers. WTF::Vector<PaintedSurface*> collect; for (unsigned int i = 0; i < m_paintedSurfaces.size(); i++) { PaintedSurface* surface = m_paintedSurfaces[i]; Layer* drawing = surface->drawingLayer(); Layer* painting = surface->paintingLayer(); XLOG("considering PS %p, drawing %p, painting %p", surface, drawing, painting); bool drawingMatchesState = state && drawing && (drawing->state() == state); bool paintingMatchesState = state && painting && (painting->state() == state); if ((!painting && !drawing) || drawingMatchesState || paintingMatchesState) { XLOG("trying to remove PS %p, painting %p, drawing %p, DMS %d, PMS %d", surface, painting, drawing, drawingMatchesState, paintingMatchesState); collect.append(surface); } } for (unsigned int i = 0; i < collect.size(); i++) { PaintedSurface* surface = collect[i]; m_paintedSurfaces.remove(m_paintedSurfaces.find(surface)); SkSafeUnref(surface); } }
void FrameLoaderClientAndroid::dispatchDidFailProvisionalLoad(const ResourceError& error) { ASSERT(m_frame); // Ignore ErrorInterrupted since it is due to a policy interruption. This // is caused by a decision to download the main resource rather than // display it. if (error.errorCode() == InternalErrorInterrupted || error.errorCode() == InternalErrorCancelled) { // If we decided to download the main resource or if the user cancelled // it, make sure we report that the load is done. didFinishLoad(); return; } AssetManager* am = globalAssetManager(); // Check to see if the error code was not generated internally WebCore::PlatformBridge::rawResId id = WebCore::PlatformBridge::NoDomain; if ((error.errorCode() == ErrorFile || error.errorCode() == ErrorFileNotFound) && (!error.localizedDescription().isEmpty())) { id = WebCore::PlatformBridge::LoadError; } String filename = m_webFrame->getRawResourceFilename(id); if (filename.isEmpty()) return; // Grab the error page from the asset manager Asset* a = am->openNonAsset( filename.utf8().data(), Asset::ACCESS_BUFFER); if (!a) return; // Take the failing url and encode html entities so javascript urls are not // executed. CString failingUrl = error.failingURL().utf8(); WTF::Vector<char> url; int len = failingUrl.length(); const char* data = failingUrl.data(); for (int i = 0; i < len; i++) { char c = data[i]; if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9')) url.append(c); else { char buf[16]; int res = sprintf(buf, "&#%d;", c); buf[res] = 0; url.append(buf, res); } } // Replace all occurances of %s with the failing url. String s = UTF8Encoding().decode((const char*)a->getBuffer(false), a->getLength()); // samsung shkim // \frameworks\base\core\res\res\raw-XX\nodomain.html or loaderror.html // These error pages does not have <viewport> tag, it is loaded as low zoom scale if( s.contains( "viewport" ) == false ) s = s.replace( "<head>", "<head> <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0, user-scalable=no\"/>" ); s = s.replace("%s", String(url.data(), url.size())); // Replace all occurances of %e with the error text s = s.replace("%e", error.localizedDescription()); // Create the request and the substitute data and tell the FrameLoader to // load with the replacement data. // use KURL(const char*) as KURL(const String& url) can trigger ASSERT for // invalidate URL string. loadDataIntoFrame(m_frame, KURL(ParsedURLString, data), error.failingURL(), s); // Delete the asset. delete a; }
Value RelationOp::doEvaluate() const { Value lhs( subExpr( 0 )->evaluate() ); Value rhs( subExpr( 1 )->evaluate() ); if (lhs.isNodeset() || rhs.isNodeset()) { // If both are nodesets, or one is a string our // comparisons are based on strings. if ((lhs.isNodeset() && rhs.isNodeset()) || (lhs.isString() || rhs.isString())) { WTF::Vector<DOM::DOMString> leftStrings; WTF::Vector<DOM::DOMString> rightStrings; stringify(lhs, &leftStrings); stringify(rhs, &rightStrings); for (unsigned pl = 0; pl < leftStrings.size(); ++pl) { for (unsigned pr = 0; pr < rightStrings.size(); ++pr) { if (compareStrings(leftStrings[pl], rightStrings[pr])) return Value(true); } // pr } // pl return Value(false); } // If one is a number, we do a number-based comparison if (lhs.isNumber() || rhs.isNumber()) { WTF::Vector<double> leftNums; WTF::Vector<double> rightNums; numify(lhs, &leftNums); numify(rhs, &rightNums); for (unsigned pl = 0; pl < leftNums.size(); ++pl) { for (unsigned pr = 0; pr < rightNums.size(); ++pr) { if (compareNumbers(leftNums[pl], rightNums[pr])) return Value(true); } // pr } // pl return Value(false); } // Has to be a boolean-based comparison. // These ones are simpler, since we just convert the nodeset to a bool assert(lhs.isBoolean() || rhs.isBoolean()); if (lhs.isNodeset()) lhs = Value(lhs.toBoolean()); else rhs = Value(rhs.toBoolean()); } // nodeset comparisons if (opCode == OP_EQ || opCode == OP_NE) { bool equal; if ( lhs.isBoolean() || rhs.isBoolean() ) { equal = ( lhs.toBoolean() == rhs.toBoolean() ); } else if ( lhs.isNumber() || rhs.isNumber() ) { equal = ( lhs.toNumber() == rhs.toNumber() ); } else { equal = ( lhs.toString() == rhs.toString() ); } if ( opCode == OP_EQ ) return Value( equal ); else return Value( !equal ); } // For other ops, we always convert to numbers double leftVal = lhs.toNumber(), rightVal = rhs.toNumber(); return Value(compareNumbers(leftVal, rightVal)); }
TileTexture* TilesManager::getAvailableTexture(Tile* owner) { android::Mutex::Autolock lock(m_texturesLock); WTF::Vector<TileTexture*>* availableTexturePool; if (owner->isLayerTile()) availableTexturePool = &m_availableTilesTextures; else availableTexturePool = &m_availableTextures; // Sanity check that the tile does not already own a texture if (owner->backTexture() && owner->backTexture()->owner() == owner) { int removeIndex = availableTexturePool->find(owner->backTexture()); // TODO: investigate why texture isn't found if (removeIndex >= 0) availableTexturePool->remove(removeIndex); return owner->backTexture(); } // The heuristic for selecting a texture is as follows: // 1. Skip textures currently being painted, they can't be painted while // busy anyway // 2. If a tile isn't owned, break with that one // 3. Don't let tiles acquire their front textures // 4. Otherwise, use the least recently prepared tile, but ignoring tiles // drawn in the last frame to avoid flickering TileTexture* farthestTexture = 0; unsigned long long oldestDrawCount = getDrawGLCount() - 1; const unsigned int max = availableTexturePool->size(); for (unsigned int i = 0; i < max; i++) { TileTexture* texture = (*availableTexturePool)[i]; Tile* currentOwner = static_cast<Tile*>(texture->owner()); if (!currentOwner) { // unused texture! take it! farthestTexture = texture; break; } if (currentOwner == owner) { // Don't let a tile acquire its own front texture, as the // acquisition logic doesn't handle that continue; } unsigned long long textureDrawCount = currentOwner->drawCount(); if (oldestDrawCount > textureDrawCount) { farthestTexture = texture; oldestDrawCount = textureDrawCount; } } if (farthestTexture) { Tile* previousOwner = static_cast<Tile*>(farthestTexture->owner()); if (farthestTexture->acquire(owner)) { if (previousOwner) { previousOwner->removeTexture(farthestTexture); ALOGV("%s texture %p stolen from tile %d, %d for %d, %d, drawCount was %llu (now %llu)", owner->isLayerTile() ? "LAYER" : "BASE", farthestTexture, previousOwner->x(), previousOwner->y(), owner->x(), owner->y(), oldestDrawCount, getDrawGLCount()); } availableTexturePool->remove(availableTexturePool->find(farthestTexture)); return farthestTexture; } } else { if (owner->isLayerTile()) { // couldn't find a tile for a layer, layers shouldn't request redraw // TODO: once we do layer prefetching, don't set this for those // tiles m_layerTexturesRemain = false; } } ALOGV("Couldn't find an available texture for %s tile %x (%d, %d) out of %d available", owner->isLayerTile() ? "LAYER" : "BASE", owner, owner->x(), owner->y(), max); #ifdef DEBUG printTextures(); #endif // DEBUG return 0; }
BaseTileTexture* TilesManager::getAvailableTexture(BaseTile* owner) { android::Mutex::Autolock lock(m_texturesLock); // Sanity check that the tile does not already own a texture if (owner->backTexture() && owner->backTexture()->owner() == owner) { XLOG("same owner (%d, %d), getAvailableBackTexture(%x) => texture %x", owner->x(), owner->y(), owner, owner->backTexture()); if (owner->isLayerTile()) m_availableTilesTextures.remove(m_availableTilesTextures.find(owner->backTexture())); else m_availableTextures.remove(m_availableTextures.find(owner->backTexture())); return owner->backTexture(); } WTF::Vector<BaseTileTexture*>* availableTexturePool; if (owner->isLayerTile()) { availableTexturePool = &m_availableTilesTextures; } else { availableTexturePool = &m_availableTextures; } // The heuristic for selecting a texture is as follows: // 1. Skip textures currently being painted, they can't be painted while // busy anyway // 2. If a tile isn't owned, break with that one // 3. Don't let tiles acquire their front textures // 4. If we find a tile in the same page with a different scale, // it's old and not visible. Break with that one // 5. Otherwise, use the least recently prepared tile, but ignoring tiles // drawn in the last frame to avoid flickering BaseTileTexture* farthestTexture = 0; unsigned long long oldestDrawCount = getDrawGLCount() - 1; const unsigned int max = availableTexturePool->size(); for (unsigned int i = 0; i < max; i++) { BaseTileTexture* texture = (*availableTexturePool)[i]; BaseTile* currentOwner = static_cast<BaseTile*>(texture->owner()); if (texture->busy()) { // don't bother, since the acquire() will likely fail continue; } if (!currentOwner) { // unused texture! take it! farthestTexture = texture; break; } if (currentOwner == owner) { // Don't let a tile acquire its own front texture, as the // acquisition logic doesn't handle that continue; } if (currentOwner->painter() == owner->painter() && texture->scale() != owner->scale()) { // if we render the back page with one scale, then another while // still zooming, we recycle the tiles with the old scale instead of // taking ones from the front page farthestTexture = texture; break; } unsigned long long textureDrawCount = currentOwner->drawCount(); if (oldestDrawCount > textureDrawCount) { farthestTexture = texture; oldestDrawCount = textureDrawCount; } } if (farthestTexture) { BaseTile* previousOwner = static_cast<BaseTile*>(farthestTexture->owner()); if (farthestTexture->acquire(owner)) { if (previousOwner) { previousOwner->removeTexture(farthestTexture); XLOG("%s texture %p stolen from tile %d, %d for %d, %d, drawCount was %llu (now %llu)", owner->isLayerTile() ? "LAYER" : "BASE", farthestTexture, previousOwner->x(), previousOwner->y(), owner->x(), owner->y(), oldestDrawCount, getDrawGLCount()); } availableTexturePool->remove(availableTexturePool->find(farthestTexture)); return farthestTexture; } } else { if (owner->isLayerTile()) { // couldn't find a tile for a layer, layers shouldn't request redraw // TODO: once we do layer prefetching, don't set this for those // tiles m_layerTexturesRemain = false; } } XLOG("Couldn't find an available texture for %s tile %x (%d, %d) out of %d available", owner->isLayerTile() ? "LAYER" : "BASE", owner, owner->x(), owner->y(), max); #ifdef DEBUG printTextures(); #endif // DEBUG return 0; }