mirror of
https://github.com/SFML/SFML.git
synced 2024-11-28 14:21:04 +08:00
Merge branch 'master' of https://github.com/SFML/SFML into comparisonbenchmark
This commit is contained in:
commit
bb0f88594f
7
.github/workflows/ci.yml
vendored
7
.github/workflows/ci.yml
vendored
@ -32,6 +32,7 @@ jobs:
|
|||||||
- { name: Windows VS2019 x64, os: windows-2019, flags: -DSFML_USE_MESA3D=ON -GNinja }
|
- { name: Windows VS2019 x64, os: windows-2019, flags: -DSFML_USE_MESA3D=ON -GNinja }
|
||||||
- { name: Windows VS2022 x86, os: windows-2022, flags: -DSFML_USE_MESA3D=ON -GNinja }
|
- { name: Windows VS2022 x86, os: windows-2022, flags: -DSFML_USE_MESA3D=ON -GNinja }
|
||||||
- { name: Windows VS2022 x64, os: windows-2022, flags: -DSFML_USE_MESA3D=ON -GNinja }
|
- { name: Windows VS2022 x64, os: windows-2022, flags: -DSFML_USE_MESA3D=ON -GNinja }
|
||||||
|
- { name: Windows VS2022 arm64, os: windows-2022, flags: -DSFML_USE_MESA3D=OFF -GNinja -DSFML_BUILD_TEST_SUITE=OFF }
|
||||||
- { name: Windows VS2022 ClangCL MSBuild, os: windows-2022, flags: -DSFML_USE_MESA3D=ON -T ClangCL } # ninja doesn't support specifying the toolset, so use the ClangCL toolset to test building with MSBuild as well
|
- { name: Windows VS2022 ClangCL MSBuild, os: windows-2022, flags: -DSFML_USE_MESA3D=ON -T ClangCL } # ninja doesn't support specifying the toolset, so use the ClangCL toolset to test building with MSBuild as well
|
||||||
- { name: Windows VS2022 OpenGL ES, os: windows-2022, flags: -DSFML_USE_MESA3D=ON -DSFML_OPENGL_ES=ON -GNinja }
|
- { name: Windows VS2022 OpenGL ES, os: windows-2022, flags: -DSFML_USE_MESA3D=ON -DSFML_OPENGL_ES=ON -GNinja }
|
||||||
- { name: Windows VS2022 Unity, os: windows-2022, flags: -DSFML_USE_MESA3D=ON -DCMAKE_UNITY_BUILD=ON -GNinja }
|
- { name: Windows VS2022 Unity, os: windows-2022, flags: -DSFML_USE_MESA3D=ON -DCMAKE_UNITY_BUILD=ON -GNinja }
|
||||||
@ -117,7 +118,7 @@ jobs:
|
|||||||
if: contains(matrix.platform.name, 'Windows VS') && !contains(matrix.platform.name, 'MSBuild')
|
if: contains(matrix.platform.name, 'Windows VS') && !contains(matrix.platform.name, 'MSBuild')
|
||||||
uses: ilammy/msvc-dev-cmd@v1
|
uses: ilammy/msvc-dev-cmd@v1
|
||||||
with:
|
with:
|
||||||
arch: ${{ contains(matrix.platform.name, 'x86') && 'x86' || 'x64' }}
|
arch: ${{ contains(matrix.platform.name, 'arm64') && 'amd64_arm64' || contains(matrix.platform.name, 'x86') && 'x86' || 'x64' }}
|
||||||
|
|
||||||
# Although the CMake configuration will run with 3.24 on Windows and 3.22
|
# Although the CMake configuration will run with 3.24 on Windows and 3.22
|
||||||
# elsewhere, we install 3.25 on Windows in order to support specifying
|
# elsewhere, we install 3.25 on Windows in order to support specifying
|
||||||
@ -237,7 +238,7 @@ jobs:
|
|||||||
find build/bin -name test-sfml-window -or -name test-sfml-window.exe -exec sh -c "{} *sf::Context* --section=\"Version String\" --success | grep OpenGL" \;
|
find build/bin -name test-sfml-window -or -name test-sfml-window.exe -exec sh -c "{} *sf::Context* --section=\"Version String\" --success | grep OpenGL" \;
|
||||||
|
|
||||||
- name: Test (Windows)
|
- name: Test (Windows)
|
||||||
if: runner.os == 'Windows' && !contains(matrix.platform.name, 'MinGW')
|
if: runner.os == 'Windows' && !contains(matrix.platform.name, 'MinGW') && !contains(matrix.platform.name, 'arm64')
|
||||||
run: cmake --build build --target runtests --config ${{ matrix.type.name == 'Debug' && 'Debug' || 'Release' }}
|
run: cmake --build build --target runtests --config ${{ matrix.type.name == 'Debug' && 'Debug' || 'Release' }}
|
||||||
|
|
||||||
- name: Test (Linux/macOS/MinGW)
|
- name: Test (Linux/macOS/MinGW)
|
||||||
@ -291,7 +292,7 @@ jobs:
|
|||||||
ctest --test-dir build --output-on-failure -C ${{ matrix.type.name == 'Debug' && 'Debug' || 'Release' }} --repeat until-pass:3
|
ctest --test-dir build --output-on-failure -C ${{ matrix.type.name == 'Debug' && 'Debug' || 'Release' }} --repeat until-pass:3
|
||||||
|
|
||||||
- name: Upload Coverage Report to Coveralls
|
- name: Upload Coverage Report to Coveralls
|
||||||
if: matrix.type.name == 'Debug' && github.repository == 'SFML/SFML' && !contains(matrix.platform.name, 'iOS') && !contains(matrix.platform.name, 'Android') # Disable upload in forks
|
if: matrix.type.name == 'Debug' && github.repository == 'SFML/SFML' && !contains(matrix.platform.name, 'iOS') && !contains(matrix.platform.name, 'Android') && !contains(matrix.platform.name, 'arm64') # Disable upload in forks
|
||||||
uses: coverallsapp/github-action@v2
|
uses: coverallsapp/github-action@v2
|
||||||
with:
|
with:
|
||||||
file: ./build/coverage.out
|
file: ./build/coverage.out
|
||||||
|
@ -6,9 +6,7 @@ if(${CMAKE_SYSTEM_NAME} STREQUAL "Windows")
|
|||||||
set(OPENGL_ES 0)
|
set(OPENGL_ES 0)
|
||||||
|
|
||||||
# detect the architecture
|
# detect the architecture
|
||||||
if(${CMAKE_GENERATOR_PLATFORM} MATCHES "ARM64")
|
if("${CMAKE_GENERATOR_PLATFORM}" MATCHES "ARM64" OR "${MSVC_CXX_ARCHITECTURE_ID}" MATCHES "ARM64" OR "${CMAKE_SYSTEM_PROCESSOR}" MATCHES "ARM64")
|
||||||
set(ARCH_ARM64 1)
|
|
||||||
elseif("${CMAKE_GENERATOR_PLATFORM}" STREQUAL "" AND ${CMAKE_SYSTEM_PROCESSOR} MATCHES "ARM64")
|
|
||||||
set(ARCH_ARM64 1)
|
set(ARCH_ARM64 1)
|
||||||
elseif(CMAKE_SIZEOF_VOID_P EQUAL 4)
|
elseif(CMAKE_SIZEOF_VOID_P EQUAL 4)
|
||||||
set(ARCH_X86 1)
|
set(ARCH_X86 1)
|
||||||
|
@ -4,11 +4,11 @@ set(MESA3D_SHA256 "FEF8A643689414A70347AE8027D24674DEFD85E8D6428C8A9D4145BB3F44A
|
|||||||
get_filename_component(MESA3D_ARCHIVE "${MESA3D_URL}" NAME)
|
get_filename_component(MESA3D_ARCHIVE "${MESA3D_URL}" NAME)
|
||||||
get_filename_component(MESA3D_ARCHIVE_DIRECTORY "${MESA3D_URL}" NAME_WLE)
|
get_filename_component(MESA3D_ARCHIVE_DIRECTORY "${MESA3D_URL}" NAME_WLE)
|
||||||
|
|
||||||
if(${ARCH_X64})
|
if(ARCH_X64)
|
||||||
set(MESA3D_ARCH "x64")
|
set(MESA3D_ARCH "x64")
|
||||||
elseif(${ARCH_X86})
|
elseif(ARCH_X86)
|
||||||
set(MESA3D_ARCH "x86")
|
set(MESA3D_ARCH "x86")
|
||||||
else()
|
elseif(SFML_USE_MESA3D)
|
||||||
message(FATAL_ERROR "Mesa 3D does currently not support the target architecture.")
|
message(FATAL_ERROR "Mesa 3D does currently not support the target architecture.")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
@ -61,7 +61,7 @@ if(SFML_OS_WINDOWS AND SFML_USE_MESA3D)
|
|||||||
add_custom_target(install-mesa3d DEPENDS ${MESA3D_INSTALLED_FILES})
|
add_custom_target(install-mesa3d DEPENDS ${MESA3D_INSTALLED_FILES})
|
||||||
|
|
||||||
set_target_properties(install-mesa3d PROPERTIES EXCLUDE_FROM_ALL ON)
|
set_target_properties(install-mesa3d PROPERTIES EXCLUDE_FROM_ALL ON)
|
||||||
elseif(SFML_OS_WINDOWS AND EXISTS "${MESA3D_ARCH_PATH}")
|
elseif(SFML_OS_WINDOWS AND MESA3D_ARCH AND EXISTS "${MESA3D_ARCH_PATH}")
|
||||||
# we are removing the files
|
# we are removing the files
|
||||||
|
|
||||||
# compile a list of file names that we have to remove
|
# compile a list of file names that we have to remove
|
||||||
|
@ -24,12 +24,10 @@
|
|||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
// Width and height of the application window
|
// Width and height of the application window
|
||||||
const unsigned int windowWidth = 800;
|
const sf::Vector2u windowSize(800, 600);
|
||||||
const unsigned int windowHeight = 600;
|
|
||||||
|
|
||||||
// Resolution of the generated terrain
|
// Resolution of the generated terrain
|
||||||
const unsigned int resolutionX = 800;
|
const sf::Vector2u resolution(800, 600);
|
||||||
const unsigned int resolutionY = 600;
|
|
||||||
|
|
||||||
// Thread pool parameters
|
// Thread pool parameters
|
||||||
const unsigned int threadCount = 4;
|
const unsigned int threadCount = 4;
|
||||||
@ -68,7 +66,7 @@ float edgeDropoffExponent = 1.5f;
|
|||||||
float snowcapHeight = 0.6f;
|
float snowcapHeight = 0.6f;
|
||||||
|
|
||||||
// Terrain lighting parameters
|
// Terrain lighting parameters
|
||||||
float heightFactor = windowHeight / 2.0f;
|
float heightFactor = static_cast<float>(windowSize.y) / 2.0f;
|
||||||
float heightFlatten = 3.0f;
|
float heightFlatten = 3.0f;
|
||||||
float lightFactor = 0.7f;
|
float lightFactor = 0.7f;
|
||||||
} // namespace
|
} // namespace
|
||||||
@ -88,7 +86,7 @@ void generateTerrain(sf::Vertex* vertexBuffer);
|
|||||||
int main()
|
int main()
|
||||||
{
|
{
|
||||||
// Create the window of the application
|
// Create the window of the application
|
||||||
sf::RenderWindow window(sf::VideoMode({windowWidth, windowHeight}), "SFML Island", sf::Style::Titlebar | sf::Style::Close);
|
sf::RenderWindow window(sf::VideoMode(windowSize), "SFML Island", sf::Style::Titlebar | sf::Style::Close);
|
||||||
window.setVerticalSyncEnabled(true);
|
window.setVerticalSyncEnabled(true);
|
||||||
|
|
||||||
const sf::Font font("resources/tuffy.ttf");
|
const sf::Font font("resources/tuffy.ttf");
|
||||||
@ -133,14 +131,14 @@ int main()
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Create our VertexBuffer with enough space to hold all the terrain geometry
|
// Create our VertexBuffer with enough space to hold all the terrain geometry
|
||||||
if (!terrain.create(resolutionX * resolutionY * 6))
|
if (!terrain.create(resolution.x * resolution.y * 6))
|
||||||
{
|
{
|
||||||
std::cerr << "Failed to create vertex buffer" << std::endl;
|
std::cerr << "Failed to create vertex buffer" << std::endl;
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Resize the staging buffer to be able to hold all the terrain geometry
|
// Resize the staging buffer to be able to hold all the terrain geometry
|
||||||
terrainStagingBuffer.resize(resolutionX * resolutionY * 6);
|
terrainStagingBuffer.resize(resolution.x * resolution.y * 6);
|
||||||
|
|
||||||
// Generate the initial terrain
|
// Generate the initial terrain
|
||||||
generateTerrain(terrainStagingBuffer.data());
|
generateTerrain(terrainStagingBuffer.data());
|
||||||
@ -152,7 +150,7 @@ int main()
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Center the status text
|
// Center the status text
|
||||||
statusText.setPosition((sf::Vector2f(windowWidth, windowHeight) - statusText.getLocalBounds().size) / 2.f);
|
statusText.setPosition((sf::Vector2f(windowSize) - statusText.getLocalBounds().size) / 2.f);
|
||||||
|
|
||||||
// Set up an array of pointers to our settings for arrow navigation
|
// Set up an array of pointers to our settings for arrow navigation
|
||||||
constexpr std::array<Setting, 9> settings = {
|
constexpr std::array<Setting, 9> settings = {
|
||||||
@ -279,58 +277,45 @@ int main()
|
|||||||
/// Get the terrain elevation at the given coordinates.
|
/// Get the terrain elevation at the given coordinates.
|
||||||
///
|
///
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
float getElevation(float x, float y)
|
float getElevation(sf::Vector2u position)
|
||||||
{
|
{
|
||||||
x = x / resolutionX - 0.5f;
|
const sf::Vector2f normalized = sf::Vector2f(position).componentWiseDiv(sf::Vector2f(resolution)) -
|
||||||
y = y / resolutionY - 0.5f;
|
sf::Vector2f(0.5f, 0.5f);
|
||||||
|
|
||||||
float elevation = 0.0f;
|
float elevation = 0.0f;
|
||||||
|
|
||||||
for (int i = 0; i < perlinOctaves; ++i)
|
for (int i = 0; i < perlinOctaves; ++i)
|
||||||
{
|
{
|
||||||
elevation += stb_perlin_noise3(x * perlinFrequency * static_cast<float>(std::pow(perlinFrequencyBase, i)),
|
const sf::Vector2f scaled = normalized * perlinFrequency * static_cast<float>(std::pow(perlinFrequencyBase, i));
|
||||||
y * perlinFrequency * static_cast<float>(std::pow(perlinFrequencyBase, i)),
|
elevation += stb_perlin_noise3(scaled.x, scaled.y, 0, 0, 0, 0) *
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0) *
|
|
||||||
static_cast<float>(std::pow(perlinFrequencyBase, -i));
|
static_cast<float>(std::pow(perlinFrequencyBase, -i));
|
||||||
}
|
}
|
||||||
|
|
||||||
elevation = (elevation + 1.f) / 2.f;
|
elevation = (elevation + 1.f) / 2.f;
|
||||||
|
|
||||||
const float distance = 2.0f * std::sqrt(x * x + y * y);
|
const float distance = 2.0f * normalized.length();
|
||||||
elevation = (elevation + heightBase) * (1.0f - edgeFactor * std::pow(distance, edgeDropoffExponent));
|
elevation = (elevation + heightBase) * (1.0f - edgeFactor * std::pow(distance, edgeDropoffExponent));
|
||||||
elevation = std::clamp(elevation, 0.0f, 1.0f);
|
elevation = std::clamp(elevation, 0.0f, 1.0f);
|
||||||
|
|
||||||
return elevation;
|
return elevation;
|
||||||
}
|
}
|
||||||
|
|
||||||
float getElevation(unsigned int x, unsigned int y)
|
|
||||||
{
|
|
||||||
return getElevation(static_cast<float>(x), static_cast<float>(y));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// Get the terrain moisture at the given coordinates.
|
/// Get the terrain moisture at the given coordinates.
|
||||||
///
|
///
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
float getMoisture(float x, float y)
|
float getMoisture(sf::Vector2u position)
|
||||||
{
|
{
|
||||||
x = x / resolutionX - 0.5f;
|
const sf::Vector2f normalized = sf::Vector2f(position).componentWiseDiv(sf::Vector2f(resolution)) -
|
||||||
y = y / resolutionY - 0.5f;
|
sf::Vector2f(0.5f, 0.5f);
|
||||||
|
const sf::Vector2f transformed = normalized * 4.f + sf::Vector2f(0.5f, 0.5f);
|
||||||
|
|
||||||
const float moisture = stb_perlin_noise3(x * 4.f + 0.5f, y * 4.f + 0.5f, 0, 0, 0, 0);
|
const float moisture = stb_perlin_noise3(transformed.x, transformed.y, 0, 0, 0, 0);
|
||||||
|
|
||||||
return (moisture + 1.f) / 2.f;
|
return (moisture + 1.f) / 2.f;
|
||||||
}
|
}
|
||||||
|
|
||||||
float getMoisture(unsigned int x, unsigned int y)
|
|
||||||
{
|
|
||||||
return getMoisture(static_cast<float>(x), static_cast<float>(y));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// Get the lowlands terrain color for the given moisture.
|
/// Get the lowlands terrain color for the given moisture.
|
||||||
@ -372,18 +357,16 @@ sf::Color getHighlandsTerrainColor(float elevation, float moisture)
|
|||||||
{
|
{
|
||||||
const sf::Color lowlandsColor = getLowlandsTerrainColor(moisture);
|
const sf::Color lowlandsColor = getLowlandsTerrainColor(moisture);
|
||||||
|
|
||||||
sf::Color color = moisture < 0.6f ? sf::Color(112, 128, 144)
|
const sf::Color color = moisture < 0.6f ? sf::Color(112, 128, 144)
|
||||||
: colorFromFloats(112 + (110 * (moisture - 0.6f) / 0.4f),
|
: colorFromFloats(112 + (110 * (moisture - 0.6f) / 0.4f),
|
||||||
128 + (56 * (moisture - 0.6f) / 0.4f),
|
128 + (56 * (moisture - 0.6f) / 0.4f),
|
||||||
144 - (9 * (moisture - 0.6f) / 0.4f));
|
144 - (9 * (moisture - 0.6f) / 0.4f));
|
||||||
|
|
||||||
const float factor = std::min((elevation - 0.4f) / 0.1f, 1.f);
|
const float factor = std::min((elevation - 0.4f) / 0.1f, 1.f);
|
||||||
|
|
||||||
color.r = static_cast<std::uint8_t>(lowlandsColor.r * (1.f - factor) + color.r * factor);
|
return colorFromFloats(lowlandsColor.r * (1.f - factor) + color.r * factor,
|
||||||
color.g = static_cast<std::uint8_t>(lowlandsColor.g * (1.f - factor) + color.g * factor);
|
lowlandsColor.g * (1.f - factor) + color.g * factor,
|
||||||
color.b = static_cast<std::uint8_t>(lowlandsColor.b * (1.f - factor) + color.b * factor);
|
lowlandsColor.b * (1.f - factor) + color.b * factor);
|
||||||
|
|
||||||
return color;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -396,15 +379,13 @@ sf::Color getSnowcapTerrainColor(float elevation, float moisture)
|
|||||||
{
|
{
|
||||||
const sf::Color highlandsColor = getHighlandsTerrainColor(elevation, moisture);
|
const sf::Color highlandsColor = getHighlandsTerrainColor(elevation, moisture);
|
||||||
|
|
||||||
sf::Color color = sf::Color::White;
|
const sf::Color color = sf::Color::White;
|
||||||
|
|
||||||
const float factor = std::min((elevation - snowcapHeight) / 0.05f, 1.f);
|
const float factor = std::min((elevation - snowcapHeight) / 0.05f, 1.f);
|
||||||
|
|
||||||
color.r = static_cast<std::uint8_t>(highlandsColor.r * (1.f - factor) + color.r * factor);
|
return colorFromFloats(highlandsColor.r * (1.f - factor) + color.r * factor,
|
||||||
color.g = static_cast<std::uint8_t>(highlandsColor.g * (1.f - factor) + color.g * factor);
|
highlandsColor.g * (1.f - factor) + color.g * factor,
|
||||||
color.b = static_cast<std::uint8_t>(highlandsColor.b * (1.f - factor) + color.b * factor);
|
highlandsColor.b * (1.f - factor) + color.b * factor);
|
||||||
|
|
||||||
return color;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -446,9 +427,7 @@ sf::Vector2f computeNormal(float left, float right, float bottom, float top)
|
|||||||
const sf::Vector3f deltaX(1, 0, (std::pow(right, heightFlatten) - std::pow(left, heightFlatten)) * heightFactor);
|
const sf::Vector3f deltaX(1, 0, (std::pow(right, heightFlatten) - std::pow(left, heightFlatten)) * heightFactor);
|
||||||
const sf::Vector3f deltaY(0, 1, (std::pow(top, heightFlatten) - std::pow(bottom, heightFlatten)) * heightFactor);
|
const sf::Vector3f deltaY(0, 1, (std::pow(top, heightFlatten) - std::pow(bottom, heightFlatten)) * heightFactor);
|
||||||
|
|
||||||
sf::Vector3f crossProduct(deltaX.y * deltaY.z - deltaX.z * deltaY.y,
|
sf::Vector3f crossProduct = deltaX.cross(deltaY);
|
||||||
deltaX.z * deltaY.x - deltaX.x * deltaY.z,
|
|
||||||
deltaX.x * deltaY.y - deltaX.y * deltaY.x);
|
|
||||||
|
|
||||||
// Scale cross product to make z component 1.0f so we can drop it
|
// Scale cross product to make z component 1.0f so we can drop it
|
||||||
crossProduct /= crossProduct.z;
|
crossProduct /= crossProduct.z;
|
||||||
@ -458,6 +437,26 @@ sf::Vector2f computeNormal(float left, float right, float bottom, float top)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// Compute the vertex representing the terrain at the given
|
||||||
|
/// coordinates.
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
const auto scalingFactors = sf::Vector2f(windowSize).componentWiseDiv(sf::Vector2f(resolution));
|
||||||
|
|
||||||
|
sf::Vertex computeVertex(sf::Vector2u position)
|
||||||
|
{
|
||||||
|
sf::Vertex vertex;
|
||||||
|
vertex.position = sf::Vector2f(position).componentWiseMul(scalingFactors);
|
||||||
|
vertex.color = getTerrainColor(getElevation(position), getMoisture(position));
|
||||||
|
vertex.texCoords = computeNormal(getElevation(position - sf::Vector2u(1, 0)),
|
||||||
|
getElevation(position + sf::Vector2u(1, 0)),
|
||||||
|
getElevation(position + sf::Vector2u(0, 1)),
|
||||||
|
getElevation(position - sf::Vector2u(0, 1)));
|
||||||
|
return vertex;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// Process a terrain generation work item. Use the vector
|
/// Process a terrain generation work item. Use the vector
|
||||||
/// of vertices as scratch memory and upload the data to
|
/// of vertices as scratch memory and upload the data to
|
||||||
@ -466,23 +465,20 @@ sf::Vector2f computeNormal(float left, float right, float bottom, float top)
|
|||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
void processWorkItem(std::vector<sf::Vertex>& vertices, const WorkItem& workItem)
|
void processWorkItem(std::vector<sf::Vertex>& vertices, const WorkItem& workItem)
|
||||||
{
|
{
|
||||||
const unsigned int rowBlockSize = (resolutionY / blockCount) + 1;
|
const unsigned int rowBlockSize = (resolution.y / blockCount) + 1;
|
||||||
const unsigned int rowStart = rowBlockSize * workItem.index;
|
const unsigned int rowStart = rowBlockSize * workItem.index;
|
||||||
|
|
||||||
if (rowStart >= resolutionY)
|
if (rowStart >= resolution.y)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
const unsigned int rowEnd = std::min(rowStart + rowBlockSize, resolutionY);
|
const unsigned int rowEnd = std::min(rowStart + rowBlockSize, resolution.y);
|
||||||
const unsigned int rowCount = rowEnd - rowStart;
|
const unsigned int rowCount = rowEnd - rowStart;
|
||||||
|
|
||||||
const float scalingFactorX = float{windowWidth} / float{resolutionX};
|
|
||||||
const float scalingFactorY = float{windowHeight} / float{resolutionY};
|
|
||||||
|
|
||||||
for (unsigned int y = rowStart; y < rowEnd; ++y)
|
for (unsigned int y = rowStart; y < rowEnd; ++y)
|
||||||
{
|
{
|
||||||
for (unsigned int x = 0; x < resolutionX; ++x)
|
for (unsigned int x = 0; x < resolution.x; ++x)
|
||||||
{
|
{
|
||||||
const unsigned int arrayIndexBase = ((y - rowStart) * resolutionX + x) * 6;
|
const unsigned int arrayIndexBase = ((y - rowStart) * resolution.x + x) * 6;
|
||||||
|
|
||||||
// Top left corner (first triangle)
|
// Top left corner (first triangle)
|
||||||
if (x > 0)
|
if (x > 0)
|
||||||
@ -491,17 +487,11 @@ void processWorkItem(std::vector<sf::Vertex>& vertices, const WorkItem& workItem
|
|||||||
}
|
}
|
||||||
else if (y > rowStart)
|
else if (y > rowStart)
|
||||||
{
|
{
|
||||||
vertices[arrayIndexBase + 0] = vertices[arrayIndexBase - resolutionX * 6 + 1];
|
vertices[arrayIndexBase + 0] = vertices[arrayIndexBase - resolution.x * 6 + 1];
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
vertices[arrayIndexBase + 0].position = sf::Vector2f(static_cast<float>(x) * scalingFactorX,
|
vertices[arrayIndexBase + 0] = computeVertex({x, y});
|
||||||
static_cast<float>(y) * scalingFactorY);
|
|
||||||
vertices[arrayIndexBase + 0].color = getTerrainColor(getElevation(x, y), getMoisture(x, y));
|
|
||||||
vertices[arrayIndexBase + 0].texCoords = computeNormal(getElevation(x - 1, y),
|
|
||||||
getElevation(x + 1, y),
|
|
||||||
getElevation(x, y + 1),
|
|
||||||
getElevation(x, y - 1));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Bottom left corner (first triangle)
|
// Bottom left corner (first triangle)
|
||||||
@ -511,23 +501,11 @@ void processWorkItem(std::vector<sf::Vertex>& vertices, const WorkItem& workItem
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
vertices[arrayIndexBase + 1].position = sf::Vector2f(static_cast<float>(x) * scalingFactorX,
|
vertices[arrayIndexBase + 1] = computeVertex({x, y + 1});
|
||||||
static_cast<float>(y + 1) * scalingFactorY);
|
|
||||||
vertices[arrayIndexBase + 1].color = getTerrainColor(getElevation(x, y + 1), getMoisture(x, y + 1));
|
|
||||||
vertices[arrayIndexBase + 1].texCoords = computeNormal(getElevation(x - 1, y + 1),
|
|
||||||
getElevation(x + 1, y + 1),
|
|
||||||
getElevation(x, y + 2),
|
|
||||||
getElevation(x, y));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Bottom right corner (first triangle)
|
// Bottom right corner (first triangle)
|
||||||
vertices[arrayIndexBase + 2].position = sf::Vector2f(static_cast<float>(x + 1) * scalingFactorX,
|
vertices[arrayIndexBase + 2] = computeVertex({x + 1, y + 1});
|
||||||
static_cast<float>(y + 1) * scalingFactorY);
|
|
||||||
vertices[arrayIndexBase + 2].color = getTerrainColor(getElevation(x + 1, y + 1), getMoisture(x + 1, y + 1));
|
|
||||||
vertices[arrayIndexBase + 2].texCoords = computeNormal(getElevation(x, y + 1),
|
|
||||||
getElevation(x + 2, y + 1),
|
|
||||||
getElevation(x + 1, y + 2),
|
|
||||||
getElevation(x + 1, y));
|
|
||||||
|
|
||||||
// Top left corner (second triangle)
|
// Top left corner (second triangle)
|
||||||
vertices[arrayIndexBase + 3] = vertices[arrayIndexBase + 0];
|
vertices[arrayIndexBase + 3] = vertices[arrayIndexBase + 0];
|
||||||
@ -538,25 +516,19 @@ void processWorkItem(std::vector<sf::Vertex>& vertices, const WorkItem& workItem
|
|||||||
// Top right corner (second triangle)
|
// Top right corner (second triangle)
|
||||||
if (y > rowStart)
|
if (y > rowStart)
|
||||||
{
|
{
|
||||||
vertices[arrayIndexBase + 5] = vertices[arrayIndexBase - resolutionX * 6 + 2];
|
vertices[arrayIndexBase + 5] = vertices[arrayIndexBase - resolution.x * 6 + 2];
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
vertices[arrayIndexBase + 5].position = sf::Vector2f(static_cast<float>(x + 1) * scalingFactorX,
|
vertices[arrayIndexBase + 5] = computeVertex({x + 1, y});
|
||||||
static_cast<float>(y) * scalingFactorY);
|
|
||||||
vertices[arrayIndexBase + 5].color = getTerrainColor(getElevation(x + 1, y), getMoisture(x + 1, y));
|
|
||||||
vertices[arrayIndexBase + 5].texCoords = computeNormal(getElevation(x, y),
|
|
||||||
getElevation(x + 2, y),
|
|
||||||
getElevation(x + 1, y + 1),
|
|
||||||
getElevation(x + 1, y - 1));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Copy the resulting geometry from our thread-local buffer into the target buffer
|
// Copy the resulting geometry from our thread-local buffer into the target buffer
|
||||||
std::memcpy(workItem.targetBuffer + (resolutionX * rowStart * 6),
|
std::memcpy(workItem.targetBuffer + (resolution.x * rowStart * 6),
|
||||||
vertices.data(),
|
vertices.data(),
|
||||||
sizeof(sf::Vertex) * resolutionX * rowCount * 6);
|
sizeof(sf::Vertex) * resolution.x * rowCount * 6);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -568,9 +540,9 @@ void processWorkItem(std::vector<sf::Vertex>& vertices, const WorkItem& workItem
|
|||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
void threadFunction()
|
void threadFunction()
|
||||||
{
|
{
|
||||||
const unsigned int rowBlockSize = (resolutionY / blockCount) + 1;
|
const unsigned int rowBlockSize = (resolution.y / blockCount) + 1;
|
||||||
|
|
||||||
std::vector<sf::Vertex> vertices(resolutionX * rowBlockSize * 6);
|
std::vector<sf::Vertex> vertices(resolution.x * rowBlockSize * 6);
|
||||||
|
|
||||||
WorkItem workItem = {nullptr, 0};
|
WorkItem workItem = {nullptr, 0};
|
||||||
|
|
||||||
|
@ -346,11 +346,11 @@ private:
|
|||||||
/// {
|
/// {
|
||||||
/// // Open the source and get audio settings
|
/// // Open the source and get audio settings
|
||||||
/// ...
|
/// ...
|
||||||
/// unsigned int channelCount = ...;
|
/// unsigned int channelCount = 2; // Stereo
|
||||||
/// unsigned int sampleRate = ...;
|
/// unsigned int sampleRate = 44100; // 44100 Hz
|
||||||
///
|
///
|
||||||
/// // Initialize the stream -- important!
|
/// // Initialize the stream -- important!
|
||||||
/// initialize(channelCount, sampleRate);
|
/// initialize(channelCount, sampleRate, {sf::SoundChannel::FrontLeft, sf::SoundChannel::FrontRight});
|
||||||
/// return true;
|
/// return true;
|
||||||
/// }
|
/// }
|
||||||
///
|
///
|
||||||
|
@ -180,9 +180,8 @@ public:
|
|||||||
/// If \a `state` is `State::Fullscreen`, then \a `mode` must be
|
/// If \a `state` is `State::Fullscreen`, then \a `mode` must be
|
||||||
/// a valid video mode.
|
/// a valid video mode.
|
||||||
///
|
///
|
||||||
/// The last parameter is an optional structure specifying
|
/// The last parameter is a structure specifying advanced OpenGL
|
||||||
/// advanced OpenGL context settings such as anti-aliasing,
|
/// context settings such as anti-aliasing, depth-buffer bits, etc.
|
||||||
/// depth-buffer bits, etc.
|
|
||||||
///
|
///
|
||||||
/// \param mode Video mode to use (defines the width, height and depth of the rendering area of the window)
|
/// \param mode Video mode to use (defines the width, height and depth of the rendering area of the window)
|
||||||
/// \param title Title of the window
|
/// \param title Title of the window
|
||||||
@ -193,6 +192,38 @@ public:
|
|||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
virtual void create(VideoMode mode, const String& title, std::uint32_t style, State state, const ContextSettings& settings);
|
virtual void create(VideoMode mode, const String& title, std::uint32_t style, State state, const ContextSettings& settings);
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// \brief Create (or recreate) the window
|
||||||
|
///
|
||||||
|
/// If the window was already created, it closes it first.
|
||||||
|
/// If \a `state` is `State::Fullscreen`, then \a `mode` must be
|
||||||
|
/// a valid video mode.
|
||||||
|
///
|
||||||
|
/// \param mode Video mode to use (defines the width, height and depth of the rendering area of the window)
|
||||||
|
/// \param title Title of the window
|
||||||
|
/// \param state %Window state
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
void create(VideoMode mode, const String& title, State state) override;
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// \brief Create (or recreate) the window
|
||||||
|
///
|
||||||
|
/// If the window was already created, it closes it first.
|
||||||
|
/// If \a `state` is `State::Fullscreen`, then \a `mode` must be
|
||||||
|
/// a valid video mode.
|
||||||
|
///
|
||||||
|
/// The last parameter is a structure specifying advanced OpenGL
|
||||||
|
/// context settings such as anti-aliasing, depth-buffer bits, etc.
|
||||||
|
///
|
||||||
|
/// \param mode Video mode to use (defines the width, height and depth of the rendering area of the window)
|
||||||
|
/// \param title Title of the window
|
||||||
|
/// \param state %Window state
|
||||||
|
/// \param settings Additional settings for the underlying OpenGL context
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
virtual void create(VideoMode mode, const String& title, State state, const ContextSettings& settings);
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// \brief Create (or recreate) the window from an existing control
|
/// \brief Create (or recreate) the window from an existing control
|
||||||
///
|
///
|
||||||
|
@ -157,6 +157,20 @@ public:
|
|||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
virtual void create(VideoMode mode, const String& title, std::uint32_t style = Style::Default, State state = State::Windowed);
|
virtual void create(VideoMode mode, const String& title, std::uint32_t style = Style::Default, State state = State::Windowed);
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// \brief Create (or recreate) the window
|
||||||
|
///
|
||||||
|
/// If the window was already created, it closes it first.
|
||||||
|
/// If \a `state` is `State::Fullscreen`, then \a `mode` must be
|
||||||
|
/// a valid video mode.
|
||||||
|
///
|
||||||
|
/// \param mode Video mode to use (defines the width, height and depth of the rendering area of the window)
|
||||||
|
/// \param title Title of the window
|
||||||
|
/// \param state %Window state
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
virtual void create(VideoMode mode, const String& title, State state);
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// \brief Create (or recreate) the window from an existing control
|
/// \brief Create (or recreate) the window from an existing control
|
||||||
///
|
///
|
||||||
|
@ -362,13 +362,10 @@ std::uint64_t SoundFileReaderFlac::read(std::int16_t* samples, std::uint64_t max
|
|||||||
if (left > maxCount)
|
if (left > maxCount)
|
||||||
{
|
{
|
||||||
// There are more leftovers than needed
|
// There are more leftovers than needed
|
||||||
std::copy(m_clientData.leftovers.begin(),
|
const auto signedMaxCount = static_cast<std::vector<std::int16_t>::difference_type>(maxCount);
|
||||||
m_clientData.leftovers.begin() + static_cast<std::vector<std::int16_t>::difference_type>(maxCount),
|
std::copy(m_clientData.leftovers.begin(), m_clientData.leftovers.begin() + signedMaxCount, samples);
|
||||||
samples);
|
m_clientData.leftovers = std::vector<std::int16_t>(m_clientData.leftovers.begin() + signedMaxCount,
|
||||||
std::vector<std::int16_t> leftovers(m_clientData.leftovers.begin() +
|
|
||||||
static_cast<std::vector<std::int16_t>::difference_type>(maxCount),
|
|
||||||
m_clientData.leftovers.end());
|
m_clientData.leftovers.end());
|
||||||
m_clientData.leftovers.swap(leftovers);
|
|
||||||
return maxCount;
|
return maxCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -31,81 +31,52 @@
|
|||||||
#include <SFML/System/Err.hpp>
|
#include <SFML/System/Err.hpp>
|
||||||
|
|
||||||
#include <ostream>
|
#include <ostream>
|
||||||
#include <string>
|
|
||||||
|
|
||||||
|
|
||||||
namespace sf::priv
|
namespace sf::priv
|
||||||
{
|
{
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
void glCheckError(const std::filesystem::path& file, unsigned int line, std::string_view expression)
|
bool glCheckError(const std::filesystem::path& file, unsigned int line, std::string_view expression)
|
||||||
{
|
{
|
||||||
// Get the last error
|
const auto logError = [&](const char* error, const char* description)
|
||||||
const GLenum errorCode = glGetError();
|
|
||||||
|
|
||||||
if (errorCode != GL_NO_ERROR)
|
|
||||||
{
|
{
|
||||||
std::string error = "Unknown error";
|
|
||||||
std::string description = "No description";
|
|
||||||
|
|
||||||
// Decode the error code
|
|
||||||
switch (errorCode)
|
|
||||||
{
|
|
||||||
case GL_INVALID_ENUM:
|
|
||||||
{
|
|
||||||
error = "GL_INVALID_ENUM";
|
|
||||||
description = "An unacceptable value has been specified for an enumerated argument.";
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case GL_INVALID_VALUE:
|
|
||||||
{
|
|
||||||
error = "GL_INVALID_VALUE";
|
|
||||||
description = "A numeric argument is out of range.";
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case GL_INVALID_OPERATION:
|
|
||||||
{
|
|
||||||
error = "GL_INVALID_OPERATION";
|
|
||||||
description = "The specified operation is not allowed in the current state.";
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case GL_STACK_OVERFLOW:
|
|
||||||
{
|
|
||||||
error = "GL_STACK_OVERFLOW";
|
|
||||||
description = "This command would cause a stack overflow.";
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case GL_STACK_UNDERFLOW:
|
|
||||||
{
|
|
||||||
error = "GL_STACK_UNDERFLOW";
|
|
||||||
description = "This command would cause a stack underflow.";
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case GL_OUT_OF_MEMORY:
|
|
||||||
{
|
|
||||||
error = "GL_OUT_OF_MEMORY";
|
|
||||||
description = "There is not enough memory left to execute the command.";
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case GLEXT_GL_INVALID_FRAMEBUFFER_OPERATION:
|
|
||||||
{
|
|
||||||
error = "GL_INVALID_FRAMEBUFFER_OPERATION";
|
|
||||||
description = "The object bound to FRAMEBUFFER_BINDING is not \"framebuffer complete\".";
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Log the error
|
|
||||||
err() << "An internal OpenGL call failed in " << file.filename() << "(" << line << ")."
|
err() << "An internal OpenGL call failed in " << file.filename() << "(" << line << ")."
|
||||||
<< "\nExpression:\n " << expression << "\nError description:\n " << error << "\n " << description << '\n'
|
<< "\nExpression:\n " << expression << "\nError description:\n " << error << "\n " << description << '\n'
|
||||||
<< std::endl;
|
<< std::endl;
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
|
||||||
|
switch (glGetError())
|
||||||
|
{
|
||||||
|
case GL_NO_ERROR:
|
||||||
|
return true;
|
||||||
|
|
||||||
|
case GL_INVALID_ENUM:
|
||||||
|
return logError("GL_INVALID_ENUM", "An unacceptable value has been specified for an enumerated argument.");
|
||||||
|
|
||||||
|
case GL_INVALID_VALUE:
|
||||||
|
return logError("GL_INVALID_VALUE", "A numeric argument is out of range.");
|
||||||
|
|
||||||
|
case GL_INVALID_OPERATION:
|
||||||
|
return logError("GL_INVALID_OPERATION", "The specified operation is not allowed in the current state.");
|
||||||
|
|
||||||
|
case GL_STACK_OVERFLOW:
|
||||||
|
return logError("GL_STACK_OVERFLOW", "This command would cause a stack overflow.");
|
||||||
|
|
||||||
|
case GL_STACK_UNDERFLOW:
|
||||||
|
return logError("GL_STACK_UNDERFLOW", "This command would cause a stack underflow.");
|
||||||
|
|
||||||
|
case GL_OUT_OF_MEMORY:
|
||||||
|
return logError("GL_OUT_OF_MEMORY", "There is not enough memory left to execute the command.");
|
||||||
|
|
||||||
|
case GLEXT_GL_INVALID_FRAMEBUFFER_OPERATION:
|
||||||
|
return logError("GL_INVALID_FRAMEBUFFER_OPERATION",
|
||||||
|
"The object bound to FRAMEBUFFER_BINDING is not \"framebuffer complete\".");
|
||||||
|
|
||||||
|
default:
|
||||||
|
return logError("Unknown error", "Unknown description");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace sf::priv
|
} // namespace sf::priv
|
||||||
|
@ -63,7 +63,9 @@ namespace sf::priv
|
|||||||
/// \param line Line number of the source file where the call is located
|
/// \param line Line number of the source file where the call is located
|
||||||
/// \param expression The evaluated expression as a string
|
/// \param expression The evaluated expression as a string
|
||||||
///
|
///
|
||||||
|
/// \return `false` if an error occurred, `true` otherwise
|
||||||
|
///
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
void glCheckError(const std::filesystem::path& file, unsigned int line, std::string_view expression);
|
bool glCheckError(const std::filesystem::path& file, unsigned int line, std::string_view expression);
|
||||||
|
|
||||||
} // namespace sf::priv
|
} // namespace sf::priv
|
||||||
|
@ -46,6 +46,7 @@
|
|||||||
#include <memory>
|
#include <memory>
|
||||||
#include <ostream>
|
#include <ostream>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
@ -154,7 +155,7 @@ void Image::resize(Vector2u size, Color color)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Commit the new pixel buffer
|
// Commit the new pixel buffer
|
||||||
m_pixels.swap(newPixels);
|
m_pixels = std::move(newPixels);
|
||||||
|
|
||||||
// Assign the new size
|
// Assign the new size
|
||||||
m_size = size;
|
m_size = size;
|
||||||
@ -179,7 +180,7 @@ void Image::resize(Vector2u size, const std::uint8_t* pixels)
|
|||||||
std::vector<std::uint8_t> newPixels(pixels, pixels + size.x * size.y * 4);
|
std::vector<std::uint8_t> newPixels(pixels, pixels + size.x * size.y * 4);
|
||||||
|
|
||||||
// Commit the new pixel buffer
|
// Commit the new pixel buffer
|
||||||
m_pixels.swap(newPixels);
|
m_pixels = std::move(newPixels);
|
||||||
|
|
||||||
// Assign the new size
|
// Assign the new size
|
||||||
m_size = size;
|
m_size = size;
|
||||||
|
@ -312,9 +312,7 @@ Vector2f Text::findCharacterPos(std::size_t index) const
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Transform the position to global coordinates
|
// Transform the position to global coordinates
|
||||||
position = getTransform().transformPoint(position);
|
return getTransform().transformPoint(position);
|
||||||
|
|
||||||
return position;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -33,139 +33,88 @@
|
|||||||
#include <glad/egl.h>
|
#include <glad/egl.h>
|
||||||
|
|
||||||
#include <ostream>
|
#include <ostream>
|
||||||
#include <string>
|
|
||||||
|
|
||||||
|
|
||||||
namespace sf::priv
|
namespace sf::priv
|
||||||
{
|
{
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
void eglCheckError(const std::filesystem::path& file, unsigned int line, std::string_view expression)
|
bool eglCheckError(const std::filesystem::path& file, unsigned int line, std::string_view expression)
|
||||||
{
|
{
|
||||||
// Obtain information about the success or failure of the most recent EGL
|
const auto logError = [&](const char* error, const char* description)
|
||||||
// function called in the current thread
|
|
||||||
const EGLint errorCode = eglGetError();
|
|
||||||
|
|
||||||
if (errorCode != EGL_SUCCESS)
|
|
||||||
{
|
{
|
||||||
std::string error = "unknown error";
|
|
||||||
std::string description = "no description";
|
|
||||||
|
|
||||||
// Decode the error code returned
|
|
||||||
switch (errorCode)
|
|
||||||
{
|
|
||||||
case EGL_NOT_INITIALIZED:
|
|
||||||
{
|
|
||||||
error = "EGL_NOT_INITIALIZED";
|
|
||||||
description = "EGL is not initialized, or could not be initialized, for the specified display";
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case EGL_BAD_ACCESS:
|
|
||||||
{
|
|
||||||
error = "EGL_BAD_ACCESS";
|
|
||||||
description =
|
|
||||||
"EGL cannot access a requested resource (for example, a context is bound in another thread)";
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case EGL_BAD_ALLOC:
|
|
||||||
{
|
|
||||||
error = "EGL_BAD_ALLOC";
|
|
||||||
description = "EGL failed to allocate resources for the requested operation";
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case EGL_BAD_ATTRIBUTE:
|
|
||||||
{
|
|
||||||
error = "EGL_BAD_ATTRIBUTE";
|
|
||||||
description = "an unrecognized attribute or attribute value was passed in an attribute list";
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case EGL_BAD_CONTEXT:
|
|
||||||
{
|
|
||||||
error = "EGL_BAD_CONTEXT";
|
|
||||||
description = "an EGLContext argument does not name a valid EGLContext";
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case EGL_BAD_CONFIG:
|
|
||||||
{
|
|
||||||
error = "EGL_BAD_CONFIG";
|
|
||||||
description = "an EGLConfig argument does not name a valid EGLConfig";
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case EGL_BAD_CURRENT_SURFACE:
|
|
||||||
{
|
|
||||||
error = "EGL_BAD_CURRENT_SURFACE";
|
|
||||||
description =
|
|
||||||
"the current surface of the calling thread is a window, pbuffer, or pixmap that is no longer valid";
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case EGL_BAD_DISPLAY:
|
|
||||||
{
|
|
||||||
error = "EGL_BAD_DISPLAY";
|
|
||||||
description =
|
|
||||||
"an EGLDisplay argument does not name a valid EGLDisplay; or, EGL is not initialized on the "
|
|
||||||
"specified EGLDisplay";
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
case EGL_BAD_SURFACE:
|
|
||||||
{
|
|
||||||
error = "EGL_BAD_SURFACE";
|
|
||||||
description =
|
|
||||||
"an EGLSurface argument does not name a valid surface (window, pbuffer, or pixmap) configured for "
|
|
||||||
"rendering";
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case EGL_BAD_MATCH:
|
|
||||||
{
|
|
||||||
error = "EGL_BAD_MATCH";
|
|
||||||
description =
|
|
||||||
"arguments are inconsistent; for example, an otherwise valid context requires buffers (e.g. depth "
|
|
||||||
"or stencil) not allocated by an otherwise valid surface";
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case EGL_BAD_PARAMETER:
|
|
||||||
{
|
|
||||||
error = "EGL_BAD_PARAMETER";
|
|
||||||
description = "one or more argument values are invalid";
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case EGL_BAD_NATIVE_PIXMAP:
|
|
||||||
{
|
|
||||||
error = "EGL_BAD_NATIVE_PIXMAP";
|
|
||||||
description = "an EGLNativePixmapType argument does not refer to a valid native pixmap";
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case EGL_BAD_NATIVE_WINDOW:
|
|
||||||
{
|
|
||||||
error = "EGL_BAD_NATIVE_WINDOW";
|
|
||||||
description = "an EGLNativeWindowType argument does not refer to a valid native window";
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case EGL_CONTEXT_LOST:
|
|
||||||
{
|
|
||||||
error = "EGL_CONTEXT_LOST";
|
|
||||||
description =
|
|
||||||
"a power management event has occurred. The application must destroy all contexts and reinitialize "
|
|
||||||
"client API state and objects to continue rendering";
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Log the error
|
|
||||||
err() << "An internal EGL call failed in " << file.filename() << " (" << line << ") : "
|
err() << "An internal EGL call failed in " << file.filename() << " (" << line << ") : "
|
||||||
<< "\nExpression:\n " << expression << "\nError description:\n " << error << "\n " << description << '\n'
|
<< "\nExpression:\n " << expression << "\nError description:\n " << error << "\n " << description << '\n'
|
||||||
<< std::endl;
|
<< std::endl;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
|
||||||
|
switch (eglGetError())
|
||||||
|
{
|
||||||
|
case EGL_SUCCESS:
|
||||||
|
return true;
|
||||||
|
|
||||||
|
case EGL_NOT_INITIALIZED:
|
||||||
|
return logError("EGL_NOT_INITIALIZED",
|
||||||
|
"EGL is not initialized, or could not be initialized, for the specified display");
|
||||||
|
|
||||||
|
case EGL_BAD_ACCESS:
|
||||||
|
return logError("EGL_BAD_ACCESS",
|
||||||
|
"EGL cannot access a requested resource (for example, a context is bound in another "
|
||||||
|
"thread)");
|
||||||
|
|
||||||
|
case EGL_BAD_ALLOC:
|
||||||
|
return logError("EGL_BAD_ALLOC", "EGL failed to allocate resources for the requested operation");
|
||||||
|
|
||||||
|
case EGL_BAD_ATTRIBUTE:
|
||||||
|
return logError("EGL_BAD_ATTRIBUTE",
|
||||||
|
"an unrecognized attribute or attribute value was passed in an attribute list");
|
||||||
|
|
||||||
|
case EGL_BAD_CONTEXT:
|
||||||
|
return logError("EGL_BAD_CONTEXT", "an EGLContext argument does not name a valid EGLContext");
|
||||||
|
|
||||||
|
case EGL_BAD_CONFIG:
|
||||||
|
return logError("EGL_BAD_CONFIG", "an EGLConfig argument does not name a valid EGLConfig");
|
||||||
|
|
||||||
|
case EGL_BAD_CURRENT_SURFACE:
|
||||||
|
return logError("EGL_BAD_CURRENT_SURFACE",
|
||||||
|
"the current surface of the calling thread is a window, pbuffer, or pixmap that is no "
|
||||||
|
"longer valid");
|
||||||
|
|
||||||
|
case EGL_BAD_DISPLAY:
|
||||||
|
return logError("EGL_BAD_DISPLAY",
|
||||||
|
"an EGLDisplay argument does not name a valid EGLDisplay; or, EGL is not initialized on "
|
||||||
|
"the specified EGLDisplay");
|
||||||
|
|
||||||
|
|
||||||
|
case EGL_BAD_SURFACE:
|
||||||
|
return logError("EGL_BAD_SURFACE",
|
||||||
|
"an EGLSurface argument does not name a valid surface (window, pbuffer, or pixmap) "
|
||||||
|
"configured for rendering");
|
||||||
|
|
||||||
|
case EGL_BAD_MATCH:
|
||||||
|
return logError("EGL_BAD_MATCH",
|
||||||
|
"arguments are inconsistent; for example, an otherwise valid context requires buffers "
|
||||||
|
"(e.g. depth or stencil) not allocated by an otherwise valid surface");
|
||||||
|
|
||||||
|
case EGL_BAD_PARAMETER:
|
||||||
|
return logError("EGL_BAD_PARAMETER", "one or more argument values are invalid");
|
||||||
|
|
||||||
|
case EGL_BAD_NATIVE_PIXMAP:
|
||||||
|
return logError("EGL_BAD_NATIVE_PIXMAP",
|
||||||
|
"an EGLNativePixmapType argument does not refer to a valid native pixmap");
|
||||||
|
|
||||||
|
case EGL_BAD_NATIVE_WINDOW:
|
||||||
|
return logError("EGL_BAD_NATIVE_WINDOW",
|
||||||
|
"an EGLNativeWindowType argument does not refer to a valid native window");
|
||||||
|
|
||||||
|
case EGL_CONTEXT_LOST:
|
||||||
|
return logError("EGL_CONTEXT_LOST",
|
||||||
|
"a power management event has occurred. The application must destroy all contexts and "
|
||||||
|
"reinitialize client API state and objects to continue rendering");
|
||||||
|
|
||||||
|
default:
|
||||||
|
return logError("Unknown error", "Unknown description");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -63,7 +63,9 @@ namespace sf::priv
|
|||||||
/// \param line Line number of the source file where the call is located
|
/// \param line Line number of the source file where the call is located
|
||||||
/// \param expression The evaluated expression as a string
|
/// \param expression The evaluated expression as a string
|
||||||
///
|
///
|
||||||
|
/// \return `false` if an error occurred, `true` otherwise
|
||||||
|
///
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
void eglCheckError(const std::filesystem::path& file, unsigned int line, std::string_view expression);
|
bool eglCheckError(const std::filesystem::path& file, unsigned int line, std::string_view expression);
|
||||||
|
|
||||||
} // namespace sf::priv
|
} // namespace sf::priv
|
||||||
|
@ -95,6 +95,20 @@ void Window::create(VideoMode mode, const String& title, std::uint32_t style, St
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
void Window::create(VideoMode mode, const String& title, State state)
|
||||||
|
{
|
||||||
|
Window::create(mode, title, sf::Style::Default, state, ContextSettings{});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
void Window::create(VideoMode mode, const String& title, State state, const ContextSettings& settings)
|
||||||
|
{
|
||||||
|
Window::create(mode, title, sf::Style::Default, state, settings);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
void Window::create(WindowHandle handle)
|
void Window::create(WindowHandle handle)
|
||||||
{
|
{
|
||||||
|
@ -102,6 +102,13 @@ void WindowBase::create(VideoMode mode, const String& title, std::uint32_t style
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
void WindowBase::create(VideoMode mode, const String& title, State state)
|
||||||
|
{
|
||||||
|
create(mode, title, Style::Default, state);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
void WindowBase::create(WindowHandle handle)
|
void WindowBase::create(WindowHandle handle)
|
||||||
{
|
{
|
||||||
|
@ -287,6 +287,7 @@ private:
|
|||||||
// Member data
|
// Member data
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
IOHIDManagerRef m_manager{}; ///< Underlying HID Manager
|
IOHIDManagerRef m_manager{}; ///< Underlying HID Manager
|
||||||
|
bool m_keysInitialized{}; ///< Has initializeKeyboard been called at least once?
|
||||||
EnumArray<Keyboard::Scancode, IOHIDElements, Keyboard::ScancodeCount> m_keys; ///< All the keys on any connected keyboard
|
EnumArray<Keyboard::Scancode, IOHIDElements, Keyboard::ScancodeCount> m_keys; ///< All the keys on any connected keyboard
|
||||||
EnumArray<Keyboard::Key, Keyboard::Scancode, Keyboard::KeyCount> m_keyToScancodeMapping{}; ///< Mapping from Key to Scancode
|
EnumArray<Keyboard::Key, Keyboard::Scancode, Keyboard::KeyCount> m_keyToScancodeMapping{}; ///< Mapping from Key to Scancode
|
||||||
EnumArray<Keyboard::Scancode, Keyboard::Key, Keyboard::ScancodeCount> m_scancodeToKeyMapping{}; ///< Mapping from Scancode to Key
|
EnumArray<Keyboard::Scancode, Keyboard::Key, Keyboard::ScancodeCount> m_scancodeToKeyMapping{}; ///< Mapping from Scancode to Key
|
||||||
|
@ -562,6 +562,13 @@ bool HIDInputManager::isKeyPressed(Keyboard::Key key)
|
|||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
bool HIDInputManager::isKeyPressed(Keyboard::Scancode code)
|
bool HIDInputManager::isKeyPressed(Keyboard::Scancode code)
|
||||||
{
|
{
|
||||||
|
// Lazy load m_keys to prevent unnecessary macOS input monitoring permission requests
|
||||||
|
if (!m_keysInitialized)
|
||||||
|
{
|
||||||
|
initializeKeyboard();
|
||||||
|
m_keysInitialized = true;
|
||||||
|
}
|
||||||
|
|
||||||
return (code != Keyboard::Scan::Unknown) && isPressed(m_keys[code]);
|
return (code != Keyboard::Scan::Unknown) && isPressed(m_keys[code]);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -716,7 +723,6 @@ HIDInputManager::HIDInputManager()
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Build up our knowledge of the hardware
|
// Build up our knowledge of the hardware
|
||||||
initializeKeyboard();
|
|
||||||
buildMappings();
|
buildMappings();
|
||||||
|
|
||||||
// Register for notification on keyboard layout changes
|
// Register for notification on keyboard layout changes
|
||||||
@ -924,6 +930,8 @@ void HIDInputManager::freeUp()
|
|||||||
|
|
||||||
m_manager = nil;
|
m_manager = nil;
|
||||||
|
|
||||||
|
if (m_keysInitialized)
|
||||||
|
{
|
||||||
for (auto& key : m_keys)
|
for (auto& key : m_keys)
|
||||||
{
|
{
|
||||||
for (IOHIDElementRef iohidElementRef : key)
|
for (IOHIDElementRef iohidElementRef : key)
|
||||||
@ -932,6 +940,8 @@ void HIDInputManager::freeUp()
|
|||||||
key.clear();
|
key.clear();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
m_keysInitialized = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
|
@ -128,7 +128,16 @@ TEST_CASE("[Window] sf::Window", runDisplayTests())
|
|||||||
CHECK(window.getSettings().attributeFlags == sf::ContextSettings::Default);
|
CHECK(window.getSettings().attributeFlags == sf::ContextSettings::Default);
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("Mode, title, style, and context settings")
|
SECTION("Mode, title, style, and state")
|
||||||
|
{
|
||||||
|
window.create(sf::VideoMode({240, 360}), "Window Tests", sf::Style::Resize, sf::State::Windowed);
|
||||||
|
CHECK(window.isOpen());
|
||||||
|
CHECK(window.getSize() == sf::Vector2u(240, 360));
|
||||||
|
CHECK(window.getNativeHandle() != sf::WindowHandle());
|
||||||
|
CHECK(window.getSettings().attributeFlags == sf::ContextSettings::Default);
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("Mode, title, style, state, and context settings")
|
||||||
{
|
{
|
||||||
window.create(sf::VideoMode({240, 360}),
|
window.create(sf::VideoMode({240, 360}),
|
||||||
"Window Tests",
|
"Window Tests",
|
||||||
@ -142,5 +151,28 @@ TEST_CASE("[Window] sf::Window", runDisplayTests())
|
|||||||
CHECK(window.getSettings().stencilBits >= 1);
|
CHECK(window.getSettings().stencilBits >= 1);
|
||||||
CHECK(window.getSettings().antiAliasingLevel >= 1);
|
CHECK(window.getSettings().antiAliasingLevel >= 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SECTION("Mode, title, and state")
|
||||||
|
{
|
||||||
|
window.create(sf::VideoMode({240, 360}), "Window Tests", sf::State::Windowed);
|
||||||
|
CHECK(window.isOpen());
|
||||||
|
CHECK(window.getSize() == sf::Vector2u(240, 360));
|
||||||
|
CHECK(window.getNativeHandle() != sf::WindowHandle());
|
||||||
|
CHECK(window.getSettings().attributeFlags == sf::ContextSettings::Default);
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("Mode, title, state, and context settings")
|
||||||
|
{
|
||||||
|
window.create(sf::VideoMode({240, 360}),
|
||||||
|
"Window Tests",
|
||||||
|
sf::State::Windowed,
|
||||||
|
sf::ContextSettings{/* depthBits*/ 1, /* stencilBits */ 1, /* antiAliasingLevel */ 1});
|
||||||
|
CHECK(window.isOpen());
|
||||||
|
CHECK(window.getSize() == sf::Vector2u(240, 360));
|
||||||
|
CHECK(window.getNativeHandle() != sf::WindowHandle());
|
||||||
|
CHECK(window.getSettings().depthBits >= 1);
|
||||||
|
CHECK(window.getSettings().stencilBits >= 1);
|
||||||
|
CHECK(window.getSettings().antiAliasingLevel >= 1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -88,6 +88,14 @@ TEST_CASE("[Window] sf::WindowBase", runDisplayTests())
|
|||||||
CHECK(windowBase.getNativeHandle() != sf::WindowHandle());
|
CHECK(windowBase.getNativeHandle() != sf::WindowHandle());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SECTION("Mode, title, and state")
|
||||||
|
{
|
||||||
|
windowBase.create(sf::VideoMode({240, 360}), "WindowBase Tests", sf::State::Windowed);
|
||||||
|
CHECK(windowBase.isOpen());
|
||||||
|
CHECK(windowBase.getSize() == sf::Vector2u(240, 360));
|
||||||
|
CHECK(windowBase.getNativeHandle() != sf::WindowHandle());
|
||||||
|
}
|
||||||
|
|
||||||
SECTION("Mode, title, style, and state")
|
SECTION("Mode, title, style, and state")
|
||||||
{
|
{
|
||||||
windowBase.create(sf::VideoMode({240, 360}), "WindowBase Tests", sf::Style::Resize, sf::State::Windowed);
|
windowBase.create(sf::VideoMode({240, 360}), "WindowBase Tests", sf::Style::Resize, sf::State::Windowed);
|
||||||
|
Loading…
Reference in New Issue
Block a user