Allow setting frustum offset to not render edges of the screen (#3676)
Co-authored-by: Bart Louwers <bart@emeel.net>
This commit is contained in:
@@ -639,6 +639,7 @@ MLN_CORE_HEADERS = [
|
||||
"include/mbgl/gfx/stencil_mode.hpp",
|
||||
"include/mbgl/gfx/types.hpp",
|
||||
"include/mbgl/gfx/vertex_buffer.hpp",
|
||||
"include/mbgl/gfx/scissor_rect.hpp",
|
||||
"include/mbgl/i18n/collator.hpp",
|
||||
"include/mbgl/i18n/number_format.hpp",
|
||||
"include/mbgl/layermanager/background_layer_factory.hpp",
|
||||
|
||||
21
include/mbgl/gfx/scissor_rect.hpp
Normal file
21
include/mbgl/gfx/scissor_rect.hpp
Normal file
@@ -0,0 +1,21 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
namespace mbgl {
|
||||
namespace gfx {
|
||||
|
||||
class ScissorRect {
|
||||
public:
|
||||
int32_t x;
|
||||
int32_t y;
|
||||
uint32_t width;
|
||||
uint32_t height;
|
||||
|
||||
bool operator==(const ScissorRect& other) const = default;
|
||||
|
||||
bool operator!=(const ScissorRect& other) const = default;
|
||||
};
|
||||
|
||||
} // namespace gfx
|
||||
} // namespace mbgl
|
||||
@@ -45,7 +45,7 @@ protected:
|
||||
/// It sets the internal assumed state to the supplied values.
|
||||
void assumeFramebufferBinding(FramebufferID fbo);
|
||||
void assumeViewport(int32_t x, int32_t y, const Size&);
|
||||
void assumeScissorTest(bool);
|
||||
void assumeScissorTest(int32_t, int32_t, uint32_t, uint32_t);
|
||||
|
||||
/// Returns true when assumed framebuffer binding hasn't changed from the implicit binding.
|
||||
bool implicitFramebufferBound();
|
||||
@@ -55,7 +55,7 @@ public:
|
||||
/// match the supplied values.
|
||||
void setFramebufferBinding(FramebufferID fbo);
|
||||
void setViewport(int32_t x, int32_t y, const Size&);
|
||||
void setScissorTest(bool);
|
||||
void setScissorTest(int32_t, int32_t, uint32_t, uint32_t);
|
||||
};
|
||||
|
||||
} // namespace gl
|
||||
|
||||
@@ -107,6 +107,8 @@ public:
|
||||
void setConstrainMode(ConstrainMode);
|
||||
void setViewportMode(ViewportMode);
|
||||
void setSize(Size);
|
||||
void setFrustumOffset(const EdgeInsets&);
|
||||
EdgeInsets getFrustumOffset();
|
||||
MapOptions getMapOptions() const;
|
||||
|
||||
// Projection Mode
|
||||
|
||||
@@ -62,6 +62,7 @@ public:
|
||||
|
||||
void setCullMode(const MTL::CullMode);
|
||||
void setFrontFacingWinding(const MTL::Winding);
|
||||
void setScissorRect(const MTL::ScissorRect);
|
||||
|
||||
private:
|
||||
void pushDebugGroup(const char* name) override;
|
||||
@@ -92,6 +93,10 @@ private:
|
||||
|
||||
MTL::CullMode currentCullMode = MTL::CullModeNone;
|
||||
MTL::Winding currentWinding = MTL::WindingClockwise;
|
||||
MTL::ScissorRect currentScissorRect;
|
||||
|
||||
size_t width;
|
||||
size_t height;
|
||||
};
|
||||
|
||||
} // namespace mtl
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
#include <mbgl/gfx/cull_face_mode.hpp>
|
||||
#include <mbgl/gfx/depth_mode.hpp>
|
||||
#include <mbgl/gfx/stencil_mode.hpp>
|
||||
#include <mbgl/gfx/scissor_rect.hpp>
|
||||
|
||||
namespace mbgl {
|
||||
namespace vulkan {
|
||||
@@ -44,6 +45,7 @@ public:
|
||||
// external values (used in hash)
|
||||
vk::RenderPass renderPass{};
|
||||
vk::Extent2D viewExtent{};
|
||||
vk::Rect2D scissorRect{};
|
||||
|
||||
// dynamic values (not part of the pipeline/ignored in hash)
|
||||
struct {
|
||||
@@ -67,6 +69,7 @@ public:
|
||||
static vk::CompareOp vulkanCompareOp(const gfx::DepthFunctionType& value);
|
||||
static vk::CompareOp vulkanCompareOp(const gfx::StencilFunctionType& value);
|
||||
static vk::StencilOp vulkanStencilOp(const gfx::StencilOpType& value);
|
||||
static vk::Rect2D vulkanScissorRect(const gfx::ScissorRect& value);
|
||||
|
||||
void setCullMode(const gfx::CullFaceMode& value);
|
||||
void setDrawMode(const gfx::DrawModeType& value);
|
||||
@@ -78,6 +81,7 @@ public:
|
||||
void setStencilMode(const gfx::StencilMode& value);
|
||||
void setRenderable(const gfx::Renderable& value);
|
||||
void setLineWidth(float value);
|
||||
void setScissorRect(const gfx::ScissorRect& value);
|
||||
|
||||
bool usesBlendConstants() const;
|
||||
void updateVertexInputHash();
|
||||
|
||||
@@ -1320,6 +1320,14 @@ void NativeMapView::enableRenderingStatsView(JNIEnv&, jni::jboolean value) {
|
||||
map->enableRenderingStatsView(value);
|
||||
}
|
||||
|
||||
void NativeMapView::setFrustumOffset(JNIEnv& env, const jni::Object<RectF>& padding) {
|
||||
mbgl::EdgeInsets offset = {RectF::getTop(env, padding),
|
||||
RectF::getLeft(env, padding),
|
||||
RectF::getBottom(env, padding),
|
||||
RectF::getRight(env, padding)};
|
||||
map->setFrustumOffset(offset);
|
||||
}
|
||||
|
||||
// Static methods //
|
||||
|
||||
void NativeMapView::registerNative(jni::JNIEnv& env) {
|
||||
@@ -1442,7 +1450,8 @@ void NativeMapView::registerNative(jni::JNIEnv& env) {
|
||||
METHOD(&NativeMapView::getTileLodZoomShift, "nativeGetTileLodZoomShift"),
|
||||
METHOD(&NativeMapView::triggerRepaint, "nativeTriggerRepaint"),
|
||||
METHOD(&NativeMapView::isRenderingStatsViewEnabled, "nativeIsRenderingStatsViewEnabled"),
|
||||
METHOD(&NativeMapView::enableRenderingStatsView, "nativeEnableRenderingStatsView"));
|
||||
METHOD(&NativeMapView::enableRenderingStatsView, "nativeEnableRenderingStatsView"),
|
||||
METHOD(&NativeMapView::setFrustumOffset, "nativeSetFrustumOffset"));
|
||||
}
|
||||
|
||||
void NativeMapView::onRegisterShaders(gfx::ShaderRegistry&) {};
|
||||
|
||||
@@ -325,6 +325,8 @@ public:
|
||||
jni::jboolean isRenderingStatsViewEnabled(JNIEnv&);
|
||||
void enableRenderingStatsView(JNIEnv&, jni::jboolean);
|
||||
|
||||
void setFrustumOffset(JNIEnv&, const jni::Object<RectF>&);
|
||||
|
||||
// Shader compilation
|
||||
void onRegisterShaders(mbgl::gfx::ShaderRegistry&) override;
|
||||
void onPreCompileShader(mbgl::shaders::BuiltIn, mbgl::gfx::Backend::Type, const std::string&) override;
|
||||
|
||||
@@ -117,6 +117,18 @@ public final class MapLibreMap {
|
||||
nativeMapView.enableRenderingStatsView(value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Frustum offset used to disable rendering of elements at the edge of the screen
|
||||
*
|
||||
* Offset applied to camera frustum and scissor rectangle. The camrea frustum is modified
|
||||
* to avoid loading geometry that's behind UI elements at the top of the screen. The scissor
|
||||
* rectangle is used to avoid shading fragments that are behind UI elements at the edges of
|
||||
* the screen. All values are in logical pixels.
|
||||
*/
|
||||
public void setFrustumOffset(@NonNull RectF offset) {
|
||||
nativeMapView.setFrustumOffset(offset);
|
||||
}
|
||||
|
||||
public void setSwapBehaviorFlush(boolean flush) {
|
||||
nativeMapView.setSwapBehaviorFlush(flush);
|
||||
}
|
||||
|
||||
@@ -270,6 +270,8 @@ interface NativeMap {
|
||||
|
||||
void enableRenderingStatsView(boolean value);
|
||||
|
||||
void setFrustumOffset(RectF offset);
|
||||
|
||||
void setSwapBehaviorFlush(boolean flush);
|
||||
|
||||
//
|
||||
|
||||
@@ -1149,6 +1149,14 @@ final class NativeMapView implements NativeMap {
|
||||
nativeEnableRenderingStatsView(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setFrustumOffset(RectF offset) {
|
||||
if (checkState("setFrustumOffset")) {
|
||||
return;
|
||||
}
|
||||
nativeSetFrustumOffset(offset);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSwapBehaviorFlush(boolean flush) {
|
||||
mapRenderer.setSwapBehaviorFlush(flush);
|
||||
@@ -1746,6 +1754,9 @@ final class NativeMapView implements NativeMap {
|
||||
@Keep
|
||||
private native void nativeEnableRenderingStatsView(boolean enabled);
|
||||
|
||||
@Keep
|
||||
private native void nativeSetFrustumOffset(RectF offsset);
|
||||
|
||||
//
|
||||
// Snapshot
|
||||
//
|
||||
|
||||
@@ -497,6 +497,44 @@ class MapLibreMapTest : EspressoTest() {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testSetFrustumOffset() {
|
||||
validateTestSetup()
|
||||
rule.runOnUiThread {
|
||||
// RectF(left, top, right, bottom) - frustum offset represents insets in pixels
|
||||
val offset = android.graphics.RectF(20f, 50f, 30f, 40f)
|
||||
maplibreMap.setFrustumOffset(offset)
|
||||
// Verify that setFrustumOffset was called without throwing an exception
|
||||
// Since there's no getter, we can only verify it doesn't crash
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testSetFrustumOffsetZero() {
|
||||
validateTestSetup()
|
||||
rule.runOnUiThread {
|
||||
val zeroOffset = android.graphics.RectF(0f, 0f, 0f, 0f)
|
||||
maplibreMap.setFrustumOffset(zeroOffset)
|
||||
// Verify that setFrustumOffset with zero values works
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testSetFrustumOffsetMultipleChanges() {
|
||||
validateTestSetup()
|
||||
rule.runOnUiThread {
|
||||
val firstOffset = android.graphics.RectF(10f, 20f, 30f, 40f)
|
||||
maplibreMap.setFrustumOffset(firstOffset)
|
||||
|
||||
val secondOffset = android.graphics.RectF(100f, 200f, 300f, 400f)
|
||||
maplibreMap.setFrustumOffset(secondOffset)
|
||||
|
||||
val zeroOffset = android.graphics.RectF(0f, 0f, 0f, 0f)
|
||||
maplibreMap.setFrustumOffset(zeroOffset)
|
||||
// Verify that multiple changes to frustum offset work correctly
|
||||
}
|
||||
}
|
||||
|
||||
@Deprecated("remove this class when removing deprecated annotations")
|
||||
inner class MapLibreMapAction internal constructor(private val invokeViewAction: InvokeViewAction) : ViewAction {
|
||||
override fun getConstraints(): Matcher<View> {
|
||||
|
||||
@@ -24,7 +24,7 @@ public:
|
||||
|
||||
void bind() override {
|
||||
context.bindFramebuffer = framebuffer.framebuffer;
|
||||
context.scissorTest = false;
|
||||
context.scissorTest = {0, 0, 0, 0};
|
||||
context.viewport = {0, 0, framebuffer.size};
|
||||
}
|
||||
|
||||
|
||||
@@ -532,6 +532,16 @@ MLN_EXPORT
|
||||
*/
|
||||
@property (nonatomic, assign) double tileLodZoomShift;
|
||||
|
||||
/**
|
||||
Frustum offset used to disable rendering of elements at the edge of the screen
|
||||
|
||||
Offset applied to camera frustum and scissor rectangle. The camrea frustum is modified
|
||||
to avoid loading geometry that's behind UI elements at the top of the screen. The scissor
|
||||
rectangle is used to avoid shading fragments that are behind UI elements at the edges of
|
||||
the screen. All values are in logical pixels.
|
||||
*/
|
||||
@property (nonatomic, assign) UIEdgeInsets frustumOffset;
|
||||
|
||||
// MARK: Displaying the User’s Location
|
||||
|
||||
/**
|
||||
|
||||
@@ -3327,6 +3327,16 @@ static void *windowScreenContext = &windowScreenContext;
|
||||
return _mbglMap->getTileLodZoomShift();
|
||||
}
|
||||
|
||||
-(void)setFrustumOffset:(UIEdgeInsets)frustomOffset
|
||||
{
|
||||
_mbglMap->setFrustumOffset(MLNEdgeInsetsFromNSEdgeInsets(frustomOffset));
|
||||
}
|
||||
|
||||
-(UIEdgeInsets)frustumOffset
|
||||
{
|
||||
return NSEdgeInsetsFromMLNEdgeInsets(_mbglMap->getFrustumOffset());
|
||||
}
|
||||
|
||||
// MARK: - Accessibility -
|
||||
|
||||
- (NSString *)accessibilityValue
|
||||
|
||||
97
platform/ios/test/MLNMapViewFrustumOffsetTests.m
Normal file
97
platform/ios/test/MLNMapViewFrustumOffsetTests.m
Normal file
@@ -0,0 +1,97 @@
|
||||
#import <Mapbox.h>
|
||||
#import <XCTest/XCTest.h>
|
||||
|
||||
@interface MLNMapViewFrustumOffsetTests : XCTestCase <MLNMapViewDelegate>
|
||||
|
||||
@property (nonatomic) MLNMapView *mapView;
|
||||
@property (nonatomic) XCTestExpectation *styleLoadingExpectation;
|
||||
|
||||
@end
|
||||
|
||||
@implementation MLNMapViewFrustumOffsetTests
|
||||
|
||||
- (void)setUp {
|
||||
[super setUp];
|
||||
|
||||
NSURL *styleURL = [[NSBundle bundleForClass:[self class]] URLForResource:@"one-liner" withExtension:@"json"];
|
||||
self.mapView = [[MLNMapView alloc] initWithFrame:CGRectMake(0, 0, 400, 400) styleURL:styleURL];
|
||||
self.mapView.delegate = self;
|
||||
|
||||
if (!self.mapView.style) {
|
||||
_styleLoadingExpectation = [self expectationWithDescription:@"Map view should finish loading style."];
|
||||
[self waitForExpectationsWithTimeout:10 handler:nil];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)mapView:(MLNMapView *)mapView didFinishLoadingStyle:(MLNStyle *)style {
|
||||
XCTAssertNotNil(mapView.style);
|
||||
XCTAssertEqual(mapView.style, style);
|
||||
|
||||
[_styleLoadingExpectation fulfill];
|
||||
}
|
||||
|
||||
- (void)tearDown {
|
||||
self.mapView = nil;
|
||||
[super tearDown];
|
||||
}
|
||||
|
||||
- (void)testFrustumOffsetGetterSetter {
|
||||
// Test default value (should be UIEdgeInsetsZero)
|
||||
UIEdgeInsets defaultOffset = self.mapView.frustumOffset;
|
||||
XCTAssertEqual(defaultOffset.top, 0.0);
|
||||
XCTAssertEqual(defaultOffset.left, 0.0);
|
||||
XCTAssertEqual(defaultOffset.bottom, 0.0);
|
||||
XCTAssertEqual(defaultOffset.right, 0.0);
|
||||
|
||||
// Test setting a non-zero offset
|
||||
UIEdgeInsets testOffset = UIEdgeInsetsMake(50.0, 40.0, 30.0, 20.0);
|
||||
self.mapView.frustumOffset = testOffset;
|
||||
|
||||
UIEdgeInsets retrievedOffset = self.mapView.frustumOffset;
|
||||
XCTAssertEqualWithAccuracy(retrievedOffset.top, testOffset.top, 0.01);
|
||||
XCTAssertEqualWithAccuracy(retrievedOffset.left, testOffset.left, 0.01);
|
||||
XCTAssertEqualWithAccuracy(retrievedOffset.bottom, testOffset.bottom, 0.01);
|
||||
XCTAssertEqualWithAccuracy(retrievedOffset.right, testOffset.right, 0.01);
|
||||
}
|
||||
|
||||
- (void)testFrustumOffsetZeroInsets {
|
||||
// Test setting zero insets
|
||||
UIEdgeInsets zeroOffset = UIEdgeInsetsZero;
|
||||
self.mapView.frustumOffset = zeroOffset;
|
||||
|
||||
UIEdgeInsets retrievedOffset = self.mapView.frustumOffset;
|
||||
XCTAssertEqual(retrievedOffset.top, 0.0);
|
||||
XCTAssertEqual(retrievedOffset.left, 0.0);
|
||||
XCTAssertEqual(retrievedOffset.bottom, 0.0);
|
||||
XCTAssertEqual(retrievedOffset.right, 0.0);
|
||||
}
|
||||
|
||||
- (void)testFrustumOffsetMultipleChanges {
|
||||
// Test changing the offset multiple times
|
||||
UIEdgeInsets firstOffset = UIEdgeInsetsMake(10.0, 20.0, 30.0, 40.0);
|
||||
self.mapView.frustumOffset = firstOffset;
|
||||
UIEdgeInsets retrievedOffset = self.mapView.frustumOffset;
|
||||
XCTAssertEqualWithAccuracy(retrievedOffset.top, 10.0, 0.01);
|
||||
XCTAssertEqualWithAccuracy(retrievedOffset.left, 20.0, 0.01);
|
||||
XCTAssertEqualWithAccuracy(retrievedOffset.bottom, 30.0, 0.01);
|
||||
XCTAssertEqualWithAccuracy(retrievedOffset.right, 40.0, 0.01);
|
||||
|
||||
UIEdgeInsets secondOffset = UIEdgeInsetsMake(100.0, 200.0, 300.0, 400.0);
|
||||
self.mapView.frustumOffset = secondOffset;
|
||||
retrievedOffset = self.mapView.frustumOffset;
|
||||
XCTAssertEqualWithAccuracy(retrievedOffset.top, 100.0, 0.01);
|
||||
XCTAssertEqualWithAccuracy(retrievedOffset.left, 200.0, 0.01);
|
||||
XCTAssertEqualWithAccuracy(retrievedOffset.bottom, 300.0, 0.01);
|
||||
XCTAssertEqualWithAccuracy(retrievedOffset.right, 400.0, 0.01);
|
||||
|
||||
// Test setting back to zero
|
||||
UIEdgeInsets zeroOffset = UIEdgeInsetsZero;
|
||||
self.mapView.frustumOffset = zeroOffset;
|
||||
retrievedOffset = self.mapView.frustumOffset;
|
||||
XCTAssertEqual(retrievedOffset.top, 0.0);
|
||||
XCTAssertEqual(retrievedOffset.left, 0.0);
|
||||
XCTAssertEqual(retrievedOffset.bottom, 0.0);
|
||||
XCTAssertEqual(retrievedOffset.right, 0.0);
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -463,6 +463,7 @@ void Context::resetState(gfx::DepthMode depthMode, gfx::ColorMode colorMode) {
|
||||
setStencilMode(gfx::StencilMode::disabled());
|
||||
setColorMode(colorMode);
|
||||
setCullFaceMode(gfx::CullFaceMode::disabled());
|
||||
setScissorTest({0, 0, 0, 0});
|
||||
}
|
||||
|
||||
bool Context::emplaceOrUpdateUniformBuffer(gfx::UniformBufferPtr& buffer,
|
||||
@@ -495,7 +496,7 @@ void Context::unbindGlobalUniformBuffers(gfx::RenderPass&) const noexcept {
|
||||
void Context::setDirtyState() {
|
||||
MLN_TRACE_FUNC();
|
||||
|
||||
// Note: does not set viewport/scissorTest/bindFramebuffer to dirty
|
||||
// Note: does not set viewport/bindFramebuffer to dirty
|
||||
// since they are handled separately in the view object.
|
||||
stencilFunc.setDirty();
|
||||
stencilMask.setDirty();
|
||||
@@ -518,6 +519,7 @@ void Context::setDirtyState() {
|
||||
cullFace.setDirty();
|
||||
cullFaceSide.setDirty();
|
||||
cullFaceWinding.setDirty();
|
||||
scissorTest.setDirty();
|
||||
program.setDirty();
|
||||
lineWidth.setDirty();
|
||||
activeTextureUnit.setDirty();
|
||||
@@ -642,6 +644,10 @@ void Context::setCullFaceMode(const gfx::CullFaceMode& mode) {
|
||||
cullFaceWinding = mode.winding;
|
||||
}
|
||||
|
||||
void Context::setScissorTest(const gfx::ScissorRect& rect) {
|
||||
scissorTest = rect;
|
||||
}
|
||||
|
||||
void Context::setDepthMode(const gfx::DepthMode& depth) {
|
||||
if (depth.func == gfx::DepthFunctionType::Always && depth.mask != gfx::DepthMaskType::ReadWrite) {
|
||||
depthTest = false;
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
#include <mbgl/gfx/stencil_mode.hpp>
|
||||
#include <mbgl/gfx/color_mode.hpp>
|
||||
#include <mbgl/gfx/context.hpp>
|
||||
#include <mbgl/gfx/scissor_rect.hpp>
|
||||
#include <mbgl/gl/object.hpp>
|
||||
#include <mbgl/gl/state.hpp>
|
||||
#include <mbgl/gl/value.hpp>
|
||||
@@ -77,6 +78,7 @@ public:
|
||||
void setStencilMode(const gfx::StencilMode&);
|
||||
void setColorMode(const gfx::ColorMode&);
|
||||
void setCullFaceMode(const gfx::CullFaceMode&);
|
||||
void setScissorTest(const gfx::ScissorRect&);
|
||||
|
||||
void draw(const gfx::DrawMode&, std::size_t indexOffset, std::size_t indexLength);
|
||||
|
||||
|
||||
@@ -60,6 +60,8 @@ void DrawableGL::draw(PaintParameters& parameters) const {
|
||||
context.setColorMode(getColorMode());
|
||||
context.setCullFaceMode(getCullFaceMode());
|
||||
|
||||
context.setScissorTest(parameters.scissorRect);
|
||||
|
||||
impl->uniformBuffers.bind();
|
||||
bindTextures();
|
||||
|
||||
|
||||
@@ -33,7 +33,7 @@ public:
|
||||
}
|
||||
|
||||
context.activeTextureUnit = 0;
|
||||
context.scissorTest = false;
|
||||
context.scissorTest = {0, 0, 0, 0};
|
||||
context.viewport = {.x = 0, .y = 0, .size = size};
|
||||
}
|
||||
|
||||
|
||||
@@ -53,10 +53,10 @@ void RendererBackend::assumeViewport(int32_t x, int32_t y, const Size& size) {
|
||||
assert(gl::value::Viewport::Get() == getContext<gl::Context>().viewport.getCurrentValue());
|
||||
}
|
||||
|
||||
void RendererBackend::assumeScissorTest(bool enabled) {
|
||||
void RendererBackend::assumeScissorTest(int32_t x, int32_t y, uint32_t width, uint32_t height) {
|
||||
MLN_TRACE_FUNC();
|
||||
|
||||
getContext<gl::Context>().scissorTest.setCurrentValue(enabled);
|
||||
getContext<gl::Context>().scissorTest.setCurrentValue({x, y, width, height});
|
||||
assert(gl::value::ScissorTest::Get() == getContext<gl::Context>().scissorTest.getCurrentValue());
|
||||
}
|
||||
|
||||
@@ -82,10 +82,10 @@ void RendererBackend::setViewport(int32_t x, int32_t y, const Size& size) {
|
||||
assert(gl::value::Viewport::Get() == getContext<gl::Context>().viewport.getCurrentValue());
|
||||
}
|
||||
|
||||
void RendererBackend::setScissorTest(bool enabled) {
|
||||
void RendererBackend::setScissorTest(int32_t x, int32_t y, uint32_t width, uint32_t height) {
|
||||
MLN_TRACE_FUNC();
|
||||
|
||||
getContext<gl::Context>().scissorTest = enabled;
|
||||
getContext<gl::Context>().scissorTest = {x, y, width, height};
|
||||
assert(gl::value::ScissorTest::Get() == getContext<gl::Context>().scissorTest.getCurrentValue());
|
||||
}
|
||||
|
||||
|
||||
@@ -358,15 +358,17 @@ const constexpr ScissorTest::Type ScissorTest::Default;
|
||||
void ScissorTest::Set(const Type& value) {
|
||||
MLN_TRACE_ZONE(ScissorTest::Set);
|
||||
MLN_TRACE_FUNC_GL();
|
||||
MBGL_CHECK_ERROR(value ? glEnable(GL_SCISSOR_TEST) : glDisable(GL_SCISSOR_TEST));
|
||||
bool enabled = value.x != 0 || value.y != 0 || value.width != 0 || value.height != 0;
|
||||
MBGL_CHECK_ERROR(enabled ? glEnable(GL_SCISSOR_TEST) : glDisable(GL_SCISSOR_TEST));
|
||||
MBGL_CHECK_ERROR(glScissor(value.x, value.y, value.width, value.height));
|
||||
}
|
||||
|
||||
ScissorTest::Type ScissorTest::Get() {
|
||||
MLN_TRACE_ZONE(ScissorTest::Get);
|
||||
MLN_TRACE_FUNC_GL();
|
||||
Type scissorTest;
|
||||
MBGL_CHECK_ERROR(scissorTest = glIsEnabled(GL_SCISSOR_TEST));
|
||||
return scissorTest;
|
||||
GLint scissor[4];
|
||||
MBGL_CHECK_ERROR(glGetIntegerv(GL_SCISSOR_BOX, scissor));
|
||||
return {scissor[0], scissor[1], static_cast<uint32_t>(scissor[2]), static_cast<uint32_t>(scissor[3])};
|
||||
}
|
||||
|
||||
const constexpr BindFramebuffer::Type BindFramebuffer::Default;
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
#include <mbgl/gfx/stencil_mode.hpp>
|
||||
#include <mbgl/gfx/color_mode.hpp>
|
||||
#include <mbgl/gfx/cull_face_mode.hpp>
|
||||
#include <mbgl/gfx/scissor_rect.hpp>
|
||||
#include <mbgl/gl/attribute.hpp>
|
||||
#include <mbgl/platform/gl_functions.hpp>
|
||||
#include <mbgl/util/color.hpp>
|
||||
@@ -189,8 +190,8 @@ struct Viewport {
|
||||
};
|
||||
|
||||
struct ScissorTest {
|
||||
using Type = bool;
|
||||
static const constexpr Type Default = false;
|
||||
using Type = gfx::ScissorRect;
|
||||
static const constexpr Type Default = {0, 0, 0, 0};
|
||||
static void Set(const Type&);
|
||||
static Type Get();
|
||||
};
|
||||
|
||||
@@ -375,6 +375,15 @@ void Map::setSize(const Size size) {
|
||||
impl->onUpdate();
|
||||
}
|
||||
|
||||
void Map::setFrustumOffset(const EdgeInsets& frustumOffset) {
|
||||
impl->transform.setFrustumOffset(frustumOffset);
|
||||
impl->onUpdate();
|
||||
}
|
||||
|
||||
EdgeInsets Map::getFrustumOffset() {
|
||||
return impl->transform.getFrustumOffset();
|
||||
}
|
||||
|
||||
void Map::setNorthOrientation(NorthOrientation orientation) {
|
||||
impl->transform.setNorthOrientation(orientation);
|
||||
impl->onUpdate();
|
||||
|
||||
@@ -432,6 +432,14 @@ void Transform::setMaxPitch(const double maxPitch) {
|
||||
state.setMaxPitch(util::deg2rad(maxPitch));
|
||||
}
|
||||
|
||||
void Transform::setFrustumOffset(const EdgeInsets& frustumOffset) {
|
||||
state.setFrustumOffset(frustumOffset);
|
||||
}
|
||||
|
||||
EdgeInsets Transform::getFrustumOffset() {
|
||||
return state.getFrustumOffset();
|
||||
}
|
||||
|
||||
// MARK: - Bearing
|
||||
|
||||
void Transform::rotateBy(const ScreenCoordinate& first,
|
||||
|
||||
@@ -132,6 +132,10 @@ public:
|
||||
FreeCameraOptions getFreeCameraOptions() const;
|
||||
void setFreeCameraOptions(const FreeCameraOptions& options);
|
||||
|
||||
// Frustum
|
||||
void setFrustumOffset(const EdgeInsets&);
|
||||
EdgeInsets getFrustumOffset();
|
||||
|
||||
private:
|
||||
TransformObserver& observer;
|
||||
TransformState state;
|
||||
|
||||
@@ -88,6 +88,9 @@ void TransformState::setProperties(const TransformStateProperties& properties) {
|
||||
if (properties.viewPortMode) {
|
||||
setViewportMode(*properties.viewPortMode);
|
||||
}
|
||||
if (properties.frustumOffset) {
|
||||
setFrustumOffset(*properties.frustumOffset);
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Matrix
|
||||
@@ -120,7 +123,8 @@ void TransformState::getProjMatrix(mat4& projMatrix, uint16_t nearZ, bool aligne
|
||||
// (the distance between[width/2, height/2] and [width/2 + 1, height/2])
|
||||
// See https://github.com/mapbox/mapbox-gl-native/pull/15195 for details.
|
||||
// See TransformState::fov description: fov = 2 * arctan((height / 2) / (height * 1.5)).
|
||||
const double tanFovAboveCenter = (size.height * 0.5 + offset.y) / (size.height * 1.5);
|
||||
const double tanFovAboveCenter =
|
||||
((size.height - frustumOffset.top()) * 0.5 + (offset.y - (frustumOffset.top() / 2))) / (size.height * 1.5);
|
||||
const double tanMultiple = tanFovAboveCenter * std::tan(getPitch());
|
||||
assert(tanMultiple < 1);
|
||||
// Calculate z distance of the farthest fragment that should be rendered.
|
||||
@@ -372,6 +376,17 @@ void TransformState::setSize(const Size& size_) {
|
||||
}
|
||||
}
|
||||
|
||||
EdgeInsets TransformState::getFrustumOffset() const {
|
||||
return frustumOffset;
|
||||
}
|
||||
|
||||
void TransformState::setFrustumOffset(const EdgeInsets& frustumOffset_) {
|
||||
if (frustumOffset != frustumOffset_) {
|
||||
frustumOffset = frustumOffset_;
|
||||
requestMatricesUpdate = true;
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - North Orientation
|
||||
|
||||
NorthOrientation TransformState::getNorthOrientation() const {
|
||||
|
||||
@@ -85,6 +85,10 @@ struct TransformStateProperties {
|
||||
viewPortMode = val;
|
||||
return *this;
|
||||
}
|
||||
TransformStateProperties withFrustumOffset(const std::optional<EdgeInsets>& val) {
|
||||
frustumOffset = val;
|
||||
return *this;
|
||||
}
|
||||
|
||||
std::optional<double> x;
|
||||
std::optional<double> y;
|
||||
@@ -102,6 +106,7 @@ struct TransformStateProperties {
|
||||
std::optional<ConstrainMode> constrain;
|
||||
std::optional<NorthOrientation> northOrientation;
|
||||
std::optional<ViewportMode> viewPortMode;
|
||||
std::optional<EdgeInsets> frustumOffset;
|
||||
};
|
||||
|
||||
class TransformState {
|
||||
@@ -118,6 +123,9 @@ public:
|
||||
Size getSize() const;
|
||||
void setSize(const Size& size_);
|
||||
|
||||
EdgeInsets getFrustumOffset() const;
|
||||
void setFrustumOffset(const EdgeInsets& frustumOffset_);
|
||||
|
||||
// North Orientation
|
||||
NorthOrientation getNorthOrientation() const;
|
||||
double getNorthOrientationAngle() const;
|
||||
@@ -246,6 +254,7 @@ private:
|
||||
|
||||
// logical dimensions
|
||||
Size size;
|
||||
EdgeInsets frustumOffset;
|
||||
|
||||
mat4 coordinatePointMatrix(const mat4& projMatrix) const;
|
||||
mat4 getPixelMatrix() const;
|
||||
|
||||
@@ -121,6 +121,10 @@ MTL::Winding mapWindingMode(const gfx::CullFaceWindingType mode) noexcept {
|
||||
}
|
||||
}
|
||||
|
||||
MTL::ScissorRect getMetalScissorRect(gfx::ScissorRect rect) noexcept {
|
||||
return {static_cast<uint32_t>(rect.x), static_cast<uint32_t>(rect.y), rect.width, rect.height};
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
void Drawable::setColorMode(const gfx::ColorMode& value) {
|
||||
@@ -215,6 +219,8 @@ void Drawable::draw(PaintParameters& parameters) const {
|
||||
renderPass.setCullMode(cullMode.enabled ? mapCullMode(cullMode.side) : MTL::CullModeNone);
|
||||
renderPass.setFrontFacingWinding(mapWindingMode(cullMode.winding));
|
||||
|
||||
renderPass.setScissorRect(getMetalScissorRect(parameters.scissorRect));
|
||||
|
||||
if (!impl->pipelineState) {
|
||||
impl->pipelineState = shaderMTL.getRenderPipelineState(
|
||||
renderable,
|
||||
|
||||
@@ -30,6 +30,10 @@ RenderPass::RenderPass(CommandEncoder& commandEncoder_, const char* name, const
|
||||
}
|
||||
}
|
||||
encoder = NS::RetainPtr(buffer->renderCommandEncoder(rpd.get()));
|
||||
|
||||
const auto& texture = rpd->colorAttachments()->object(0)->texture();
|
||||
width = texture->width();
|
||||
height = texture->height();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -78,6 +82,7 @@ void RenderPass::resetState() {
|
||||
|
||||
currentCullMode = MTL::CullModeNone;
|
||||
currentWinding = MTL::WindingClockwise;
|
||||
currentScissorRect = {0, 0, 0, 0};
|
||||
}
|
||||
|
||||
namespace {
|
||||
@@ -216,5 +221,19 @@ void RenderPass::setFrontFacingWinding(const MTL::Winding winding) {
|
||||
}
|
||||
}
|
||||
|
||||
void RenderPass::setScissorRect(MTL::ScissorRect rect) {
|
||||
if (rect.x != currentScissorRect.x || rect.y != currentScissorRect.y || rect.width != currentScissorRect.width ||
|
||||
rect.height != currentScissorRect.height) {
|
||||
if (rect.width + rect.x > width) {
|
||||
rect.width = width - rect.x;
|
||||
}
|
||||
if (rect.height + rect.y > height) {
|
||||
rect.height = height - rect.y;
|
||||
}
|
||||
encoder->setScissorRect(rect);
|
||||
currentScissorRect = rect;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace mtl
|
||||
} // namespace mbgl
|
||||
|
||||
@@ -63,7 +63,8 @@ PaintParameters::PaintParameters(gfx::Context& context_,
|
||||
uint64_t frameCount_,
|
||||
double tileLodMinRadius_,
|
||||
double tileLodScale_,
|
||||
double tileLodPitchThreshold_)
|
||||
double tileLodPitchThreshold_,
|
||||
const gfx::ScissorRect& scissorRect_)
|
||||
: context(context_),
|
||||
backend(backend_),
|
||||
encoder(context.createCommandEncoder()),
|
||||
@@ -81,7 +82,8 @@ PaintParameters::PaintParameters(gfx::Context& context_,
|
||||
frameCount(frameCount_),
|
||||
tileLodMinRadius(tileLodMinRadius_),
|
||||
tileLodScale(tileLodScale_),
|
||||
tileLodPitchThreshold(tileLodPitchThreshold_) {
|
||||
tileLodPitchThreshold(tileLodPitchThreshold_),
|
||||
scissorRect(scissorRect_) {
|
||||
pixelsToGLUnits = {{2.0f / state.getSize().width, -2.0f / state.getSize().height}};
|
||||
|
||||
if (state.getViewportMode() == ViewportMode::FlippedY) {
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
#include <mbgl/gfx/depth_mode.hpp>
|
||||
#include <mbgl/gfx/stencil_mode.hpp>
|
||||
#include <mbgl/gfx/color_mode.hpp>
|
||||
#include <mbgl/gfx/scissor_rect.hpp>
|
||||
#include <mbgl/util/mat4.hpp>
|
||||
|
||||
#include <array>
|
||||
@@ -60,7 +61,8 @@ public:
|
||||
uint64_t frameCount,
|
||||
double tileLodMinRadius,
|
||||
double tileLodScale,
|
||||
double tileLodPitchThreshold);
|
||||
double tileLodPitchThreshold,
|
||||
const gfx::ScissorRect&);
|
||||
~PaintParameters();
|
||||
|
||||
gfx::Context& context;
|
||||
@@ -137,6 +139,8 @@ public:
|
||||
double tileLodMinRadius;
|
||||
double tileLodScale;
|
||||
double tileLodPitchThreshold;
|
||||
|
||||
gfx::ScissorRect scissorRect;
|
||||
};
|
||||
|
||||
} // namespace mbgl
|
||||
|
||||
@@ -71,6 +71,10 @@ void RenderTarget::render(RenderOrchestrator& orchestrator, const RenderTree& re
|
||||
.clearDepth = {},
|
||||
.clearStencil = {}});
|
||||
|
||||
const gfx::ScissorRect prevSicssorRect = parameters.scissorRect;
|
||||
const auto& size = getTexture()->getSize();
|
||||
parameters.scissorRect = {0, 0, size.width, size.height};
|
||||
|
||||
// Run layer tweakers to update any dynamic elements
|
||||
parameters.currentLayer = 0;
|
||||
visitLayerGroups([&](LayerGroupBase& layerGroup) {
|
||||
@@ -104,6 +108,8 @@ void RenderTarget::render(RenderOrchestrator& orchestrator, const RenderTree& re
|
||||
|
||||
parameters.renderPass.reset();
|
||||
parameters.encoder->present(*offscreenTexture);
|
||||
|
||||
parameters.scissorRect = prevSicssorRect;
|
||||
}
|
||||
|
||||
} // namespace mbgl
|
||||
|
||||
@@ -184,21 +184,38 @@ void Renderer::Impl::render(const RenderTree& renderTree, const std::shared_ptr<
|
||||
|
||||
observer->onWillStartRenderingFrame();
|
||||
|
||||
PaintParameters parameters{context,
|
||||
pixelRatio,
|
||||
backend,
|
||||
renderTreeParameters.light,
|
||||
renderTreeParameters.mapMode,
|
||||
renderTreeParameters.debugOptions,
|
||||
renderTreeParameters.timePoint,
|
||||
renderTreeParameters.transformParams,
|
||||
*staticData,
|
||||
renderTree.getLineAtlas(),
|
||||
renderTree.getPatternAtlas(),
|
||||
frameCount,
|
||||
updateParameters->tileLodMinRadius,
|
||||
updateParameters->tileLodScale,
|
||||
updateParameters->tileLodPitchThreshold};
|
||||
const TransformState& state = renderTreeParameters.transformParams.state;
|
||||
const Size& size = state.getSize();
|
||||
const EdgeInsets& frustumOffset = state.getFrustumOffset();
|
||||
const gfx::ScissorRect scissorRect = {
|
||||
.x = static_cast<int32_t>(frustumOffset.left() * pixelRatio),
|
||||
#if MLN_RENDER_BACKEND_OPENGL
|
||||
.y = static_cast<int32_t>(frustumOffset.bottom() * pixelRatio),
|
||||
#else
|
||||
.y = static_cast<int32_t>(frustumOffset.top() * pixelRatio),
|
||||
#endif
|
||||
.width = static_cast<uint32_t>((size.width - (frustumOffset.left() + frustumOffset.right())) * pixelRatio),
|
||||
.height = static_cast<uint32_t>((size.height - (frustumOffset.top() + frustumOffset.bottom())) * pixelRatio),
|
||||
};
|
||||
|
||||
PaintParameters parameters{
|
||||
context,
|
||||
pixelRatio,
|
||||
backend,
|
||||
renderTreeParameters.light,
|
||||
renderTreeParameters.mapMode,
|
||||
renderTreeParameters.debugOptions,
|
||||
renderTreeParameters.timePoint,
|
||||
renderTreeParameters.transformParams,
|
||||
*staticData,
|
||||
renderTree.getLineAtlas(),
|
||||
renderTree.getPatternAtlas(),
|
||||
frameCount,
|
||||
updateParameters->tileLodMinRadius,
|
||||
updateParameters->tileLodScale,
|
||||
updateParameters->tileLodPitchThreshold,
|
||||
scissorRect,
|
||||
};
|
||||
|
||||
parameters.symbolFadeChange = renderTreeParameters.symbolFadeChange;
|
||||
parameters.opaquePassCutoff = renderTreeParameters.opaquePassCutOff;
|
||||
|
||||
@@ -560,6 +560,8 @@ bool Context::renderTileClippingMasks(gfx::RenderPass& renderPass,
|
||||
const auto& pipeline = shaderImpl.getPipeline(clipping.pipelineInfo);
|
||||
|
||||
commandBuffer->bindPipeline(vk::PipelineBindPoint::eGraphics, pipeline.get(), dispatcher);
|
||||
clipping.pipelineInfo.setScissorRect(
|
||||
{0, 0, clipping.pipelineInfo.viewExtent.width, clipping.pipelineInfo.viewExtent.height});
|
||||
clipping.pipelineInfo.setDynamicValues(backend, commandBuffer);
|
||||
|
||||
const std::array<vk::Buffer, 1> vertexBuffers = {clipping.vertexBuffer->getVulkanBuffer()};
|
||||
|
||||
@@ -298,6 +298,8 @@ void Drawable::draw(PaintParameters& parameters) const {
|
||||
// update pipeline info with per segment modifiers
|
||||
impl->pipelineInfo.setDrawMode(seg->getMode());
|
||||
|
||||
impl->pipelineInfo.setScissorRect(parameters.scissorRect);
|
||||
|
||||
impl->pipelineInfo.setDynamicValues(context.getBackend(), commandBuffer);
|
||||
|
||||
const auto& pipeline = shaderImpl.getPipeline(impl->pipelineInfo);
|
||||
|
||||
@@ -6,8 +6,6 @@
|
||||
namespace mbgl {
|
||||
namespace vulkan {
|
||||
|
||||
#define USE_DYNAMIC_VIEWPORT 0
|
||||
|
||||
vk::Format PipelineInfo::vulkanFormat(const gfx::AttributeDataType& value) {
|
||||
switch (value) {
|
||||
case gfx::AttributeDataType::Byte:
|
||||
@@ -110,6 +108,10 @@ vk::CullModeFlagBits PipelineInfo::vulkanCullMode(const gfx::CullFaceSideType& v
|
||||
}
|
||||
}
|
||||
|
||||
vk::Rect2D PipelineInfo::vulkanScissorRect(const gfx::ScissorRect& value) {
|
||||
return {{value.x, value.y}, {value.width, value.height}};
|
||||
}
|
||||
|
||||
vk::FrontFace PipelineInfo::vulkanFrontFace(const gfx::CullFaceWindingType& value) {
|
||||
switch (value) {
|
||||
default:
|
||||
@@ -245,6 +247,10 @@ void PipelineInfo::setCullMode(const gfx::CullFaceMode& value) {
|
||||
frontFace = vulkanFrontFace(value.winding);
|
||||
}
|
||||
|
||||
void PipelineInfo::setScissorRect(const gfx::ScissorRect& value) {
|
||||
scissorRect = vulkanScissorRect(value);
|
||||
}
|
||||
|
||||
void PipelineInfo::setDrawMode(const gfx::DrawModeType& value) {
|
||||
topology = vulkanPrimitiveTopology(value);
|
||||
}
|
||||
@@ -400,10 +406,6 @@ std::size_t PipelineInfo::hash() const {
|
||||
stencilDepthFail,
|
||||
wideLines,
|
||||
VkRenderPass(renderPass),
|
||||
#if !USE_DYNAMIC_VIEWPORT
|
||||
viewExtent.width,
|
||||
viewExtent.height,
|
||||
#endif
|
||||
vertexInputHash);
|
||||
}
|
||||
|
||||
@@ -424,13 +426,10 @@ void PipelineInfo::setDynamicValues(const RendererBackend& backend, const vk::Un
|
||||
buffer->setLineWidth(dynamicValues.lineWidth, dispatcher);
|
||||
}
|
||||
|
||||
#if USE_DYNAMIC_VIEWPORT
|
||||
const vk::Viewport viewport(0.0f, 0.0f, viewExtent.width, viewExtent.height, 0.0f, 1.0f);
|
||||
const vk::Rect2D scissorRect({}, {viewExtent.width, viewExtent.height});
|
||||
|
||||
buffer->setViewport(0, viewport, dispatcher);
|
||||
buffer->setScissor(0, scissorRect, dispatcher);
|
||||
#endif
|
||||
}
|
||||
|
||||
std::vector<vk::DynamicState> PipelineInfo::getDynamicStates(const RendererBackend& backend) const {
|
||||
@@ -450,10 +449,8 @@ std::vector<vk::DynamicState> PipelineInfo::getDynamicStates(const RendererBacke
|
||||
dynamicStates.push_back(vk::DynamicState::eLineWidth);
|
||||
}
|
||||
|
||||
#if USE_DYNAMIC_VIEWPORT
|
||||
dynamicStates.push_back(vk::DynamicState::eViewport);
|
||||
dynamicStates.push_back(vk::DynamicState::eScissor);
|
||||
#endif
|
||||
|
||||
return dynamicStates;
|
||||
}
|
||||
|
||||
@@ -841,6 +841,12 @@ void Drawable::draw(PaintParameters& parameters) const {
|
||||
return;
|
||||
}
|
||||
|
||||
wgpuRenderPassEncoderSetScissorRect(renderPassEncoder,
|
||||
parameters.scissorRect.x,
|
||||
parameters.scissorRect.y,
|
||||
parameters.scissorRect.width,
|
||||
parameters.scissorRect.height);
|
||||
|
||||
uint32_t bufferSlot = 0;
|
||||
for (const auto& binding : uniqueBindings) {
|
||||
if (!binding.buffer || !binding.buffer->getBuffer()) {
|
||||
|
||||
BIN
test/fixtures/map/setFrustumOffset/after/expected.png
vendored
Normal file
BIN
test/fixtures/map/setFrustumOffset/after/expected.png
vendored
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.2 KiB |
BIN
test/fixtures/map/setFrustumOffset/before/expected.png
vendored
Normal file
BIN
test/fixtures/map/setFrustumOffset/before/expected.png
vendored
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 853 B |
@@ -38,6 +38,7 @@
|
||||
#include <mbgl/util/client_options.hpp>
|
||||
#include <mbgl/util/color.hpp>
|
||||
#include <mbgl/util/image.hpp>
|
||||
#include <mbgl/util/geo.hpp>
|
||||
#include <mbgl/util/io.hpp>
|
||||
#include <mbgl/util/logging.hpp>
|
||||
#include <mbgl/util/run_loop.hpp>
|
||||
@@ -2020,3 +2021,19 @@ TEST(Map, LineLayerDepthDistribution) {
|
||||
test::checkImage(
|
||||
"test/fixtures/map/layer_depth_distribution/line", test.frontend.render(test.map).image, 0.0006, 0.1);
|
||||
}
|
||||
|
||||
TEST(Map, SetFrustumOffset) {
|
||||
MapTest<> test;
|
||||
|
||||
test.map.getStyle().loadJSON(util::read_file("test/fixtures/api/empty.json"));
|
||||
|
||||
auto layer = std::make_unique<BackgroundLayer>("background");
|
||||
layer->setBackgroundColor({{1, 0, 0, 1}});
|
||||
test.map.getStyle().addLayer(std::move(layer));
|
||||
|
||||
test::checkImage("test/fixtures/map/setFrustumOffset/before", test.frontend.render(test.map).image, 0.0006, 0.1);
|
||||
|
||||
test.map.setFrustumOffset(EdgeInsets{50, 50, 50, 50});
|
||||
|
||||
test::checkImage("test/fixtures/map/setFrustumOffset/after", test.frontend.render(test.map).image, 0.0006, 0.1);
|
||||
}
|
||||
|
||||
@@ -24,8 +24,7 @@ TEST(OffscreenTexture, EmptyRed) {
|
||||
gfx::BackendScope scope{backend};
|
||||
|
||||
// Scissor test shouldn't leak after gl::HeadlessBackend::bind().
|
||||
MBGL_CHECK_ERROR(glScissor(64, 64, 128, 128));
|
||||
static_cast<gl::Context&>(backend.getContext()).scissorTest.setCurrentValue(true);
|
||||
static_cast<gl::Context&>(backend.getContext()).scissorTest.setCurrentValue({64, 64, 128, 128});
|
||||
|
||||
backend.getDefaultRenderable().getResource<gl::RenderableResource>().bind();
|
||||
|
||||
@@ -146,8 +145,7 @@ void main() {
|
||||
gl::OffscreenTexture offscreenTexture(context, {128, 128});
|
||||
|
||||
// Scissor test shouldn't leak after OffscreenTexture::bind().
|
||||
MBGL_CHECK_ERROR(glScissor(32, 32, 64, 64));
|
||||
context.scissorTest.setCurrentValue(true);
|
||||
context.scissorTest.setCurrentValue({32, 32, 64, 64});
|
||||
|
||||
offscreenTexture.getResource<gl::RenderableResource>().bind();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user