Skip to content
This repository has been archived by the owner on Aug 8, 2023. It is now read-only.

Commit

Permalink
[core] Privatize layers and sources
Browse files Browse the repository at this point in the history
  • Loading branch information
jfirebaugh committed Dec 1, 2015
1 parent bafbf6c commit b767404
Show file tree
Hide file tree
Showing 5 changed files with 130 additions and 124 deletions.
9 changes: 2 additions & 7 deletions src/mbgl/map/map_context.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -277,19 +277,15 @@ void MapContext::setSourceTileCacheSize(size_t size) {
if (size != sourceCacheSize) {
sourceCacheSize = size;
if (!style) return;
for (const auto &source : style->sources) {
source->setCacheSize(sourceCacheSize);
}
style->setSourceTileCacheSize(size);
asyncInvalidate.send();
}
}

void MapContext::onLowMemory() {
assert(util::ThreadContext::currentlyOn(util::ThreadType::Map));
if (!style) return;
for (const auto &source : style->sources) {
source->onLowMemory();
}
style->onLowMemory();
asyncInvalidate.send();
}

Expand All @@ -300,7 +296,6 @@ void MapContext::setSprite(const std::string& name, std::shared_ptr<const Sprite

void MapContext::onTileDataChanged() {
assert(util::ThreadContext::currentlyOn(util::ThreadType::Map));

updateFlags |= Update::Repaint;
asyncUpdate.send();
}
Expand Down
118 changes: 19 additions & 99 deletions src/mbgl/renderer/painter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -109,19 +109,6 @@ void Painter::changeMatrix() {
matrix::multiply(nativeMatrix, projMatrix, nativeMatrix);
}

void Painter::clear() {
MBGL_DEBUG_GROUP("clear");
config.stencilFunc.reset();
config.stencilTest = GL_TRUE;
config.stencilMask = 0xFF;
config.depthTest = GL_FALSE;
config.depthMask = GL_TRUE;
config.clearColor = { background[0], background[1], background[2], background[3] };
config.clearStencil = 0;
config.clearDepth = 1;
MBGL_CHECK_ERROR(glClear(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT | GL_DEPTH_BUFFER_BIT));
}

void Painter::prepareTile(const Tile& tile) {
const GLint ref = (GLint)tile.clip.reference.to_ulong();
const GLuint mask = (GLuint)tile.clip.mask.to_ulong();
Expand All @@ -135,19 +122,14 @@ void Painter::render(const Style& style, const FrameData& frame_, SpriteAtlas& a
spriteAtlas = style.spriteAtlas.get();
lineAtlas = style.lineAtlas.get();

std::set<Source*> sources;
for (const auto& source : style.sources) {
if (source->enabled) {
sources.insert(source.get());
}
}
RenderData renderData = style.getRenderData();
const std::vector<RenderItem>& order = renderData.order;
const std::set<Source*>& sources = renderData.sources;
const Color& background = renderData.backgroundColor;

resize();
changeMatrix();

// Figure out what buckets we have to draw and what order we have to draw them in.
const auto order = determineRenderOrder(style);

// - UPLOAD PASS -------------------------------------------------------------------------------
// Uploads all required buffers and images before we do any actual rendering.
{
Expand All @@ -167,6 +149,21 @@ void Painter::render(const Style& style, const FrameData& frame_, SpriteAtlas& a
}
}

// - CLEAR -------------------------------------------------------------------------------------
// Renders the backdrop of the OpenGL view. This also paints in areas where we don't have any
// tiles whatsoever.
{
MBGL_DEBUG_GROUP("clear");
config.stencilFunc.reset();
config.stencilTest = GL_TRUE;
config.stencilMask = 0xFF;
config.depthTest = GL_FALSE;
config.depthMask = GL_TRUE;
config.clearColor = { background[0], background[1], background[2], background[3] };
config.clearStencil = 0;
config.clearDepth = 1;
MBGL_CHECK_ERROR(glClear(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT | GL_DEPTH_BUFFER_BIT));
}

// - CLIPPING MASKS ----------------------------------------------------------------------------
// Draws the clipping masks to the stencil buffer.
Expand All @@ -180,8 +177,6 @@ void Painter::render(const Style& style, const FrameData& frame_, SpriteAtlas& a
source->updateMatrices(projMatrix, state);
}

clear();

drawClippingMasks(sources);
}

Expand Down Expand Up @@ -275,81 +270,6 @@ void Painter::renderPass(RenderPass pass_,
}
}

std::vector<RenderItem> Painter::determineRenderOrder(const Style& style) {
std::vector<RenderItem> order;

for (const auto& layerPtr : style.layers) {
const auto& layer = *layerPtr;
if (layer.visibility == VisibilityType::None) continue;
if (layer.type == StyleLayerType::Background) {
// This layer defines a background color/image.
auto& props = dynamic_cast<const BackgroundLayer&>(layer).paint;
if (props.pattern.value.from.empty()) {
// This is a solid background. We can use glClear().
background = props.color;
background[0] *= props.opacity;
background[1] *= props.opacity;
background[2] *= props.opacity;
background[3] *= props.opacity;
} else {
// This is a textured background. We need to render it with a quad.
background = {{ 0, 0, 0, 0 }};
order.emplace_back(layer);
}
continue;
}

Source* source = style.getSource(layer.source);
if (!source) {
Log::Warning(Event::Render, "can't find source for layer '%s'", layer.id.c_str());
continue;
}

// Skip this layer if it's outside the range of min/maxzoom.
// This may occur when there /is/ a bucket created for this layer, but the min/max-zoom
// is set to a fractional value, or value that is larger than the source maxzoom.
const double zoom = state.getZoom();
if (layer.minZoom > zoom ||
layer.maxZoom <= zoom) {
continue;
}

const auto& tiles = source->getTiles();
for (auto tile : tiles) {
assert(tile);
if (!tile->data && !tile->data->isReady()) {
continue;
}

// We're not clipping symbol layers, so when we have both parents and children of symbol
// layers, we drop all children in favor of their parent to avoid duplicate labels.
// See https://github.com/mapbox/mapbox-gl-native/issues/2482
if (layer.type == StyleLayerType::Symbol) {
bool skip = false;
// Look back through the buckets we decided to render to find out whether there is
// already a bucket from this layer that is a parent of this tile. Tiles are ordered
// by zoom level when we obtain them from getTiles().
for (auto it = order.rbegin(); it != order.rend() && (&it->layer == &layer); ++it) {
if (tile->id.isChildOf(it->tile->id)) {
skip = true;
break;
}
}
if (skip) {
continue;
}
}

auto bucket = tile->data->getBucket(layer);
if (bucket) {
order.emplace_back(layer, tile, bucket);
}
}
}

return order;
}

void Painter::renderBackground(const BackgroundLayer& layer) {
// Note: This function is only called for textured background. Otherwise, the background color
// is created with glClear.
Expand Down
17 changes: 0 additions & 17 deletions src/mbgl/renderer/painter.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -68,27 +68,11 @@ class CollisionBoxShader;

struct ClipID;

struct RenderItem {
inline RenderItem(const StyleLayer& layer_,
const Tile* tile_ = nullptr,
Bucket* bucket_ = nullptr)
: tile(tile_), bucket(bucket_), layer(layer_) {
}

const Tile* const tile;
Bucket* const bucket;
const StyleLayer& layer;
};

class Painter : private util::noncopyable {
public:
Painter(MapData&, TransformState&);
~Painter();

// Renders the backdrop of the OpenGL view. This also paints in areas where we don't have any
// tiles whatsoever.
void clear();

// Updates the default matrices to the current viewport dimensions.
void changeMatrix();

Expand Down Expand Up @@ -190,7 +174,6 @@ class Painter : private util::noncopyable {
gl::Config config;

RenderPass pass = RenderPass::Opaque;
Color background = {{ 0, 0, 0, 0 }};

int numSublayers = 3;
GLsizei currentLayer;
Expand Down
82 changes: 82 additions & 0 deletions src/mbgl/style/style.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#include <mbgl/style/style.hpp>
#include <mbgl/map/map_data.hpp>
#include <mbgl/map/source.hpp>
#include <mbgl/map/tile.hpp>
#include <mbgl/map/transform_state.hpp>
#include <mbgl/layer/symbol_layer.hpp>
#include <mbgl/sprite/sprite_store.hpp>
Expand All @@ -16,6 +17,8 @@
#include <mbgl/geometry/line_atlas.hpp>
#include <mbgl/util/constants.hpp>
#include <mbgl/platform/log.hpp>
#include <mbgl/layer/background_layer.hpp>

#include <csscolorparser/csscolorparser.hpp>

#include <rapidjson/document.h>
Expand Down Expand Up @@ -220,6 +223,85 @@ bool Style::isLoaded() const {
return true;
}

RenderData Style::getRenderData() const {
RenderData result;

for (const auto& source : sources) {
if (source->enabled) {
result.sources.insert(source.get());
}
}

for (const auto& layer : layers) {
if (layer->visibility == VisibilityType::None)
continue;

if (const BackgroundLayer* background = dynamic_cast<const BackgroundLayer*>(layer.get())) {
if (background->paint.pattern.value.from.empty()) {
// This is a solid background. We can use glClear().
result.backgroundColor = background->paint.color;
result.backgroundColor[0] *= background->paint.opacity;
result.backgroundColor[1] *= background->paint.opacity;
result.backgroundColor[2] *= background->paint.opacity;
result.backgroundColor[3] *= background->paint.opacity;
} else {
// This is a textured background. We need to render it with a quad.
result.order.emplace_back(*layer);
}
continue;
}

Source* source = getSource(layer->source);
if (!source) {
Log::Warning(Event::Render, "can't find source for layer '%s'", layer->id.c_str());
continue;
}

for (auto tile : source->getTiles()) {
if (!tile->data || !tile->data->isReady())
continue;

// We're not clipping symbol layers, so when we have both parents and children of symbol
// layers, we drop all children in favor of their parent to avoid duplicate labels.
// See https://github.com/mapbox/mapbox-gl-native/issues/2482
if (layer->type == StyleLayerType::Symbol) {
bool skip = false;
// Look back through the buckets we decided to render to find out whether there is
// already a bucket from this layer that is a parent of this tile. Tiles are ordered
// by zoom level when we obtain them from getTiles().
for (auto it = result.order.rbegin(); it != result.order.rend() && (&it->layer == layer.get()); ++it) {
if (tile->id.isChildOf(it->tile->id)) {
skip = true;
break;
}
}
if (skip) {
continue;
}
}

auto bucket = tile->data->getBucket(*layer);
if (bucket) {
result.order.emplace_back(*layer, tile, bucket);
}
}
}

return result;
}

void Style::setSourceTileCacheSize(size_t size) {
for (const auto& source : sources) {
source->setCacheSize(size);
}
}

void Style::onLowMemory() {
for (const auto& source : sources) {
source->onLowMemory();
}
}

void Style::setObserver(Observer* observer_) {
assert(util::ThreadContext::currentlyOn(util::ThreadType::Map));
assert(!observer);
Expand Down
28 changes: 27 additions & 1 deletion src/mbgl/style/style.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,27 @@ class StyleLayer;
class TransformState;
class TexturePool;

class Tile;
class Bucket;

struct RenderItem {
inline RenderItem(const StyleLayer& layer_,
const Tile* tile_ = nullptr,
Bucket* bucket_ = nullptr)
: tile(tile_), bucket(bucket_), layer(layer_) {
}

const Tile* const tile;
Bucket* const bucket;
const StyleLayer& layer;
};

struct RenderData {
Color backgroundColor = {{ 0, 0, 0, 0 }};
std::set<Source*> sources;
std::vector<RenderItem> order;
};

class Style : public GlyphStore::Observer,
public SpriteStore::Observer,
public Source::Observer,
Expand Down Expand Up @@ -73,6 +94,11 @@ class Style : public GlyphStore::Observer,
void addLayer(std::unique_ptr<StyleLayer>, const std::string& beforeLayerID);
void removeLayer(const std::string& layerID);

RenderData getRenderData() const;

void setSourceTileCacheSize(size_t);
void onLowMemory();

void dumpDebugLogs() const;

MapData& data;
Expand All @@ -82,10 +108,10 @@ class Style : public GlyphStore::Observer,
std::unique_ptr<SpriteAtlas> spriteAtlas;
std::unique_ptr<LineAtlas> lineAtlas;

private:
std::vector<std::unique_ptr<Source>> sources;
std::vector<std::unique_ptr<StyleLayer>> layers;

private:
std::vector<std::unique_ptr<StyleLayer>>::const_iterator findLayer(const std::string& layerID) const;

// GlyphStore::Observer implementation.
Expand Down

0 comments on commit b767404

Please sign in to comment.