예제 #1
0
FloatRect TilingData::tileBoundsNormalized(int tile) const
{
    assertTile(tile);
    FloatRect bounds(tileBounds(tile));
    bounds.scale(1.0f / m_totalSizeX, 1.0f / m_totalSizeY);
    return bounds;
}
void CaptureGameEngine::Render(CIwRect& bounds)
{
	float tileSize = 64.0f;
	float scale = tileSize / 256;
	CIwVec2 centerTileTL(bounds.x + (bounds.w - tileSize) / 2, bounds.y + (bounds.h - tileSize) / 2);

	for (int x = -1; x <= 1; ++x)
	{
		for (int y = -1; y <= 1; ++y)
		{
			CIwRect tileBounds(centerTileTL.x + (x * tileSize), centerTileTL.y + (y * tileSize), tileSize, tileSize);
			Utils::AlphaRenderImage(g_pTiles[x+1][y+1], tileBounds, 255);
		}
	}
	s3eLocation loc;
	Utils::GetLocation(&loc);
	
	int xDiff = LiveMaps::LongitudeToXAtZoom(loc.m_Longitude, LiveMaps::MaxZoom) - g_topLeft.x;
	int yDiff = LiveMaps::LatitudeToYAtZoom(loc.m_Latitude, LiveMaps::MaxZoom) - g_topLeft.y;
	
	CIwRect meLoc(centerTileTL.x + (xDiff * scale) - g_pUserTexture->GetWidth()/4, centerTileTL.y + (yDiff * scale) - g_pUserTexture->GetWidth()/4, g_pUserTexture->GetWidth() / 2, g_pUserTexture->GetWidth() / 2);
	Utils::AlphaRenderImage(g_pUserTexture, meLoc, 255);

	for (int i = 0; i < g_pCaptures.size(); ++i)
	{
		int xDiff = LiveMaps::LongitudeToXAtZoom(g_pCaptures[i]->m_Longitude, LiveMaps::MaxZoom) - g_topLeft.x;
		int yDiff = LiveMaps::LatitudeToYAtZoom(g_pCaptures[i]->m_Latitude, LiveMaps::MaxZoom) - g_topLeft.y;
		
		CIwRect capLoc(centerTileTL.x + (xDiff * scale) - g_pCursorTexture->GetWidth()/4, centerTileTL.y + (yDiff * scale) - g_pCursorTexture->GetWidth()/4, g_pCursorTexture->GetWidth() / 2, g_pCursorTexture->GetWidth() / 2);
		Utils::AlphaRenderImage(g_pCursorTexture, capLoc, 255);
	}
}
void FindTheSpotGameEngine::Render(CIwRect& bounds)
{
	CIwSVec2 imgBounds(bounds.x, bounds.y);
	Utils::AlphaRenderImage(g_pLogoTexture, imgBounds, 0xff);

	float tileSize = 160.0f;

	if (g_finalScore == 0)
	{
		CIwRect tileBounds(bounds.x + (bounds.w - tileSize) / 2, bounds.y + (bounds.h - tileSize) / 2, tileSize, tileSize);
		Utils::AlphaRenderImage(g_pTile, tileBounds, 255);

		CIwColour white;
		white.Set(0xff, 0xff, 0xff, 0x7f);

		float scale = tileSize / 256.0f;

		Iw2DSetColour(white);
		Iw2DDrawRect(CIwSVec2(tileBounds.x-1, tileBounds.y-1), CIwSVec2(tileBounds.w+2, tileBounds.h+2));
		CIwSVec2 spotLoc(tileBounds.x + (g_tileLoc.x * scale) - (g_pCursorTexture->GetWidth() / 2), tileBounds.y + (g_tileLoc.y * scale) - (g_pCursorTexture->GetHeight() / 2));
		Utils::AlphaRenderImage(g_pCursorTexture, spotLoc, 255);
		
		if (g_renderTemp == 1)
		{
			CIwSVec2 imgBounds(bounds.x, bounds.y + bounds.h - g_pColderTexture->GetHeight());
			Utils::AlphaRenderImage(g_pColderTexture, imgBounds, 255);
		}
		else if (g_renderTemp == 2)
		{
			CIwSVec2 imgBounds(bounds.x, bounds.y + bounds.h - g_pHotterTexture->GetHeight());
			Utils::AlphaRenderImage(g_pHotterTexture, imgBounds, 255);
		}
	}
	else
	{
		tileSize = g_pFoundTexture->GetWidth();
		CIwRect tileBounds(bounds.x + (bounds.w - tileSize) / 2, bounds.y + (bounds.h - tileSize) / 2, tileSize, tileSize);

		Utils::AlphaRenderImage(g_pFoundTexture, tileBounds, 255);
	}
}
예제 #4
0
void WorldMapSprite::draw(Renderer *renderer, const RenderContext &cxt){
	Grid *grid = worldMap->getMapGrid();

	for(int gridX = 0; gridX < grid->getWidth(); gridX++){
		for(int gridY = 0; gridY < grid->getHeight(); gridY++){
			Vector4 color(grid->sample(gridX, gridY), 0, 0, 1.0);
			Vector4 tileBounds(
				gridX*gridCellPixelWidth,
				gridY*gridCellPixelWidth,
				gridCellPixelWidth,
				gridCellPixelWidth
			);	
			renderer->fillRect(tileBounds, color, cxt);
		}
	}
}
std::shared_ptr<TileData> TopoJsonSource::parse(const TileTask& _task,
                                                const MapProjection& _projection) const {

    auto& task = static_cast<const DownloadTileTask&>(_task);

    std::shared_ptr<TileData> tileData = std::make_shared<TileData>();

    // Parse data into a JSON document
    const char* error;
    size_t offset;
    auto document = JsonParseBytes(task.rawTileData->data(), task.rawTileData->size(), &error, &offset);

    if (error) {
        LOGE("Json parsing failed on tile [%s]: %s (%u)", task.tileId().toString().c_str(), error, offset);
        return tileData;
    }

    // Transform JSON data into a TileData using TopoJson functions
    BoundingBox tileBounds(_projection.TileBounds(task.tileId()));
    glm::dvec2 tileOrigin = {tileBounds.min.x, tileBounds.max.y*-1.0};
    double tileInverseScale = 1.0 / tileBounds.width();

    const auto projFn = [&](glm::dvec2 _lonLat){
        glm::dvec2 tmp = _projection.LonLatToMeters(_lonLat);
        return Point {
            (tmp.x - tileOrigin.x) * tileInverseScale,
            (tmp.y - tileOrigin.y) * tileInverseScale,
             0
        };
    };

    // Parse topology and transform
    auto topology = TopoJson::getTopology(document, projFn);

    // Parse each TopoJson object as a data layer
    auto objectsIt = document.FindMember("objects");
    if (objectsIt == document.MemberEnd()) { return tileData; }
    auto& objects = objectsIt->value;
    for (auto layer = objects.MemberBegin(); layer != objects.MemberEnd(); ++layer) {
        tileData->layers.push_back(TopoJson::getLayer(layer, topology, m_id));
    }

    // Discard JSON object and return TileData
    return tileData;

}
std::unique_ptr<AnnotationTile> AnnotationManager::getTile(const TileID& tileID) {
    auto tile = std::make_unique<AnnotationTile>();

    AnnotationTileLayer& pointLayer = *tile->layers.emplace(
        PointLayerID,
        std::make_unique<AnnotationTileLayer>()).first->second;

    LatLngBounds tileBounds(tileID);

    pointTree.query(boost::geometry::index::intersects(tileBounds),
        boost::make_function_output_iterator([&](const auto& val){
            val->updateLayer(tileID, pointLayer);
        }));

    for (const auto& shape : shapeAnnotations) {
        shape.second->updateTile(tileID, *tile);
    }

    return tile;
}
예제 #7
0
IntRect TilingData::tileBoundsWithBorder(int tile) const
{
    IntRect bounds = tileBounds(tile);

    if (m_borderTexels) {
        int x1 = bounds.x();
        int x2 = bounds.maxX();
        int y1 = bounds.y();
        int y2 = bounds.maxY();

        if (tileXIndex(tile) > 0)
            x1--;
        if (tileXIndex(tile) < (numTilesX() - 1))
            x2++;
        if (tileYIndex(tile) > 0)
            y1--;
        if (tileYIndex(tile) < (numTilesY() - 1))
            y2++;

        bounds = IntRect(x1, y1, x2 - x1, y2 - y1);
    }

    return bounds;
}
예제 #8
0
파일: bdpt.cpp 프로젝트: wjakob/pbrt-v3
void BDPTIntegrator::Render(const Scene &scene) {
    std::unique_ptr<LightDistribution> lightDistribution =
        CreateLightSampleDistribution(lightSampleStrategy, scene);

    // Compute a reverse mapping from light pointers to offsets into the
    // scene lights vector (and, equivalently, offsets into
    // lightDistr). Added after book text was finalized; this is critical
    // to reasonable performance with 100s+ of light sources.
    std::unordered_map<const Light *, size_t> lightToIndex;
    for (size_t i = 0; i < scene.lights.size(); ++i)
        lightToIndex[scene.lights[i].get()] = i;

    // Partition the image into tiles
    Film *film = camera->film;
    const Bounds2i sampleBounds = film->GetSampleBounds();
    const Vector2i sampleExtent = sampleBounds.Diagonal();
    const int tileSize = 16;
    const int nXTiles = (sampleExtent.x + tileSize - 1) / tileSize;
    const int nYTiles = (sampleExtent.y + tileSize - 1) / tileSize;
    ProgressReporter reporter(nXTiles * nYTiles, "Rendering");

    // Allocate buffers for debug visualization
    const int bufferCount = (1 + maxDepth) * (6 + maxDepth) / 2;
    std::vector<std::unique_ptr<Film>> weightFilms(bufferCount);
    if (visualizeStrategies || visualizeWeights) {
        for (int depth = 0; depth <= maxDepth; ++depth) {
            for (int s = 0; s <= depth + 2; ++s) {
                int t = depth + 2 - s;
                if (t == 0 || (s == 1 && t == 1)) continue;

                std::string filename =
                    StringPrintf("bdpt_d%02i_s%02i_t%02i.exr", depth, s, t);

                weightFilms[BufferIndex(s, t)] = std::unique_ptr<Film>(new Film(
                    film->fullResolution,
                    Bounds2f(Point2f(0, 0), Point2f(1, 1)),
                    std::unique_ptr<Filter>(CreateBoxFilter(ParamSet())),
                    film->diagonal * 1000, filename, 1.f));
            }
        }
    }

    // Render and write the output image to disk
    if (scene.lights.size() > 0) {
        ParallelFor2D([&](const Point2i tile) {
            // Render a single tile using BDPT
            MemoryArena arena;
            int seed = tile.y * nXTiles + tile.x;
            std::unique_ptr<Sampler> tileSampler = sampler->Clone(seed);
            int x0 = sampleBounds.pMin.x + tile.x * tileSize;
            int x1 = std::min(x0 + tileSize, sampleBounds.pMax.x);
            int y0 = sampleBounds.pMin.y + tile.y * tileSize;
            int y1 = std::min(y0 + tileSize, sampleBounds.pMax.y);
            Bounds2i tileBounds(Point2i(x0, y0), Point2i(x1, y1));
            std::unique_ptr<FilmTile> filmTile =
                camera->film->GetFilmTile(tileBounds);
            for (Point2i pPixel : tileBounds) {
                tileSampler->StartPixel(pPixel);
                if (!InsideExclusive(pPixel, pixelBounds))
                    continue;
                do {
                    // Generate a single sample using BDPT
                    Point2f pFilm = (Point2f)pPixel + tileSampler->Get2D();

                    // Trace the camera subpath
                    Vertex *cameraVertices = arena.Alloc<Vertex>(maxDepth + 2);
                    Vertex *lightVertices = arena.Alloc<Vertex>(maxDepth + 1);
                    int nCamera = GenerateCameraSubpath(
                        scene, *tileSampler, arena, maxDepth + 2, *camera,
                        pFilm, cameraVertices);
                    // Get a distribution for sampling the light at the
                    // start of the light subpath. Because the light path
                    // follows multiple bounces, basing the sampling
                    // distribution on any of the vertices of the camera
                    // path is unlikely to be a good strategy. We use the
                    // PowerLightDistribution by default here, which
                    // doesn't use the point passed to it.
                    const Distribution1D *lightDistr =
                        lightDistribution->Lookup(cameraVertices[0].p());
                    // Now trace the light subpath
                    int nLight = GenerateLightSubpath(
                        scene, *tileSampler, arena, maxDepth + 1,
                        cameraVertices[0].time(), *lightDistr, lightToIndex,
                        lightVertices);

                    // Execute all BDPT connection strategies
                    Spectrum L(0.f);
                    for (int t = 1; t <= nCamera; ++t) {
                        for (int s = 0; s <= nLight; ++s) {
                            int depth = t + s - 2;
                            if ((s == 1 && t == 1) || depth < 0 ||
                                depth > maxDepth)
                                continue;
                            // Execute the $(s, t)$ connection strategy and
                            // update _L_
                            Point2f pFilmNew = pFilm;
                            Float misWeight = 0.f;
                            Spectrum Lpath = ConnectBDPT(
                                scene, lightVertices, cameraVertices, s, t,
                                *lightDistr, lightToIndex, *camera, *tileSampler,
                                &pFilmNew, &misWeight);
                            VLOG(2) << "Connect bdpt s: " << s <<", t: " << t <<
                                ", Lpath: " << Lpath << ", misWeight: " << misWeight;
                            if (visualizeStrategies || visualizeWeights) {
                                Spectrum value;
                                if (visualizeStrategies)
                                    value =
                                        misWeight == 0 ? 0 : Lpath / misWeight;
                                if (visualizeWeights) value = Lpath;
                                weightFilms[BufferIndex(s, t)]->AddSplat(
                                    pFilmNew, value);
                            }
                            if (t != 1)
                                L += Lpath;
                            else
                                film->AddSplat(pFilmNew, Lpath);
                        }
                    }
                    VLOG(2) << "Add film sample pFilm: " << pFilm << ", L: " << L <<
                        ", (y: " << L.y() << ")";
                    filmTile->AddSample(pFilm, L);
                    arena.Reset();
                } while (tileSampler->StartNextSample());
            }
            film->MergeFilmTile(std::move(filmTile));
            reporter.Update();
        }, Point2i(nXTiles, nYTiles));
        reporter.Done();
    }
    film->WriteImage(1.0f / sampler->samplesPerPixel);

    // Write buffers for debug visualization
    if (visualizeStrategies || visualizeWeights) {
        const Float invSampleCount = 1.0f / sampler->samplesPerPixel;
        for (size_t i = 0; i < weightFilms.size(); ++i)
            if (weightFilms[i]) weightFilms[i]->WriteImage(invSampleCount);
    }
}
예제 #9
0
void BoundsCreator::processTile(int z, int i, int j,
    BoundsMap& bounds,
    VolumeMap& volumes)
{
    std::string path = m_stack.getTilePath(0, j, i, 's', z);
    printf("%s\n", path.c_str());

    PngImage image(path.c_str());    

    int width = image.getWidth();
    int height = image.getHeight();

    //printf("width=%d height=%d\n", image.getWidth(), image.getHeight());

    // Note that i, j always represent full tiles, because only the
    // final edge/corner tile is ever partial
    int baseX = m_tilesize * i;
    int baseY = m_tilesize * j;

    // As a special case for speed if tile is completely empty we can
    // union in the bounds in a single step.
    if (isTileEmpty(image))
    {
        int edgeX = baseX + width - 1;
        int edgeY = baseY + height - 1;
    
        PixelBoundBox tileBounds(baseX, baseY, edgeX, edgeY);
    
        if (bounds.find(0) == bounds.end())
        {        
            bounds[0] = tileBounds;
            volumes[0] = width * height;
        }
        else
        {
            bounds[0].unionBounds(tileBounds);
            volumes[0] += (width * height);
        }    
    }
    else
    {
        // The tile is not empty, union every pixel separately
        for (int tileX = 0; tileX < width; ++tileX)
        {
            for (int tileY = 0; tileY < height; ++tileY)
            {
                int x = baseX + tileX;
                int y = baseY + tileY;
                unsigned int spid = image.getPixelID(tileX, tileY);
            
                if (bounds.find(spid) == bounds.end())
                {
                    bounds[spid] = PixelBoundBox(x, y);
                    volumes[spid] = 1;
                }
                else
                {   
                    bounds[spid].unionPoint(x, y);
                    volumes[spid] += 1;
                }
            }
        }
    }
}
예제 #10
0
// SamplerIntegrator Method Definitions
void SamplerIntegrator::Render(const Scene &scene) {
    ProfilePhase p(Prof::IntegratorRender);
    Preprocess(scene, *sampler);
    // Render image tiles in parallel

    // Compute number of tiles, _nTiles_, to use for parallel rendering
    Bounds2i sampleBounds = camera->film->GetSampleBounds();
    Vector2i sampleExtent = sampleBounds.Diagonal();
    const int tileSize = 16;
    Point2i nTiles((sampleExtent.x + tileSize - 1) / tileSize,
                   (sampleExtent.y + tileSize - 1) / tileSize);
    ProgressReporter reporter(nTiles.x * nTiles.y, "Rendering");
    {
        StatTimer timer(&renderingTime);
        ParallelFor2D([&](Point2i tile) {
            // Render section of image corresponding to _tile_

            // Allocate _MemoryArena_ for tile
            MemoryArena arena;

            // Get sampler instance for tile
            int seed = tile.y * nTiles.x + tile.x;
            std::unique_ptr<Sampler> tileSampler = sampler->Clone(seed);

            // Compute sample bounds for tile
            int x0 = sampleBounds.pMin.x + tile.x * tileSize;
            int x1 = std::min(x0 + tileSize, sampleBounds.pMax.x);
            int y0 = sampleBounds.pMin.y + tile.y * tileSize;
            int y1 = std::min(y0 + tileSize, sampleBounds.pMax.y);
            Bounds2i tileBounds(Point2i(x0, y0), Point2i(x1, y1));

            // Get _FilmTile_ for tile
            std::unique_ptr<FilmTile> filmTile =
                camera->film->GetFilmTile(tileBounds);

            // Loop over pixels in tile to render them
            for (Point2i pixel : tileBounds) {
                {
                    ProfilePhase pp(Prof::StartPixel);
                    tileSampler->StartPixel(pixel);
                }
                do {
                    // Initialize _CameraSample_ for current sample
                    CameraSample cameraSample =
                        tileSampler->GetCameraSample(pixel);

                    // Generate camera ray for current sample
                    RayDifferential ray;
                    Float rayWeight =
                        camera->GenerateRayDifferential(cameraSample, &ray);
                    ray.ScaleDifferentials(
                        1 / std::sqrt((Float)tileSampler->samplesPerPixel));
                    ++nCameraRays;

                    // Evaluate radiance along camera ray
                    Spectrum L(0.f);
                    if (rayWeight > 0) L = Li(ray, scene, *tileSampler, arena);

                    // Issue warning if unexpected radiance value returned
                    if (L.HasNaNs()) {
                        Error(
                            "Not-a-number radiance value returned "
                            "for image sample.  Setting to black.");
                        L = Spectrum(0.f);
                    } else if (L.y() < -1e-5) {
                        Error(
                            "Negative luminance value, %f, returned "
                            "for image sample.  Setting to black.",
                            L.y());
                        L = Spectrum(0.f);
                    } else if (std::isinf(L.y())) {
                        Error(
                            "Infinite luminance value returned "
                            "for image sample.  Setting to black.");
                        L = Spectrum(0.f);
                    }

                    // Add camera ray's contribution to image
                    filmTile->AddSample(cameraSample.pFilm, L, rayWeight);

                    // Free _MemoryArena_ memory from computing image sample
                    // value
                    arena.Reset();
                } while (tileSampler->StartNextSample());
            }

            // Merge image tile into _Film_
            camera->film->MergeFilmTile(std::move(filmTile));
            reporter.Update();
        }, nTiles);
        reporter.Done();
    }

    // Save final image after rendering
    camera->film->WriteImage();
}
예제 #11
0
void BDPTIntegrator::Render(const Scene &scene) {
    ProfilePhase p(Prof::IntegratorRender);
    // Compute _lightDistr_ for sampling lights proportional to power
    std::unique_ptr<Distribution1D> lightDistr =
        ComputeLightPowerDistribution(scene);

    // Partition the image into tiles
    Film *film = camera->film;
    const Bounds2i sampleBounds = film->GetSampleBounds();
    const Vector2i sampleExtent = sampleBounds.Diagonal();
    const int tileSize = 16;
    const int nXTiles = (sampleExtent.x + tileSize - 1) / tileSize;
    const int nYTiles = (sampleExtent.y + tileSize - 1) / tileSize;
    ProgressReporter reporter(nXTiles * nYTiles, "Rendering");

    // Allocate buffers for debug visualization
    const int bufferCount = (1 + maxDepth) * (6 + maxDepth) / 2;
    std::vector<std::unique_ptr<Film>> weightFilms(bufferCount);
    if (visualizeStrategies || visualizeWeights) {
        for (int depth = 0; depth <= maxDepth; ++depth) {
            for (int s = 0; s <= depth + 2; ++s) {
                int t = depth + 2 - s;
                if (t == 0 || (s == 1 && t == 1)) continue;

                std::string filename =
                    StringPrintf("bdpt_d%02i_s%02i_t%02i.exr", depth, s, t);

                weightFilms[BufferIndex(s, t)] = std::unique_ptr<Film>(new Film(
                    film->fullResolution,
                    Bounds2f(Point2f(0, 0), Point2f(1, 1)),
                    std::unique_ptr<Filter>(CreateBoxFilter(ParamSet())),
                    film->diagonal * 1000, filename, 1.f));
            }
        }
    }

    // Render and write the output image to disk
    if (scene.lights.size() > 0) {
        StatTimer timer(&renderingTime);
        ParallelFor2D([&](const Point2i tile) {
            // Render a single tile using BDPT
            MemoryArena arena;
            int seed = tile.y * nXTiles + tile.x;
            std::unique_ptr<Sampler> tileSampler = sampler->Clone(seed);
            int x0 = sampleBounds.pMin.x + tile.x * tileSize;
            int x1 = std::min(x0 + tileSize, sampleBounds.pMax.x);
            int y0 = sampleBounds.pMin.y + tile.y * tileSize;
            int y1 = std::min(y0 + tileSize, sampleBounds.pMax.y);
            Bounds2i tileBounds(Point2i(x0, y0), Point2i(x1, y1));
            std::unique_ptr<FilmTile> filmTile =
                camera->film->GetFilmTile(tileBounds);
            for (Point2i pPixel : tileBounds) {
                tileSampler->StartPixel(pPixel);
                if (!InsideExclusive(pPixel, pixelBounds))
                    continue;
                do {
                    // Generate a single sample using BDPT
                    Point2f pFilm = (Point2f)pPixel + tileSampler->Get2D();

                    // Trace the camera and light subpaths
                    Vertex *cameraVertices = arena.Alloc<Vertex>(maxDepth + 2);
                    Vertex *lightVertices = arena.Alloc<Vertex>(maxDepth + 1);
                    int nCamera = GenerateCameraSubpath(
                        scene, *tileSampler, arena, maxDepth + 2, *camera,
                        pFilm, cameraVertices);
                    int nLight = GenerateLightSubpath(
                        scene, *tileSampler, arena, maxDepth + 1,
                        cameraVertices[0].time(), *lightDistr, lightVertices);

                    // Execute all BDPT connection strategies
                    Spectrum L(0.f);
                    for (int t = 1; t <= nCamera; ++t) {
                        for (int s = 0; s <= nLight; ++s) {
                            int depth = t + s - 2;
                            if ((s == 1 && t == 1) || depth < 0 ||
                                depth > maxDepth)
                                continue;
                            // Execute the $(s, t)$ connection strategy and
                            // update _L_
                            Point2f pFilmNew = pFilm;
                            Float misWeight = 0.f;
                            Spectrum Lpath = ConnectBDPT(
                                scene, lightVertices, cameraVertices, s, t,
                                *lightDistr, *camera, *tileSampler, &pFilmNew,
                                &misWeight);
                            if (visualizeStrategies || visualizeWeights) {
                                Spectrum value;
                                if (visualizeStrategies)
                                    value =
                                        misWeight == 0 ? 0 : Lpath / misWeight;
                                if (visualizeWeights) value = Lpath;
                                weightFilms[BufferIndex(s, t)]->AddSplat(
                                    pFilmNew, value);
                            }
                            if (t != 1)
                                L += Lpath;
                            else
                                film->AddSplat(pFilmNew, Lpath);
                        }
                    }
                    filmTile->AddSample(pFilm, L);
                    arena.Reset();
                } while (tileSampler->StartNextSample());
            }
            film->MergeFilmTile(std::move(filmTile));
            reporter.Update();
        }, Point2i(nXTiles, nYTiles));
        reporter.Done();
    }
    film->WriteImage(1.0f / sampler->samplesPerPixel);

    // Write buffers for debug visualization
    if (visualizeStrategies || visualizeWeights) {
        const Float invSampleCount = 1.0f / sampler->samplesPerPixel;
        for (size_t i = 0; i < weightFilms.size(); ++i)
            if (weightFilms[i]) weightFilms[i]->WriteImage(invSampleCount);
    }
}
예제 #12
0
bool
ClientTiledLayerBuffer::ComputeProgressiveUpdateRegion(const nsIntRegion& aInvalidRegion,
                                                      const nsIntRegion& aOldValidRegion,
                                                      nsIntRegion& aRegionToPaint,
                                                      BasicTiledLayerPaintData* aPaintData,
                                                      bool aIsRepeated)
{
  aRegionToPaint = aInvalidRegion;

  // If the composition bounds rect is empty, we can't make any sensible
  // decision about how to update coherently. In this case, just update
  // everything in one transaction.
  if (aPaintData->mCompositionBounds.IsEmpty()) {
    aPaintData->mPaintFinished = true;
    return false;
  }

  // If this is a low precision buffer, we force progressive updates. The
  // assumption is that the contents is less important, so visual coherency
  // is lower priority than speed.
  bool drawingLowPrecision = IsLowPrecision();

  // Find out if we have any non-stale content to update.
  nsIntRegion staleRegion;
  staleRegion.And(aInvalidRegion, aOldValidRegion);

  // Find out the current view transform to determine which tiles to draw
  // first, and see if we should just abort this paint. Aborting is usually
  // caused by there being an incoming, more relevant paint.
  ParentLayerRect compositionBounds;
  CSSToParentLayerScale zoom;
#if defined(MOZ_WIDGET_ANDROID)
  bool abortPaint = mManager->ProgressiveUpdateCallback(!staleRegion.Contains(aInvalidRegion),
                                                        compositionBounds, zoom,
                                                        !drawingLowPrecision);
#else
  MOZ_ASSERT(mSharedFrameMetricsHelper);

  ContainerLayer* parent = mThebesLayer->AsLayer()->GetParent();

  bool abortPaint =
    mSharedFrameMetricsHelper->UpdateFromCompositorFrameMetrics(
      parent,
      !staleRegion.Contains(aInvalidRegion),
      drawingLowPrecision,
      compositionBounds,
      zoom);
#endif

  if (abortPaint) {
    // We ignore if front-end wants to abort if this is the first,
    // non-low-precision paint, as in that situation, we're about to override
    // front-end's page/viewport metrics.
    if (!aPaintData->mFirstPaint || drawingLowPrecision) {
      PROFILER_LABEL("ContentClient", "Abort painting");
      aRegionToPaint.SetEmpty();
      return aIsRepeated;
    }
  }

  // Transform the screen coordinates into transformed layout device coordinates.
  LayoutDeviceRect transformedCompositionBounds =
    TransformCompositionBounds(compositionBounds, zoom, aPaintData->mScrollOffset,
                               aPaintData->mResolution, aPaintData->mTransformParentLayerToLayout);

  // Paint tiles that have stale content or that intersected with the screen
  // at the time of issuing the draw command in a single transaction first.
  // This is to avoid rendering glitches on animated page content, and when
  // layers change size/shape.
  LayoutDeviceRect coherentUpdateRect =
    transformedCompositionBounds.Intersect(aPaintData->mCompositionBounds);

  nsIntRect roundedCoherentUpdateRect =
    LayoutDeviceIntRect::ToUntyped(RoundedOut(coherentUpdateRect));

  aRegionToPaint.And(aInvalidRegion, roundedCoherentUpdateRect);
  aRegionToPaint.Or(aRegionToPaint, staleRegion);
  bool drawingStale = !aRegionToPaint.IsEmpty();
  if (!drawingStale) {
    aRegionToPaint = aInvalidRegion;
  }

  // Prioritise tiles that are currently visible on the screen.
  bool paintVisible = false;
  if (aRegionToPaint.Intersects(roundedCoherentUpdateRect)) {
    aRegionToPaint.And(aRegionToPaint, roundedCoherentUpdateRect);
    paintVisible = true;
  }

  // Paint area that's visible and overlaps previously valid content to avoid
  // visible glitches in animated elements, such as gifs.
  bool paintInSingleTransaction = paintVisible && (drawingStale || aPaintData->mFirstPaint);

  // The following code decides what order to draw tiles in, based on the
  // current scroll direction of the primary scrollable layer.
  NS_ASSERTION(!aRegionToPaint.IsEmpty(), "Unexpectedly empty paint region!");
  nsIntRect paintBounds = aRegionToPaint.GetBounds();

  int startX, incX, startY, incY;
  int tileLength = GetScaledTileLength();
  if (aPaintData->mScrollOffset.x >= aPaintData->mLastScrollOffset.x) {
    startX = RoundDownToTileEdge(paintBounds.x);
    incX = tileLength;
  } else {
    startX = RoundDownToTileEdge(paintBounds.XMost() - 1);
    incX = -tileLength;
  }

  if (aPaintData->mScrollOffset.y >= aPaintData->mLastScrollOffset.y) {
    startY = RoundDownToTileEdge(paintBounds.y);
    incY = tileLength;
  } else {
    startY = RoundDownToTileEdge(paintBounds.YMost() - 1);
    incY = -tileLength;
  }

  // Find a tile to draw.
  nsIntRect tileBounds(startX, startY, tileLength, tileLength);
  int32_t scrollDiffX = aPaintData->mScrollOffset.x - aPaintData->mLastScrollOffset.x;
  int32_t scrollDiffY = aPaintData->mScrollOffset.y - aPaintData->mLastScrollOffset.y;
  // This loop will always terminate, as there is at least one tile area
  // along the first/last row/column intersecting with regionToPaint, or its
  // bounds would have been smaller.
  while (true) {
    aRegionToPaint.And(aInvalidRegion, tileBounds);
    if (!aRegionToPaint.IsEmpty()) {
      break;
    }
    if (Abs(scrollDiffY) >= Abs(scrollDiffX)) {
      tileBounds.x += incX;
    } else {
      tileBounds.y += incY;
    }
  }

  if (!aRegionToPaint.Contains(aInvalidRegion)) {
    // The region needed to paint is larger then our progressive chunk size
    // therefore update what we want to paint and ask for a new paint transaction.

    // If we need to draw more than one tile to maintain coherency, make
    // sure it happens in the same transaction by requesting this work be
    // repeated immediately.
    // If this is unnecessary, the remaining work will be done tile-by-tile in
    // subsequent transactions.
    if (!drawingLowPrecision && paintInSingleTransaction) {
      return true;
    }

    mManager->SetRepeatTransaction();
    return false;
  }

  // We're not repeating painting and we've not requested a repeat transaction,
  // so the paint is finished. If there's still a separate low precision
  // paint to do, it will get marked as unfinished later.
  aPaintData->mPaintFinished = true;
  return false;
}