TEST(RawResourceTest, RevalidationSucceededForResourceWithoutBody) { ResourcePtr<Resource> resource = new RawResource(ResourceRequest("data:text/html,"), Resource::Raw); ResourceResponse response; response.setHTTPStatusCode(200); resource->responseReceived(response, nullptr); resource->finish(); memoryCache()->add(resource.get()); // Simulate a successful revalidation. resource->setRevalidatingRequest(ResourceRequest("data:text/html,")); OwnPtr<DummyClient> client = adoptPtr(new DummyClient); resource->addClient(client.get()); ResourceResponse revalidatingResponse; revalidatingResponse.setHTTPStatusCode(304); resource->responseReceived(revalidatingResponse, nullptr); EXPECT_FALSE(resource->isCacheValidator()); EXPECT_EQ(200, resource->response().httpStatusCode()); EXPECT_EQ(nullptr, resource->resourceBuffer()); EXPECT_EQ(memoryCache()->resourceForURL(KURL(ParsedURLString, "data:text/html,")), resource.get()); memoryCache()->remove(resource.get()); resource->removeClient(client.get()); EXPECT_FALSE(resource->hasClients()); EXPECT_FALSE(client->called()); EXPECT_EQ(0u, client->data().size()); }
// Verifies that ImageBitmaps constructed from HTMLImageElements hold a reference to the original Image if the HTMLImageElement src is changed. TEST_F(ImageBitmapTest, ImageBitmapSourceChanged) { RefPtrWillBeRawPtr<HTMLImageElement> image = HTMLImageElement::create(*Document::create().get()); ResourcePtr<ImageResource> originalImageResource = new ImageResource( StaticBitmapImage::create(m_image).get()); image->setImageResource(originalImageResource.get()); RefPtrWillBeRawPtr<ImageBitmap> imageBitmap = ImageBitmap::create(image.get(), IntRect(0, 0, m_image->width(), m_image->height())); ASSERT_EQ(imageBitmap->bitmapImage().get(), originalImageResource->image()); ResourcePtr<ImageResource> newImageResource = new ImageResource( StaticBitmapImage::create(m_image2).get()); image->setImageResource(newImageResource.get()); // The ImageBitmap should contain the same data as the original cached image but should no longer hold a reference. { ASSERT_NE(imageBitmap->bitmapImage().get(), originalImageResource->image()); RefPtr<SkImage> image1 = imageBitmap->bitmapImage()->imageForCurrentFrame(); ASSERT_NE(image1, nullptr); RefPtr<SkImage> image2 = originalImageResource->image()->imageForCurrentFrame(); ASSERT_NE(image2, nullptr); ASSERT_EQ(image1, image2); } { ASSERT_NE(imageBitmap->bitmapImage().get(), newImageResource->image()); RefPtr<SkImage> image1 = imageBitmap->bitmapImage()->imageForCurrentFrame(); ASSERT_NE(image1, nullptr); RefPtr<SkImage> image2 = newImageResource->image()->imageForCurrentFrame(); ASSERT_NE(image2, nullptr); ASSERT_NE(image1, image2); } }
ResourcePtr<Resource> ResourceFetcher::createResourceForRevalidation(const FetchRequest& request, Resource* resource) { ASSERT(resource); ASSERT(memoryCache()->contains(resource)); ASSERT(resource->isLoaded()); ASSERT(resource->canUseCacheValidator()); ASSERT(!resource->resourceToRevalidate()); ResourceRequest revalidatingRequest(resource->resourceRequest()); revalidatingRequest.clearHTTPReferrer(); addAdditionalRequestHeaders(revalidatingRequest, resource->type()); const AtomicString& lastModified = resource->response().httpHeaderField("Last-Modified"); const AtomicString& eTag = resource->response().httpHeaderField("ETag"); if (!lastModified.isEmpty() || !eTag.isEmpty()) { ASSERT(context().cachePolicy(document()) != CachePolicyReload); if (context().cachePolicy(document()) == CachePolicyRevalidate) revalidatingRequest.setHTTPHeaderField("Cache-Control", "max-age=0"); } if (!lastModified.isEmpty()) revalidatingRequest.setHTTPHeaderField("If-Modified-Since", lastModified); if (!eTag.isEmpty()) revalidatingRequest.setHTTPHeaderField("If-None-Match", eTag); ResourcePtr<Resource> newResource = createResource(resource->type(), revalidatingRequest, resource->encoding()); WTF_LOG(ResourceLoading, "Resource %p created to revalidate %p", newResource.get(), resource); newResource->setResourceToRevalidate(resource); memoryCache()->remove(resource); memoryCache()->add(newResource.get()); return newResource; }
TEST(ImageResourceTest, CancelOnDetach) { KURL testURL(ParsedURLString, "http://www.test.com/cancelTest.html"); URLTestHelpers::registerMockedURLLoad(testURL, "cancelTest.html", "text/html"); ResourceFetcher* fetcher = ResourceFetcher::create(nullptr); // Emulate starting a real load. ResourcePtr<ImageResource> cachedImage = new ImageResource(ResourceRequest(testURL), nullptr); cachedImage->setIdentifier(createUniqueIdentifier()); cachedImage->load(fetcher, ResourceLoaderOptions()); memoryCache()->add(cachedImage.get()); MockImageResourceClient client(cachedImage); EXPECT_EQ(Resource::Pending, cachedImage->status()); // The load should still be alive, but a timer should be started to cancel the load inside removeClient(). client.removeAsClient(); EXPECT_EQ(Resource::Pending, cachedImage->status()); EXPECT_NE(reinterpret_cast<Resource*>(0), memoryCache()->resourceForURL(testURL)); // Trigger the cancel timer, ensure the load was cancelled and the resource was evicted from the cache. blink::testing::runPendingTasks(); EXPECT_EQ(Resource::LoadError, cachedImage->status()); EXPECT_EQ(reinterpret_cast<Resource*>(0), memoryCache()->resourceForURL(testURL)); Platform::current()->unitTestSupport()->unregisterMockedURL(testURL); }
TEST_F(MemoryCacheTest, VeryLargeResourceAccounting) { const size_t sizeMax = ~static_cast<size_t>(0); const size_t totalCapacity = sizeMax / 4; const size_t minDeadCapacity = sizeMax / 16; const size_t maxDeadCapacity = sizeMax / 8; const size_t resourceSize1 = sizeMax / 16; const size_t resourceSize2 = sizeMax / 20; memoryCache()->setCapacities(minDeadCapacity, maxDeadCapacity, totalCapacity); ResourcePtr<FakeResource> cachedResource = new FakeResource(ResourceRequest("http://test/resource"), Resource::Raw); cachedResource->fakeEncodedSize(resourceSize1); ASSERT_EQ(0u, memoryCache()->deadSize()); ASSERT_EQ(0u, memoryCache()->liveSize()); memoryCache()->add(cachedResource.get()); ASSERT_EQ(cachedResource->size(), memoryCache()->deadSize()); ASSERT_EQ(0u, memoryCache()->liveSize()); MockImageResourceClient client(cachedResource); ASSERT_EQ(0u, memoryCache()->deadSize()); ASSERT_EQ(cachedResource->size(), memoryCache()->liveSize()); cachedResource->fakeEncodedSize(resourceSize2); ASSERT_EQ(0u, memoryCache()->deadSize()); ASSERT_EQ(cachedResource->size(), memoryCache()->liveSize()); }
TEST_F(CachingCorrectnessTest, FreshWithStaleRedirect) { KURL redirectUrl(ParsedURLString, kResourceURL); const char redirectTargetUrlString[] = "http://redirect-target.com"; KURL redirectTargetUrl(ParsedURLString, redirectTargetUrlString); ResourcePtr<Resource> firstResource = new Resource(ResourceRequest(redirectUrl), Resource::Raw); ResourceResponse stale301Response; stale301Response.setURL(redirectUrl); stale301Response.setHTTPStatusCode(301); stale301Response.setHTTPHeaderField(HTTPNames::Date, kOriginalRequestDateAsString); stale301Response.setHTTPHeaderField(HTTPNames::Location, redirectTargetUrlString); // Add the redirect to our request. ResourceRequest redirectRequest = ResourceRequest(redirectTargetUrl); firstResource->willFollowRedirect(redirectRequest, stale301Response); // Add the final response to our request. ResourceResponse fresh200Response; fresh200Response.setURL(redirectTargetUrl); fresh200Response.setHTTPStatusCode(200); fresh200Response.setHTTPHeaderField(HTTPNames::Date, kOriginalRequestDateAsString); fresh200Response.setHTTPHeaderField(HTTPNames::Expires, kOneDayAfterOriginalRequest); firstResource->setResponse(fresh200Response); memoryCache()->add(firstResource.get()); advanceClock(500.); ResourcePtr<Resource> fetched = fetch(); EXPECT_NE(firstResource, fetched); }
// Verifies that dead resources that exceed dead resource capacity are evicted // from cache when pruning. TEST_F(MemoryCacheTest, DeadResourceEviction) { const unsigned totalCapacity = 1000000; const unsigned minDeadCapacity = 0; const unsigned maxDeadCapacity = 0; memoryCache()->setCapacities(minDeadCapacity, maxDeadCapacity, totalCapacity); ResourcePtr<Resource> cachedResource = new Resource(ResourceRequest(""), Resource::Raw); const char data[5] = "abcd"; cachedResource->appendData(data, 3); // The resource size has to be nonzero for this test to be meaningful, but // we do not rely on it having any particular value. ASSERT_GT(cachedResource->size(), 0u); ASSERT_EQ(0u, memoryCache()->deadSize()); ASSERT_EQ(0u, memoryCache()->liveSize()); memoryCache()->add(cachedResource.get()); ASSERT_EQ(cachedResource->size(), memoryCache()->deadSize()); ASSERT_EQ(0u, memoryCache()->liveSize()); memoryCache()->prune(); ASSERT_EQ(0u, memoryCache()->deadSize()); ASSERT_EQ(0u, memoryCache()->liveSize()); }
TEST_F(ResourceFetcherTest, StartLoadAfterFrameDetach) { KURL secureURL(ParsedURLString, "https://secureorigin.test/image.png"); // Try to request a url. The request should fail, no resource should be returned, // and no resource should be present in the cache. RefPtrWillBeRawPtr<ResourceFetcher> fetcher = ResourceFetcher::create(FetchContext::create()); FetchRequest fetchRequest = FetchRequest(ResourceRequest(secureURL), FetchInitiatorInfo()); ResourcePtr<ImageResource> image = fetcher->fetchImage(fetchRequest); EXPECT_EQ(image.get(), static_cast<ImageResource*>(0)); EXPECT_EQ(memoryCache()->resourceForURL(secureURL), static_cast<Resource*>(0)); }
ResourcePtr<Resource> ResourceFetcher::createResourceForLoading(Resource::Type type, FetchRequest& request, const String& charset) { ASSERT(!memoryCache()->resourceForURL(request.resourceRequest().url())); WTF_LOG(ResourceLoading, "Loading Resource for '%s'.", request.resourceRequest().url().elidedString().latin1().data()); addAdditionalRequestHeaders(request.mutableResourceRequest(), type); ResourcePtr<Resource> resource = createResource(type, request.resourceRequest(), charset); memoryCache()->add(resource.get()); return resource; }
void ScriptRunner::queueScriptForExecution(ScriptLoader* scriptLoader, ResourcePtr<ScriptResource> resource, ExecutionType executionType) { ASSERT(scriptLoader); ASSERT(resource.get()); Element* element = scriptLoader->element(); ASSERT(element); ASSERT(element->inDocument()); m_document->incrementLoadEventDelayCount(); switch (executionType) { case ASYNC_EXECUTION: m_pendingAsyncScripts.add(scriptLoader, PendingScript(element, resource.get())); break; case IN_ORDER_EXECUTION: m_scriptsToExecuteInOrder.append(PendingScript(element, resource.get())); break; } }
// Verifies that ImageBitmaps constructed from HTMLImageElements hold a reference to the original Image if the HTMLImageElement src is changed. TEST_F(ImageBitmapTest, ImageBitmapSourceChanged) { RefPtr<HTMLImageElement> image = HTMLImageElement::create(*Document::create().get()); ResourcePtr<ImageResource> originalImageResource = new ImageResource(BitmapImage::create(NativeImageSkia::create(m_bitmap)).get()); image->setImageResource(originalImageResource.get()); RefPtrWillBeRawPtr<ImageBitmap> imageBitmap = ImageBitmap::create(image.get(), IntRect(0, 0, m_bitmap.width(), m_bitmap.height())); ASSERT_EQ(imageBitmap->bitmapImage().get(), originalImageResource->image()); ResourcePtr<ImageResource> newImageResource = new ImageResource(BitmapImage::create(NativeImageSkia::create(m_bitmap2)).get()); image->setImageResource(newImageResource.get()); // The ImageBitmap should contain the same data as the original cached image but should no longer hold a reference. ASSERT_NE(imageBitmap->bitmapImage().get(), originalImageResource->image()); ASSERT_EQ(imageBitmap->bitmapImage()->nativeImageForCurrentFrame()->bitmap().pixelRef()->pixels(), originalImageResource->image()->nativeImageForCurrentFrame()->bitmap().pixelRef()->pixels()); ASSERT_NE(imageBitmap->bitmapImage().get(), newImageResource->image()); ASSERT_NE(imageBitmap->bitmapImage()->nativeImageForCurrentFrame()->bitmap().pixelRef()->pixels(), newImageResource->image()->nativeImageForCurrentFrame()->bitmap().pixelRef()->pixels()); }
// Verifies that CachedResources are evicted from the decode cache // according to their DecodeCachePriority. static void TestDecodeCacheOrder(const ResourcePtr<Resource>& cachedImageLowPriority, const ResourcePtr<Resource>& cachedImageHighPriority) { memoryCache()->setDelayBeforeLiveDecodedPrune(0); memoryCache()->setMaxPruneDeferralDelay(0); MockImageResourceClient clientLowPriority(cachedImageLowPriority); MockImageResourceClient clientHighPriority(cachedImageHighPriority); const char data[5] = "abcd"; cachedImageLowPriority->appendData(data, 1u); cachedImageHighPriority->appendData(data, 4u); const unsigned lowPrioritySize = cachedImageLowPriority->size(); const unsigned highPrioritySize = cachedImageHighPriority->size(); const unsigned lowPriorityMockDecodeSize = cachedImageLowPriority->decodedSize(); const unsigned highPriorityMockDecodeSize = cachedImageHighPriority->decodedSize(); const unsigned totalSize = lowPrioritySize + highPrioritySize; // Verify that the sizes are different to ensure that we can test eviction order. ASSERT_GT(lowPrioritySize, 0u); ASSERT_NE(lowPrioritySize, highPrioritySize); ASSERT_GT(lowPriorityMockDecodeSize, 0u); ASSERT_NE(lowPriorityMockDecodeSize, highPriorityMockDecodeSize); ASSERT_EQ(memoryCache()->deadSize(), 0u); ASSERT_EQ(memoryCache()->liveSize(), 0u); // Add the items. The item added first would normally be evicted first. memoryCache()->add(cachedImageHighPriority.get()); ASSERT_EQ(memoryCache()->deadSize(), 0u); ASSERT_EQ(memoryCache()->liveSize(), highPrioritySize); memoryCache()->add(cachedImageLowPriority.get()); ASSERT_EQ(memoryCache()->deadSize(), 0u); ASSERT_EQ(memoryCache()->liveSize(), highPrioritySize + lowPrioritySize); // Insert all items in the decoded items list with the same priority memoryCache()->updateDecodedResource(cachedImageHighPriority.get(), UpdateForPropertyChange); memoryCache()->updateDecodedResource(cachedImageLowPriority.get(), UpdateForPropertyChange); ASSERT_EQ(memoryCache()->deadSize(), 0u); ASSERT_EQ(memoryCache()->liveSize(), totalSize); // Now we will assign their priority and make sure they are moved to the correct buckets. memoryCache()->updateDecodedResource(cachedImageLowPriority.get(), UpdateForPropertyChange, MemoryCacheLiveResourcePriorityLow); memoryCache()->updateDecodedResource(cachedImageHighPriority.get(), UpdateForPropertyChange, MemoryCacheLiveResourcePriorityHigh); // Should first prune the LowPriority item. memoryCache()->setCapacities(memoryCache()->minDeadCapacity(), memoryCache()->liveSize() - 10, memoryCache()->liveSize() - 10); memoryCache()->prune(); ASSERT_EQ(memoryCache()->deadSize(), 0u); ASSERT_EQ(memoryCache()->liveSize(), totalSize - lowPriorityMockDecodeSize); // Should prune the HighPriority item. memoryCache()->setCapacities(memoryCache()->minDeadCapacity(), memoryCache()->liveSize() - 10, memoryCache()->liveSize() - 10); memoryCache()->prune(); ASSERT_EQ(memoryCache()->deadSize(), 0u); ASSERT_EQ(memoryCache()->liveSize(), totalSize - lowPriorityMockDecodeSize - highPriorityMockDecodeSize); }
TEST(RawResourceTest, AddClientDuringCallback) { ResourcePtr<Resource> raw = new RawResource(ResourceRequest("data:text/html,"), Resource::Raw); raw->setLoading(false); // Create a non-null response. ResourceResponse response = raw->response(); response.setURL(KURL(ParsedURLString, "http://600.613/")); raw->setResponse(response); EXPECT_FALSE(raw->response().isNull()); OwnPtr<DummyClient> dummyClient = adoptPtr(new DummyClient()); OwnPtr<AddingClient> addingClient = adoptPtr(new AddingClient(dummyClient.get(), raw.get())); raw->addClient(addingClient.get()); testing::runPendingTasks(); raw->removeClient(addingClient.get()); EXPECT_FALSE(dummyClient->called()); EXPECT_FALSE(raw->hasClients()); }
void onDisplay() { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glMatrixMode(GL_PROJECTION); glLoadIdentity(); glMultMatrixf(&c.getProjectionMatrix()[0][0]); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glMultMatrixf(&c.getViewMatrix()[0][0]); atm.Update(c); //glClearColor(97.0/255.0, 140.0/255.0, 185.0/255.0, 1.0); glPushMatrix(); s.DrawBackdrop(); glPopMatrix(); static_cast<Texture*>(texture.get())->bind(0); Renderer::instance().render(rop); //static_cast<Texture*>(texture.get())->unbind(); glutSwapBuffers(); }
// Verifies that cached resources are evicted immediately after release when // the total dead resource size is more than double the dead resource capacity. static void TestClientRemoval(const ResourcePtr<Resource>& resource1, const ResourcePtr<Resource>& resource2) { const char data[6] = "abcde"; MockImageResourceClient client1(resource1); resource1->appendData(data, 4u); MockImageResourceClient client2(resource2); resource2->appendData(data, 4u); const unsigned minDeadCapacity = 0; const unsigned maxDeadCapacity = ((resource1->size() + resource2->size()) / 2) - 1; const unsigned totalCapacity = maxDeadCapacity; memoryCache()->setCapacities(minDeadCapacity, maxDeadCapacity, totalCapacity); memoryCache()->add(resource1.get()); memoryCache()->add(resource2.get()); // Call prune. There is nothing to prune, but this will initialize // the prune timestamp, allowing future prunes to be deferred. memoryCache()->prune(); ASSERT_GT(resource1->decodedSize(), 0u); ASSERT_GT(resource2->decodedSize(), 0u); ASSERT_EQ(memoryCache()->deadSize(), 0u); ASSERT_EQ(memoryCache()->liveSize(), resource1->size() + resource2->size()); // Removing the client from resource1 should result in all resources // remaining in cache since the prune is deferred. client1.removeAsClient(); ASSERT_GT(resource1->decodedSize(), 0u); ASSERT_GT(resource2->decodedSize(), 0u); ASSERT_EQ(memoryCache()->deadSize(), resource1->size()); ASSERT_EQ(memoryCache()->liveSize(), resource2->size()); ASSERT_TRUE(memoryCache()->contains(resource1.get())); ASSERT_TRUE(memoryCache()->contains(resource2.get())); // Removing the client from resource2 should result in immediate // eviction of resource2 because we are over the prune deferral limit. client2.removeAsClient(); ASSERT_GT(resource1->decodedSize(), 0u); ASSERT_GT(resource2->decodedSize(), 0u); ASSERT_EQ(memoryCache()->deadSize(), resource1->size()); ASSERT_EQ(memoryCache()->liveSize(), 0u); ASSERT_TRUE(memoryCache()->contains(resource1.get())); ASSERT_FALSE(memoryCache()->contains(resource2.get())); }
TEST(RawResourceTest, RevalidationSucceeded) { // Create two RawResources and set one to revalidate the other. RawResource* oldResourcePointer = new RawResource(ResourceRequest("data:text/html,"), Resource::Raw); RawResource* newResourcePointer = new RawResource(ResourceRequest("data:text/html,"), Resource::Raw); newResourcePointer->setResourceToRevalidate(oldResourcePointer); ResourcePtr<Resource> oldResource = oldResourcePointer; ResourcePtr<Resource> newResource = newResourcePointer; memoryCache()->add(oldResource.get()); memoryCache()->remove(oldResource.get()); memoryCache()->add(newResource.get()); // Simulate a successful revalidation. // The revalidated resource (oldResource) should now be in the cache, newResource // should have been sliently switched to point to the revalidated resource, and // we shouldn't hit any ASSERTs. ResourceResponse response; response.setHTTPStatusCode(304); newResource->responseReceived(response, nullptr); EXPECT_EQ(memoryCache()->resourceForURL(KURL(ParsedURLString, "data:text/html,")), oldResource.get()); EXPECT_EQ(oldResource.get(), newResource.get()); EXPECT_NE(newResource.get(), newResourcePointer); memoryCache()->remove(newResource.get()); }
//----------------------------------------------------------------------- void ResourceManager::addImpl( ResourcePtr& res ) { OGRE_LOCK_AUTO_MUTEX std::pair<ResourceMap::iterator, bool> result; if(ResourceGroupManager::getSingleton().isResourceGroupInGlobalPool(res->getGroup())) { result = mResources.insert( ResourceMap::value_type( res->getName(), res ) ); } else { ResourceWithGroupMap::iterator itGroup = mResourcesWithGroup.find(res->getGroup()); // we will create the group if it doesn't exists in our list if( itGroup == mResourcesWithGroup.end()) { ResourceMap dummy; mResourcesWithGroup.insert( ResourceWithGroupMap::value_type( res->getGroup(), dummy ) ); itGroup = mResourcesWithGroup.find(res->getGroup()); } result = itGroup->second.insert( ResourceMap::value_type( res->getName(), res ) ); } if (!result.second) { // Attempt to resolve the collision if(ResourceGroupManager::getSingleton().getLoadingListener()) { if(ResourceGroupManager::getSingleton().getLoadingListener()->resourceCollision(res.get(), this)) { // Try to do the addition again, no seconds attempts to resolve collisions are allowed std::pair<ResourceMap::iterator, bool> insertResult; if(ResourceGroupManager::getSingleton().isResourceGroupInGlobalPool(res->getGroup())) { insertResult = mResources.insert( ResourceMap::value_type( res->getName(), res ) ); } else { ResourceWithGroupMap::iterator itGroup = mResourcesWithGroup.find(res->getGroup()); insertResult = itGroup->second.insert( ResourceMap::value_type( res->getName(), res ) ); } if (!insertResult.second) { OGRE_EXCEPT(Exception::ERR_DUPLICATE_ITEM, "Resource with the name " + res->getName() + " already exists.", "ResourceManager::add"); } std::pair<ResourceHandleMap::iterator, bool> resultHandle = mResourcesByHandle.insert( ResourceHandleMap::value_type( res->getHandle(), res ) ); if (!resultHandle.second) { OGRE_EXCEPT(Exception::ERR_DUPLICATE_ITEM, "Resource with the handle " + StringConverter::toString((long) (res->getHandle())) + " already exists.", "ResourceManager::add"); } } } } else { // Insert the handle std::pair<ResourceHandleMap::iterator, bool> resultHandle = mResourcesByHandle.insert( ResourceHandleMap::value_type( res->getHandle(), res ) ); if (!resultHandle.second) { OGRE_EXCEPT(Exception::ERR_DUPLICATE_ITEM, "Resource with the handle " + StringConverter::toString((long) (res->getHandle())) + " already exists.", "ResourceManager::add"); } } }
// Verifies that HTMLImageElements are given an elevated CacheLiveResourcePriority when used to construct an ImageBitmap. // ImageBitmaps that have crop rects outside of the bounds of the HTMLImageElement do not have elevated CacheLiveResourcePriority. TEST_F(ImageBitmapTest, ImageBitmapLiveResourcePriority) { RefPtrWillBePersistent<HTMLImageElement> imageNoCrop = HTMLImageElement::create(*Document::create().get()); ResourcePtr<ImageResource> cachedImageNoCrop = new ImageResource(ResourceRequest("http://foo.com/1"), StaticBitmapImage::create(m_image).get()); imageNoCrop->setImageResource(cachedImageNoCrop.get()); RefPtrWillBePersistent<HTMLImageElement> imageInteriorCrop = HTMLImageElement::create(*Document::create().get()); ResourcePtr<ImageResource> cachedImageInteriorCrop = new ImageResource(ResourceRequest("http://foo.com/2"), StaticBitmapImage::create(m_image).get()); imageInteriorCrop->setImageResource(cachedImageInteriorCrop.get()); RefPtrWillBePersistent<HTMLImageElement> imageExteriorCrop = HTMLImageElement::create(*Document::create().get()); ResourcePtr<ImageResource> cachedImageExteriorCrop = new ImageResource(ResourceRequest("http://foo.com/3"), StaticBitmapImage::create(m_image).get()); imageExteriorCrop->setImageResource(cachedImageExteriorCrop.get()); RefPtrWillBePersistent<HTMLImageElement> imageOutsideCrop = HTMLImageElement::create(*Document::create().get()); ResourcePtr<ImageResource> cachedImageOutsideCrop = new ImageResource(ResourceRequest("http://foo.com/4"), StaticBitmapImage::create(m_image).get()); imageOutsideCrop->setImageResource(cachedImageOutsideCrop.get()); MockImageResourceClient mockClient1(cachedImageNoCrop); MockImageResourceClient mockClient2(cachedImageInteriorCrop); MockImageResourceClient mockClient3(cachedImageExteriorCrop); MockImageResourceClient mockClient4(cachedImageOutsideCrop); memoryCache()->add(cachedImageNoCrop.get()); memoryCache()->add(cachedImageInteriorCrop.get()); memoryCache()->add(cachedImageExteriorCrop.get()); memoryCache()->add(cachedImageOutsideCrop.get()); memoryCache()->updateDecodedResource(cachedImageNoCrop.get(), UpdateForPropertyChange); memoryCache()->updateDecodedResource(cachedImageInteriorCrop.get(), UpdateForPropertyChange); memoryCache()->updateDecodedResource(cachedImageExteriorCrop.get(), UpdateForPropertyChange); memoryCache()->updateDecodedResource(cachedImageOutsideCrop.get(), UpdateForPropertyChange); // HTMLImageElements should default to CacheLiveResourcePriorityLow. ASSERT_EQ(memoryCache()->priority(imageNoCrop->cachedImage()), MemoryCacheLiveResourcePriorityLow); ASSERT_EQ(memoryCache()->priority(imageInteriorCrop->cachedImage()), MemoryCacheLiveResourcePriorityLow); ASSERT_EQ(memoryCache()->priority(imageExteriorCrop->cachedImage()), MemoryCacheLiveResourcePriorityLow); ASSERT_EQ(memoryCache()->priority(imageOutsideCrop->cachedImage()), MemoryCacheLiveResourcePriorityLow); RefPtrWillBePersistent<ImageBitmap> imageBitmapInteriorCrop = ImageBitmap::create(imageInteriorCrop.get(), IntRect(m_image->width() / 2, m_image->height() / 2, m_image->width(), m_image->height())); { RefPtrWillBePersistent<ImageBitmap> imageBitmapNoCrop = ImageBitmap::create(imageNoCrop.get(), IntRect(0, 0, m_image->width(), m_image->height())); RefPtrWillBePersistent<ImageBitmap> imageBitmapInteriorCrop2 = ImageBitmap::create(imageInteriorCrop.get(), IntRect(m_image->width() / 2, m_image->height() / 2, m_image->width(), m_image->height())); RefPtrWillBePersistent<ImageBitmap> imageBitmapExteriorCrop = ImageBitmap::create(imageExteriorCrop.get(), IntRect(-m_image->width() / 2, -m_image->height() / 2, m_image->width(), m_image->height())); RefPtrWillBePersistent<ImageBitmap> imageBitmapOutsideCrop = ImageBitmap::create(imageOutsideCrop.get(), IntRect(-m_image->width(), -m_image->height(), m_image->width(), m_image->height())); // Images are not referenced by ImageBitmap anymore, so always CacheLiveResourcePriorityLow ASSERT_EQ(memoryCache()->priority(imageNoCrop->cachedImage()), MemoryCacheLiveResourcePriorityLow); ASSERT_EQ(memoryCache()->priority(imageInteriorCrop->cachedImage()), MemoryCacheLiveResourcePriorityLow); ASSERT_EQ(memoryCache()->priority(imageExteriorCrop->cachedImage()), MemoryCacheLiveResourcePriorityLow); // ImageBitmaps that do not contain any of the source image do not elevate CacheLiveResourcePriority. ASSERT_EQ(memoryCache()->priority(imageOutsideCrop->cachedImage()), MemoryCacheLiveResourcePriorityLow); } // Force a garbage collection to sweep out the local ImageBitmaps. Heap::collectGarbage(BlinkGC::NoHeapPointersOnStack, BlinkGC::GCWithSweep, BlinkGC::ForcedGC); // CacheLiveResourcePriroity should return to CacheLiveResourcePriorityLow when no ImageBitmaps reference the image. ASSERT_EQ(memoryCache()->priority(imageNoCrop->cachedImage()), MemoryCacheLiveResourcePriorityLow); ASSERT_EQ(memoryCache()->priority(imageExteriorCrop->cachedImage()), MemoryCacheLiveResourcePriorityLow); ASSERT_EQ(memoryCache()->priority(imageOutsideCrop->cachedImage()), MemoryCacheLiveResourcePriorityLow); // There is still an ImageBitmap that references this image. ASSERT_EQ(memoryCache()->priority(imageInteriorCrop->cachedImage()), MemoryCacheLiveResourcePriorityLow); imageBitmapInteriorCrop = nullptr; }
// Verifies that HTMLImageElements are given an elevated CacheLiveResourcePriority when used to construct an ImageBitmap. // ImageBitmaps that have crop rects outside of the bounds of the HTMLImageElement do not have elevated CacheLiveResourcePriority. TEST_F(ImageBitmapTest, ImageBitmapLiveResourcePriority) { RefPtr<HTMLImageElement> imageNoCrop = HTMLImageElement::create(*Document::create().get()); ResourcePtr<ImageResource> cachedImageNoCrop = new ImageResource(ResourceRequest("http://foo.com/1"), BitmapImage::create(NativeImageSkia::create(m_bitmap)).get()); imageNoCrop->setImageResource(cachedImageNoCrop.get()); RefPtr<HTMLImageElement> imageInteriorCrop = HTMLImageElement::create(*Document::create().get()); ResourcePtr<ImageResource> cachedImageInteriorCrop = new ImageResource(ResourceRequest("http://foo.com/2"), BitmapImage::create(NativeImageSkia::create(m_bitmap)).get()); imageInteriorCrop->setImageResource(cachedImageInteriorCrop.get()); RefPtr<HTMLImageElement> imageExteriorCrop = HTMLImageElement::create(*Document::create().get()); ResourcePtr<ImageResource> cachedImageExteriorCrop = new ImageResource(ResourceRequest("http://foo.com/3"), BitmapImage::create(NativeImageSkia::create(m_bitmap)).get()); imageExteriorCrop->setImageResource(cachedImageExteriorCrop.get()); RefPtr<HTMLImageElement> imageOutsideCrop = HTMLImageElement::create(*Document::create().get()); ResourcePtr<ImageResource> cachedImageOutsideCrop = new ImageResource(ResourceRequest("http://foo.com/4"), BitmapImage::create(NativeImageSkia::create(m_bitmap)).get()); imageOutsideCrop->setImageResource(cachedImageOutsideCrop.get()); MockImageResourceClient mockClient1, mockClient2, mockClient3, mockClient4; cachedImageNoCrop->addClient(&mockClient1); cachedImageInteriorCrop->addClient(&mockClient2); cachedImageExteriorCrop->addClient(&mockClient3); cachedImageOutsideCrop->addClient(&mockClient4); memoryCache()->add(cachedImageNoCrop.get()); memoryCache()->add(cachedImageInteriorCrop.get()); memoryCache()->add(cachedImageExteriorCrop.get()); memoryCache()->add(cachedImageOutsideCrop.get()); memoryCache()->insertInLiveDecodedResourcesList(cachedImageNoCrop.get()); memoryCache()->insertInLiveDecodedResourcesList(cachedImageInteriorCrop.get()); memoryCache()->insertInLiveDecodedResourcesList(cachedImageExteriorCrop.get()); memoryCache()->insertInLiveDecodedResourcesList(cachedImageOutsideCrop.get()); // HTMLImageElements should default to CacheLiveResourcePriorityLow. ASSERT_EQ(imageNoCrop->cachedImage()->cacheLiveResourcePriority(), Resource::CacheLiveResourcePriorityLow); ASSERT_EQ(imageInteriorCrop->cachedImage()->cacheLiveResourcePriority(), Resource::CacheLiveResourcePriorityLow); ASSERT_EQ(imageExteriorCrop->cachedImage()->cacheLiveResourcePriority(), Resource::CacheLiveResourcePriorityLow); ASSERT_EQ(imageOutsideCrop->cachedImage()->cacheLiveResourcePriority(), Resource::CacheLiveResourcePriorityLow); RefPtrWillBeRawPtr<ImageBitmap> imageBitmapInteriorCrop = ImageBitmap::create(imageInteriorCrop.get(), IntRect(m_bitmap.width() / 2, m_bitmap.height() / 2, m_bitmap.width(), m_bitmap.height())); { RefPtrWillBeRawPtr<ImageBitmap> imageBitmapNoCrop = ImageBitmap::create(imageNoCrop.get(), IntRect(0, 0, m_bitmap.width(), m_bitmap.height())); RefPtrWillBeRawPtr<ImageBitmap> imageBitmapInteriorCrop2 = ImageBitmap::create(imageInteriorCrop.get(), IntRect(m_bitmap.width() / 2, m_bitmap.height() / 2, m_bitmap.width(), m_bitmap.height())); RefPtrWillBeRawPtr<ImageBitmap> imageBitmapExteriorCrop = ImageBitmap::create(imageExteriorCrop.get(), IntRect(-m_bitmap.width() / 2, -m_bitmap.height() / 2, m_bitmap.width(), m_bitmap.height())); RefPtrWillBeRawPtr<ImageBitmap> imageBitmapOutsideCrop = ImageBitmap::create(imageOutsideCrop.get(), IntRect(-m_bitmap.width(), -m_bitmap.height(), m_bitmap.width(), m_bitmap.height())); // Images that are referenced by ImageBitmaps have CacheLiveResourcePriorityHigh. ASSERT_EQ(imageNoCrop->cachedImage()->cacheLiveResourcePriority(), Resource::CacheLiveResourcePriorityHigh); ASSERT_EQ(imageInteriorCrop->cachedImage()->cacheLiveResourcePriority(), Resource::CacheLiveResourcePriorityHigh); ASSERT_EQ(imageExteriorCrop->cachedImage()->cacheLiveResourcePriority(), Resource::CacheLiveResourcePriorityHigh); // ImageBitmaps that do not contain any of the source image do not elevate CacheLiveResourcePriority. ASSERT_EQ(imageOutsideCrop->cachedImage()->cacheLiveResourcePriority(), Resource::CacheLiveResourcePriorityLow); // Stub out references to the ImageBitmaps created and force a // garbage collection to have the ImageBitmaps be collected and // destructed. imageBitmapNoCrop = nullptr; imageBitmapInteriorCrop2 = nullptr; imageBitmapExteriorCrop = nullptr; imageBitmapOutsideCrop = nullptr; Heap::collectGarbage(ThreadState::HeapPointersOnStack, Heap::ForcedForTesting); } // CacheLiveResourcePriroity should return to CacheLiveResourcePriorityLow when no ImageBitmaps reference the image. ASSERT_EQ(imageNoCrop->cachedImage()->cacheLiveResourcePriority(), Resource::CacheLiveResourcePriorityLow); ASSERT_EQ(imageExteriorCrop->cachedImage()->cacheLiveResourcePriority(), Resource::CacheLiveResourcePriorityLow); ASSERT_EQ(imageOutsideCrop->cachedImage()->cacheLiveResourcePriority(), Resource::CacheLiveResourcePriorityLow); // There is still an ImageBitmap that references this image. ASSERT_EQ(imageInteriorCrop->cachedImage()->cacheLiveResourcePriority(), Resource::CacheLiveResourcePriorityHigh); imageBitmapInteriorCrop = nullptr; }
// Verifies that CachedResources are evicted from the decode cache // according to their DecodeCachePriority. TEST_F(MemoryCacheTest, DecodeCacheOrder) { memoryCache()->setDelayBeforeLiveDecodedPrune(0); ResourcePtr<MockImageResource> cachedImageLowPriority = new MockImageResource(ResourceRequest(""), Resource::Raw); ResourcePtr<MockImageResource> cachedImageHighPriority = new MockImageResource(ResourceRequest(""), Resource::Raw); MockImageResourceClient clientLowPriority; MockImageResourceClient clientHighPriority; cachedImageLowPriority->addClient(&clientLowPriority); cachedImageHighPriority->addClient(&clientHighPriority); const char data[5] = "abcd"; cachedImageLowPriority->appendData(data, 1); cachedImageHighPriority->appendData(data, 4); const unsigned lowPrioritySize = cachedImageLowPriority->size(); const unsigned highPrioritySize = cachedImageHighPriority->size(); const unsigned lowPriorityMockDecodeSize = cachedImageLowPriority->decodedSize(); const unsigned highPriorityMockDecodeSize = cachedImageHighPriority->decodedSize(); const unsigned totalSize = lowPrioritySize + highPrioritySize; // Verify that the sizes are different to ensure that we can test eviction order. ASSERT_GT(lowPrioritySize, 0u); ASSERT_NE(lowPrioritySize, highPrioritySize); ASSERT_GT(lowPriorityMockDecodeSize, 0u); ASSERT_NE(lowPriorityMockDecodeSize, highPriorityMockDecodeSize); ASSERT_EQ(memoryCache()->deadSize(), 0u); ASSERT_EQ(memoryCache()->liveSize(), 0u); // Add the items. The item added first would normally be evicted first. memoryCache()->add(cachedImageHighPriority.get()); ASSERT_EQ(memoryCache()->deadSize(), 0u); ASSERT_EQ(memoryCache()->liveSize(), highPrioritySize); memoryCache()->add(cachedImageLowPriority.get()); ASSERT_EQ(memoryCache()->deadSize(), 0u); ASSERT_EQ(memoryCache()->liveSize(), highPrioritySize + lowPrioritySize); // Insert all items in the decoded items list with the same priority memoryCache()->insertInLiveDecodedResourcesList(cachedImageHighPriority.get()); memoryCache()->insertInLiveDecodedResourcesList(cachedImageLowPriority.get()); ASSERT_EQ(memoryCache()->deadSize(), 0u); ASSERT_EQ(memoryCache()->liveSize(), totalSize); // Now we will assign their priority and make sure they are moved to the correct buckets. cachedImageLowPriority->setCacheLiveResourcePriority(Resource::CacheLiveResourcePriorityLow); cachedImageHighPriority->setCacheLiveResourcePriority(Resource::CacheLiveResourcePriorityHigh); // Should first prune the LowPriority item. memoryCache()->setCapacities(memoryCache()->minDeadCapacity(), memoryCache()->liveSize() - 10, memoryCache()->liveSize() - 10); memoryCache()->prune(); ASSERT_EQ(memoryCache()->deadSize(), 0u); ASSERT_EQ(memoryCache()->liveSize(), totalSize - lowPriorityMockDecodeSize); // Should prune the HighPriority item. memoryCache()->setCapacities(memoryCache()->minDeadCapacity(), memoryCache()->liveSize() - 10, memoryCache()->liveSize() - 10); memoryCache()->prune(); ASSERT_EQ(memoryCache()->deadSize(), 0u); ASSERT_EQ(memoryCache()->liveSize(), totalSize - lowPriorityMockDecodeSize - highPriorityMockDecodeSize); }
// Verifies that HTMLImageElements are given an elevated CacheLiveResourcePriority when used to construct an ImageBitmap. // ImageBitmaps that have crop rects outside of the bounds of the HTMLImageElement do not have elevated CacheLiveResourcePriority. TEST_F(ImageBitmapTest, ImageBitmapLiveResourcePriority) { RefPtr<HTMLImageElement> imageNoCrop = HTMLImageElement::create(*Document::create().get()); ResourcePtr<ImageResource> cachedImageNoCrop = new ImageResource(BitmapImage::create(NativeImageSkia::create(m_bitmap)).get()); imageNoCrop->setImageResource(cachedImageNoCrop.get()); RefPtr<HTMLImageElement> imageInteriorCrop = HTMLImageElement::create(*Document::create().get()); ResourcePtr<ImageResource> cachedImageInteriorCrop = new ImageResource(BitmapImage::create(NativeImageSkia::create(m_bitmap)).get()); imageInteriorCrop->setImageResource(cachedImageInteriorCrop.get()); RefPtr<HTMLImageElement> imageExteriorCrop = HTMLImageElement::create(*Document::create().get()); ResourcePtr<ImageResource> cachedImageExteriorCrop = new ImageResource(BitmapImage::create(NativeImageSkia::create(m_bitmap)).get()); imageExteriorCrop->setImageResource(cachedImageExteriorCrop.get()); RefPtr<HTMLImageElement> imageOutsideCrop = HTMLImageElement::create(*Document::create().get()); ResourcePtr<ImageResource> cachedImageOutsideCrop = new ImageResource(BitmapImage::create(NativeImageSkia::create(m_bitmap)).get()); imageOutsideCrop->setImageResource(cachedImageOutsideCrop.get()); MockImageResourceClient mockClient1, mockClient2, mockClient3, mockClient4; cachedImageNoCrop->addClient(&mockClient1); cachedImageInteriorCrop->addClient(&mockClient2); cachedImageExteriorCrop->addClient(&mockClient3); cachedImageOutsideCrop->addClient(&mockClient4); memoryCache()->add(cachedImageNoCrop.get()); memoryCache()->add(cachedImageInteriorCrop.get()); memoryCache()->add(cachedImageExteriorCrop.get()); memoryCache()->add(cachedImageOutsideCrop.get()); memoryCache()->insertInLiveDecodedResourcesList(cachedImageNoCrop.get()); memoryCache()->insertInLiveDecodedResourcesList(cachedImageInteriorCrop.get()); memoryCache()->insertInLiveDecodedResourcesList(cachedImageExteriorCrop.get()); memoryCache()->insertInLiveDecodedResourcesList(cachedImageOutsideCrop.get()); // HTMLImageElements should default to CacheLiveResourcePriorityLow. ASSERT_EQ(imageNoCrop->cachedImage()->cacheLiveResourcePriority(), Resource::CacheLiveResourcePriorityLow); ASSERT_EQ(imageInteriorCrop->cachedImage()->cacheLiveResourcePriority(), Resource::CacheLiveResourcePriorityLow); ASSERT_EQ(imageExteriorCrop->cachedImage()->cacheLiveResourcePriority(), Resource::CacheLiveResourcePriorityLow); ASSERT_EQ(imageOutsideCrop->cachedImage()->cacheLiveResourcePriority(), Resource::CacheLiveResourcePriorityLow); RefPtr<ImageBitmap> imageBitmapInteriorCrop = ImageBitmap::create(imageInteriorCrop.get(), IntRect(m_bitmap.width() / 2, m_bitmap.height() / 2, m_bitmap.width(), m_bitmap.height())); { RefPtr<ImageBitmap> imageBitmapNoCrop = ImageBitmap::create(imageNoCrop.get(), IntRect(0, 0, m_bitmap.width(), m_bitmap.height())); RefPtr<ImageBitmap> imageBitmapInteriorCrop2 = ImageBitmap::create(imageInteriorCrop.get(), IntRect(m_bitmap.width() / 2, m_bitmap.height() / 2, m_bitmap.width(), m_bitmap.height())); RefPtr<ImageBitmap> imageBitmapExteriorCrop = ImageBitmap::create(imageExteriorCrop.get(), IntRect(-m_bitmap.width() / 2, -m_bitmap.height() / 2, m_bitmap.width(), m_bitmap.height())); RefPtr<ImageBitmap> imageBitmapOutsideCrop = ImageBitmap::create(imageOutsideCrop.get(), IntRect(-m_bitmap.width(), -m_bitmap.height(), m_bitmap.width(), m_bitmap.height())); // Images that are referenced by ImageBitmaps have CacheLiveResourcePriorityHigh. ASSERT_EQ(imageNoCrop->cachedImage()->cacheLiveResourcePriority(), Resource::CacheLiveResourcePriorityHigh); ASSERT_EQ(imageInteriorCrop->cachedImage()->cacheLiveResourcePriority(), Resource::CacheLiveResourcePriorityHigh); ASSERT_EQ(imageExteriorCrop->cachedImage()->cacheLiveResourcePriority(), Resource::CacheLiveResourcePriorityHigh); // ImageBitmaps that do not contain any of the source image do not elevate CacheLiveResourcePriority. ASSERT_EQ(imageOutsideCrop->cachedImage()->cacheLiveResourcePriority(), Resource::CacheLiveResourcePriorityLow); } // CacheLiveResourcePriroity should return to CacheLiveResourcePriorityLow when no ImageBitmaps reference the image. ASSERT_EQ(imageNoCrop->cachedImage()->cacheLiveResourcePriority(), Resource::CacheLiveResourcePriorityLow); ASSERT_EQ(imageExteriorCrop->cachedImage()->cacheLiveResourcePriority(), Resource::CacheLiveResourcePriorityLow); ASSERT_EQ(imageOutsideCrop->cachedImage()->cacheLiveResourcePriority(), Resource::CacheLiveResourcePriorityLow); // There is still an ImageBitmap that references this image. ASSERT_EQ(imageInteriorCrop->cachedImage()->cacheLiveResourcePriority(), Resource::CacheLiveResourcePriorityHigh); }
void initializeImpl() { c.setPosition(Vector3f(0.0f, 0.0f, 150.0f)); /* float lightAmbient[] = { 0.2f, 0.3f, 0.6f, 1.0f }; float lightDiffuse[] = { 0.2f, 0.3f, 0.6f, 1.0f }; glEnable(GL_LIGHTING); glEnable(GL_LIGHT0); glLightfv(GL_LIGHT0, GL_AMBIENT, lightAmbient); glLightfv(GL_LIGHT0, GL_DIFFUSE, lightDiffuse); */ swmR.readFile("ViperMKVII.swm", model); const std::vector<GLfloat> &mdlVertices = model.getVerticeVec(); const std::vector<GLfloat> &mdlNormals = model.getVNormalVec(); const std::vector<GLfloat> &mdlTexCoords = model.getVTextureVec(); std::size_t totalSize, vertexSize, normalSize, texCoordSize; vertexSize = sizeof(&mdlVertices[0]) * mdlVertices.size(); normalSize = sizeof(&mdlNormals[0]) * mdlNormals.size(); texCoordSize = sizeof(&mdlTexCoords[0]) * mdlTexCoords.size(); totalSize = vertexSize + normalSize + texCoordSize; vertexBuffer = HardwareBufferPtr(new HardwareBuffer(totalSize, HardwareBuffer::STATIC_DRAW, HardwareBuffer::VERTEX)); vertexBuffer->upload(0, vertexSize, &mdlVertices[0]); vertexBuffer->upload(vertexSize, normalSize, &mdlNormals[0]); vertexBuffer->upload(vertexSize + normalSize, texCoordSize, &mdlTexCoords[0]); //indexBuffer = HardwareBufferPtr(new HardwareBuffer(sizeof(&mdlIndices[0]) * mdlIndices.size(), HardwareBuffer::STATIC_DRAW, HardwareBuffer::INDEX)); //indexBuffer->upload(&mdlIndices[0]); //rop.indexData = new IndexData(); //rop.indexData->indexBuffer = indexBuffer; //rop.indexData->count = mdlIndices.size(); //rop.indexData->start = 0; rop.indexed = false; rop.vertexData = new VertexData(); rop.vertexData->count = mdlVertices.size(); rop.vertexData->start = 0; rop.vertexData->bufferElementGroup.addElement(0,0,POSITION,FLOAT3); rop.vertexData->bufferElementGroup.addElement(0,vertexSize,NORMAL,FLOAT3); rop.vertexData->bufferElementGroup.addElement(0,vertexSize + normalSize,TEXTURE_COORDINATES,FLOAT3); rop.vertexData->bufferBinding[0] = vertexBuffer; rop.primitiveType = RenderOperation::TRIANGLES; glShadeModel(GL_SMOOTH); glPixelStorei(GL_UNPACK_ALIGNMENT, 4); glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); glEnable(GL_DEPTH_TEST); glEnable(GL_TEXTURE_2D); //c.move(Vector3f(0.0, 10450.0, 0.0)); //c.setPosition(Vector3f(4000.0, 10450.0, 20620.0)); //c.setDirection(Vector3f(3999.0, 10450.0, 20620.0)); //c.rotate(Vector3f::Y, static_cast<Math::Units::Radians>(270 * Math::Units::degrees)); texture = TexturePtr(new Texture(NULL, "ViperMKVII", 0, TEXTURE_2D)); texture->setFilePath("ViperMKVII.dds"); texture->prepare(); std::cout << static_cast<Texture*> (texture.get())->getID() << std::endl; texture->load(); atm.Start(); s.myinit(); }
void MemoryCache::pruneDeadResources() { unsigned capacity = deadCapacity(); if (!m_deadSize || (capacity && m_deadSize <= capacity)) return; unsigned targetSize = static_cast<unsigned>(capacity * cTargetPrunePercentage); // Cut by a percentage to avoid immediately pruning again. int size = m_allResources.size(); // See if we have any purged resources we can evict. for (int i = 0; i < size; i++) { Resource* current = m_allResources[i].m_tail; while (current) { Resource* prev = current->m_prevInAllResourcesList; if (current->wasPurged()) { ASSERT(!current->hasClients()); ASSERT(!current->isPreloaded()); evict(current); } current = prev; } } if (targetSize && m_deadSize <= targetSize) return; bool canShrinkLRULists = true; for (int i = size - 1; i >= 0; i--) { // Remove from the tail, since this is the least frequently accessed of the objects. Resource* current = m_allResources[i].m_tail; // First flush all the decoded data in this queue. while (current) { // Protect 'previous' so it can't get deleted during destroyDecodedData(). ResourcePtr<Resource> previous = current->m_prevInAllResourcesList; ASSERT(!previous || previous->inCache()); if (!current->hasClients() && !current->isPreloaded() && current->isLoaded()) { // Destroy our decoded data. This will remove us from // m_liveDecodedResources, and possibly move us to a different // LRU list in m_allResources. current->destroyDecodedData(); if (targetSize && m_deadSize <= targetSize) return; } // Decoded data may reference other resources. Stop iterating if 'previous' somehow got // kicked out of cache during destroyDecodedData(). if (previous && !previous->inCache()) break; current = previous.get(); } // Now evict objects from this queue. current = m_allResources[i].m_tail; while (current) { ResourcePtr<Resource> previous = current->m_prevInAllResourcesList; ASSERT(!previous || previous->inCache()); if (!current->hasClients() && !current->isPreloaded() && !current->isCacheValidator()) { evict(current); if (targetSize && m_deadSize <= targetSize) return; } if (previous && !previous->inCache()) break; current = previous.get(); } // Shrink the vector back down so we don't waste time inspecting // empty LRU lists on future prunes. if (m_allResources[i].m_head) canShrinkLRULists = false; else if (canShrinkLRULists) m_allResources.resize(i); } }
void InspectorResourceContentLoader::start() { m_started = true; Vector<Document*> documents; for (Frame* frame = m_inspectedFrame; frame; frame = frame->tree().traverseNext(m_inspectedFrame)) { if (!frame->isLocalFrame()) continue; LocalFrame* localFrame = toLocalFrame(frame); documents.append(localFrame->document()); documents.appendVector(InspectorPageAgent::importsForFrame(localFrame)); } for (Document* document : documents) { HashSet<String> urlsToFetch; ResourceRequest resourceRequest; HistoryItem* item = document->frame() ? document->frame()->loader().currentItem() : nullptr; if (item) { resourceRequest = FrameLoader::requestFromHistoryItem(item, ReturnCacheDataDontLoad); } else { resourceRequest = document->url(); resourceRequest.setCachePolicy(ReturnCacheDataDontLoad); } resourceRequest.setRequestContext(blink::WebURLRequest::RequestContextInternal); if (!resourceRequest.url().string().isEmpty()) { urlsToFetch.add(resourceRequest.url().string()); FetchRequest request(resourceRequest, FetchInitiatorTypeNames::internal); ResourcePtr<Resource> resource = document->fetcher()->fetchRawResource(request); if (resource) { // Prevent garbage collection by holding a reference to this resource. m_resources.append(resource.get()); ResourceClient* resourceClient = new ResourceClient(this); m_pendingResourceClients.add(resourceClient); resourceClient->waitForResource(resource.get()); } } WillBeHeapVector<RawPtrWillBeMember<CSSStyleSheet> > styleSheets; InspectorCSSAgent::collectAllDocumentStyleSheets(document, styleSheets); for (CSSStyleSheet* styleSheet : styleSheets) { if (styleSheet->isInline() || !styleSheet->contents()->loadCompleted()) continue; String url = styleSheet->baseURL().string(); if (url.isEmpty() || urlsToFetch.contains(url)) continue; urlsToFetch.add(url); FetchRequest request(ResourceRequest(url), FetchInitiatorTypeNames::internal); request.mutableResourceRequest().setRequestContext(blink::WebURLRequest::RequestContextInternal); ResourcePtr<Resource> resource = document->fetcher()->fetchCSSStyleSheet(request); if (!resource) continue; // Prevent garbage collection by holding a reference to this resource. m_resources.append(resource.get()); ResourceClient* resourceClient = new ResourceClient(this); m_pendingResourceClients.add(resourceClient); resourceClient->waitForResource(resource.get()); } } m_allRequestsStarted = true; checkDone(); }
ResourcePtr<Resource> ResourceFetcher::requestResource(Resource::Type type, FetchRequest& request) { ASSERT(request.options().synchronousPolicy == RequestAsynchronously || type == Resource::Raw); TRACE_EVENT0("blink", "ResourceFetcher::requestResource"); KURL url = request.resourceRequest().url(); WTF_LOG(ResourceLoading, "ResourceFetcher::requestResource '%s', charset '%s', priority=%d, type=%s", url.elidedString().latin1().data(), request.charset().latin1().data(), request.priority(), ResourceTypeName(type)); // If only the fragment identifiers differ, it is the same resource. url = MemoryCache::removeFragmentIdentifierIfNeeded(url); if (!url.isValid()) return 0; if (!canRequest(type, url, request.options(), request.originRestriction())) return 0; if (LocalFrame* f = frame()) f->loaderClient()->dispatchWillRequestResource(&request); // See if we can use an existing resource from the cache. ResourcePtr<Resource> resource = memoryCache()->resourceForURL(url); const RevalidationPolicy policy = determineRevalidationPolicy(type, request, resource.get()); switch (policy) { case Reload: memoryCache()->remove(resource.get()); // Fall through case Load: resource = createResourceForLoading(type, request, request.charset()); break; case Revalidate: resource = createResourceForRevalidation(request, resource.get()); break; case Use: memoryCache()->updateForAccess(resource.get()); break; } if (!resource) return 0; if (!resource->hasClients()) m_deadStatsRecorder.update(policy); if (policy != Use) resource->setIdentifier(createUniqueIdentifier()); ResourceLoadPriority priority = loadPriority(type, request); if (priority != resource->resourceRequest().priority()) { resource->mutableResourceRequest().setPriority(priority); resource->didChangePriority(priority, 0); } if (resourceNeedsLoad(resource.get(), request, policy)) { if (!shouldLoadNewResource(type)) { if (memoryCache()->contains(resource.get())) memoryCache()->remove(resource.get()); return 0; } resource->load(this, request.options()); // For asynchronous loads that immediately fail, it's sufficient to return a // null Resource, as it indicates that something prevented the load from starting. // If there's a network error, that failure will happen asynchronously. However, if // a sync load receives a network error, it will have already happened by this point. // In that case, the requester should have access to the relevant ResourceError, so // we need to return a non-null Resource. if (resource->errorOccurred()) { if (memoryCache()->contains(resource.get())) memoryCache()->remove(resource.get()); return 0; } } requestLoadStarted(resource.get(), request, policy == Use ? ResourceLoadingFromCache : ResourceLoadingFromNetwork); ASSERT(resource->url() == url.string()); m_documentResources.set(resource->url(), resource); return resource; }
void ImageLoader::updateFromElement() { // Don't load images for inactive documents. We don't want to slow down the // raw HTML parsing case by loading images we don't intend to display. Document& document = m_element->document(); if (!document.isActive()) return; AtomicString attr = m_element->imageSourceURL(); if (!m_failedLoadURL.isEmpty() && attr == m_failedLoadURL) return; // Do not load any image if the 'src' attribute is missing or if it is // an empty string. ResourcePtr<ImageResource> newImage = 0; if (!attr.isNull() && !stripLeadingAndTrailingHTMLSpaces(attr).isEmpty()) { FetchRequest request(ResourceRequest(document.completeURL(sourceURI(attr))), element()->localName()); AtomicString crossOriginMode = m_element->fastGetAttribute(HTMLNames::crossoriginAttr); if (!crossOriginMode.isNull()) request.setCrossOriginAccessControl(document.securityOrigin(), crossOriginMode); if (m_loadManually) { bool autoLoadOtherImages = document.fetcher()->autoLoadImages(); document.fetcher()->setAutoLoadImages(false); newImage = new ImageResource(request.resourceRequest()); newImage->setLoading(true); document.fetcher()->m_documentResources.set(newImage->url(), newImage.get()); document.fetcher()->setAutoLoadImages(autoLoadOtherImages); } else { newImage = document.fetcher()->fetchImage(request); } // If we do not have an image here, it means that a cross-site // violation occurred, or that the image was blocked via Content // Security Policy, or the page is being dismissed. Trigger an // error event if the page is not being dismissed. if (!newImage && !pageIsBeingDismissed(&document)) { m_failedLoadURL = attr; m_hasPendingErrorEvent = true; errorEventSender().dispatchEventSoon(this); } else clearFailedLoadURL(); } else if (!attr.isNull()) { // Fire an error event if the url is empty. m_hasPendingErrorEvent = true; errorEventSender().dispatchEventSoon(this); } ImageResource* oldImage = m_image.get(); if (newImage != oldImage) { sourceImageChanged(); if (m_hasPendingBeforeLoadEvent) { beforeLoadEventSender().cancelEvent(this); m_hasPendingBeforeLoadEvent = false; } if (m_hasPendingLoadEvent) { loadEventSender().cancelEvent(this); m_hasPendingLoadEvent = false; } // Cancel error events that belong to the previous load, which is now cancelled by changing the src attribute. // If newImage is null and m_hasPendingErrorEvent is true, we know the error event has been just posted by // this load and we should not cancel the event. // FIXME: If both previous load and this one got blocked with an error, we can receive one error event instead of two. if (m_hasPendingErrorEvent && newImage) { errorEventSender().cancelEvent(this); m_hasPendingErrorEvent = false; } m_image = newImage; m_hasPendingBeforeLoadEvent = !m_element->document().isImageDocument() && newImage; m_hasPendingLoadEvent = newImage; m_imageComplete = !newImage; if (newImage) { if (!m_element->document().isImageDocument()) { if (!m_element->document().hasListenerType(Document::BEFORELOAD_LISTENER)) dispatchPendingBeforeLoadEvent(); else beforeLoadEventSender().dispatchEventSoon(this); } else updateRenderer(); // If newImage is cached, addClient() will result in the load event // being queued to fire. Ensure this happens after beforeload is // dispatched. newImage->addClient(this); } else { updateRenderer(); } if (oldImage) oldImage->removeClient(this); } if (RenderImageResource* imageResource = renderImageResource()) imageResource->resetAnimation(); // Only consider updating the protection ref-count of the Element immediately before returning // from this function as doing so might result in the destruction of this ImageLoader. updatedHasPendingEvent(); }
// Verifies that HTMLImageElements are given an elevated CacheLiveResourcePriority when used to construct an ImageBitmap. // ImageBitmaps that have crop rects outside of the bounds of the HTMLImageElement do not have elevated CacheLiveResourcePriority. TEST_F(ImageBitmapTest, ImageBitmapLiveResourcePriority) { RefPtrWillBePersistent<HTMLImageElement> imageNoCrop = HTMLImageElement::create(*Document::create().get()); ResourcePtr<ImageResource> cachedImageNoCrop = new ImageResource(ResourceRequest("http://foo.com/1"), BitmapImage::create(NativeImageSkia::create(m_bitmap)).get()); imageNoCrop->setImageResource(cachedImageNoCrop.get()); RefPtrWillBePersistent<HTMLImageElement> imageInteriorCrop = HTMLImageElement::create(*Document::create().get()); ResourcePtr<ImageResource> cachedImageInteriorCrop = new ImageResource(ResourceRequest("http://foo.com/2"), BitmapImage::create(NativeImageSkia::create(m_bitmap)).get()); imageInteriorCrop->setImageResource(cachedImageInteriorCrop.get()); RefPtrWillBePersistent<HTMLImageElement> imageExteriorCrop = HTMLImageElement::create(*Document::create().get()); ResourcePtr<ImageResource> cachedImageExteriorCrop = new ImageResource(ResourceRequest("http://foo.com/3"), BitmapImage::create(NativeImageSkia::create(m_bitmap)).get()); imageExteriorCrop->setImageResource(cachedImageExteriorCrop.get()); RefPtrWillBePersistent<HTMLImageElement> imageOutsideCrop = HTMLImageElement::create(*Document::create().get()); ResourcePtr<ImageResource> cachedImageOutsideCrop = new ImageResource(ResourceRequest("http://foo.com/4"), BitmapImage::create(NativeImageSkia::create(m_bitmap)).get()); imageOutsideCrop->setImageResource(cachedImageOutsideCrop.get()); MockImageResourceClient mockClient1, mockClient2, mockClient3, mockClient4; cachedImageNoCrop->addClient(&mockClient1); cachedImageInteriorCrop->addClient(&mockClient2); cachedImageExteriorCrop->addClient(&mockClient3); cachedImageOutsideCrop->addClient(&mockClient4); memoryCache()->add(cachedImageNoCrop.get()); memoryCache()->add(cachedImageInteriorCrop.get()); memoryCache()->add(cachedImageExteriorCrop.get()); memoryCache()->add(cachedImageOutsideCrop.get()); memoryCache()->updateDecodedResource(cachedImageNoCrop.get(), UpdateForPropertyChange); memoryCache()->updateDecodedResource(cachedImageInteriorCrop.get(), UpdateForPropertyChange); memoryCache()->updateDecodedResource(cachedImageExteriorCrop.get(), UpdateForPropertyChange); memoryCache()->updateDecodedResource(cachedImageOutsideCrop.get(), UpdateForPropertyChange); // HTMLImageElements should default to CacheLiveResourcePriorityLow. ASSERT_EQ(memoryCache()->priority(imageNoCrop->cachedImage()), MemoryCacheLiveResourcePriorityLow); ASSERT_EQ(memoryCache()->priority(imageInteriorCrop->cachedImage()), MemoryCacheLiveResourcePriorityLow); ASSERT_EQ(memoryCache()->priority(imageExteriorCrop->cachedImage()), MemoryCacheLiveResourcePriorityLow); ASSERT_EQ(memoryCache()->priority(imageOutsideCrop->cachedImage()), MemoryCacheLiveResourcePriorityLow); RefPtrWillBePersistent<ImageBitmap> imageBitmapInteriorCrop = ImageBitmap::create(imageInteriorCrop.get(), IntRect(m_bitmap.width() / 2, m_bitmap.height() / 2, m_bitmap.width(), m_bitmap.height())); { RefPtrWillBePersistent<ImageBitmap> imageBitmapNoCrop = ImageBitmap::create(imageNoCrop.get(), IntRect(0, 0, m_bitmap.width(), m_bitmap.height())); RefPtrWillBePersistent<ImageBitmap> imageBitmapInteriorCrop2 = ImageBitmap::create(imageInteriorCrop.get(), IntRect(m_bitmap.width() / 2, m_bitmap.height() / 2, m_bitmap.width(), m_bitmap.height())); RefPtrWillBePersistent<ImageBitmap> imageBitmapExteriorCrop = ImageBitmap::create(imageExteriorCrop.get(), IntRect(-m_bitmap.width() / 2, -m_bitmap.height() / 2, m_bitmap.width(), m_bitmap.height())); RefPtrWillBePersistent<ImageBitmap> imageBitmapOutsideCrop = ImageBitmap::create(imageOutsideCrop.get(), IntRect(-m_bitmap.width(), -m_bitmap.height(), m_bitmap.width(), m_bitmap.height())); // Images that are referenced by ImageBitmaps have CacheLiveResourcePriorityHigh. ASSERT_EQ(memoryCache()->priority(imageNoCrop->cachedImage()), MemoryCacheLiveResourcePriorityHigh); ASSERT_EQ(memoryCache()->priority(imageInteriorCrop->cachedImage()), MemoryCacheLiveResourcePriorityHigh); ASSERT_EQ(memoryCache()->priority(imageExteriorCrop->cachedImage()), MemoryCacheLiveResourcePriorityHigh); // ImageBitmaps that do not contain any of the source image do not elevate CacheLiveResourcePriority. ASSERT_EQ(memoryCache()->priority(imageOutsideCrop->cachedImage()), MemoryCacheLiveResourcePriorityLow); } // Force a garbage collection to sweep out the local ImageBitmaps. Heap::collectGarbage(ThreadState::NoHeapPointersOnStack); // CacheLiveResourcePriroity should return to CacheLiveResourcePriorityLow when no ImageBitmaps reference the image. ASSERT_EQ(memoryCache()->priority(imageNoCrop->cachedImage()), MemoryCacheLiveResourcePriorityLow); ASSERT_EQ(memoryCache()->priority(imageExteriorCrop->cachedImage()), MemoryCacheLiveResourcePriorityLow); ASSERT_EQ(memoryCache()->priority(imageOutsideCrop->cachedImage()), MemoryCacheLiveResourcePriorityLow); // There is still an ImageBitmap that references this image. ASSERT_EQ(memoryCache()->priority(imageInteriorCrop->cachedImage()), MemoryCacheLiveResourcePriorityHigh); imageBitmapInteriorCrop = nullptr; }
fresh302Response.setHTTPHeaderField(HTTPNames::Last_Modified, kOneDayBeforeOriginalRequest); fresh302Response.setHTTPHeaderField(HTTPNames::Location, redirectTargetUrlString); // Add the redirect to our request. ResourceRequest redirectRequest = ResourceRequest(redirectTargetUrl); firstResource->willFollowRedirect(redirectRequest, fresh302Response); // Add the final response to our request. ResourceResponse fresh200Response; fresh200Response.setURL(redirectTargetUrl); fresh200Response.setHTTPStatusCode(200); fresh200Response.setHTTPHeaderField(HTTPNames::Date, kOriginalRequestDateAsString); fresh200Response.setHTTPHeaderField(HTTPNames::Expires, kOneDayAfterOriginalRequest); firstResource->setResponse(fresh200Response); memoryCache()->add(firstResource.get()); advanceClock(500.); ResourcePtr<Resource> fetched = fetch(); EXPECT_NE(firstResource, fetched); } TEST_F(CachingCorrectnessTest, 302RedirectExplicitlyFreshMaxAge) { KURL redirectUrl(ParsedURLString, kResourceURL); const char redirectTargetUrlString[] = "http://redirect-target.com"; KURL redirectTargetUrl(ParsedURLString, redirectTargetUrlString); ResourcePtr<Resource> firstResource = new Resource(ResourceRequest(redirectUrl), Resource::Raw);