Skip to content

Commit

Permalink
Merge pull request #40 from gmbeard/fix/drm-color-conversion
Browse files Browse the repository at this point in the history
fix: Color conversion for Wayland compositors that use non-linear pixel formats
  • Loading branch information
gmbeard authored Aug 1, 2024
2 parents 30c97f0 + 77217c7 commit 0431b9f
Show file tree
Hide file tree
Showing 55 changed files with 11,577 additions and 77 deletions.
1 change: 1 addition & 0 deletions .versioning/changes/HkssZKsWhD.patch.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Fixes color conversion on Wayland compositors that don't use a linear pixel format for DRM planes (#39) (thanks: @SleepingPanda)
2 changes: 2 additions & 0 deletions cmake/CPPCheck.cmake
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
find_program(CMAKE_CXX_CPPCHECK NAMES cppcheck)
if(CMAKE_CXX_CPPCHECK AND CMAKE_BUILD_TYPE STREQUAL "Debug")
list(APPEND CMAKE_CXX_CPPCHECK
"--check-level=exhaustive"
"--inline-suppr"
"--enable=warning"
"--error-exitcode=1"
)
Expand Down
59 changes: 59 additions & 0 deletions cmake/EmbeddedGLSLTarget.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
# This will create an object library target called `${NAME}.o`
# which will embed and export the GLSL as a array of bytes.
# The symbol name given to each export GLSL file is derived
# from the entry in `SOURCES`...
#
# ```
# extern char const _private_<SOURCE_FILE_WITH_UNDERSCORES>_start[];
# extern char const _private_<SOURCE_FILE_WITH_UNDERSCORES>_end[];
# ```
#
# The source file (combined with any path components) have all `.`
# `-`, `/`, etc replaced with underscores (`_`)
#
# To keep the exported symbol names short, you should restrict
# `SOURCES` to files in the current directory. Any relative
# directories will also form part of the symbol name. E.g...
#
# ```
# add_embedded_glsl_target(
# SOURCES glsl/vertex-shaders/shader.glsl
# ...
# )
# ```
#
# would yield the following symbol names...
#
# ```
# extern char const _private_glsl_vertex_shaders_shader_glsl_start[];
# extern char const _private_glsl_vertex_shaders_shader_glsl_end[];
# ```
function(add_embedded_glsl_target)
set(single_value_args NAME)
set(multi_value_args SOURCES)
cmake_parse_arguments(
ADD_EMBEDDED_GLSL_TARGET
"${options}"
"${single_value_args}"
"${multi_value_args}"
${ARGN}
)

# We may be able to use the `-L` argument when generating an
# object file, which could remove the path element from the
# symbol names (`-L` is a search path)...
add_custom_target(
${ADD_EMBEDDED_GLSL_TARGET_NAME}_generator
COMMAND ${CMAKE_LINKER} -b binary -r
-o "${CMAKE_CURRENT_BINARY_DIR}/${ADD_EMBEDDED_GLSL_TARGET_NAME}.o"
${ADD_EMBEDDED_GLSL_TARGET_SOURCES}
WORKING_DIRECTORY "${CMAKE_CURRENT_LIST_DIR}"
)
add_library(${ADD_EMBEDDED_GLSL_TARGET_NAME} OBJECT IMPORTED GLOBAL)
set_target_properties(
${ADD_EMBEDDED_GLSL_TARGET_NAME}
PROPERTIES
IMPORTED_OBJECTS "${CMAKE_CURRENT_BINARY_DIR}/${ADD_EMBEDDED_GLSL_TARGET_NAME}.o"
)
add_dependencies(${ADD_EMBEDDED_GLSL_TARGET_NAME} ${ADD_EMBEDDED_GLSL_TARGET_NAME}_generator)
endfunction()
44 changes: 32 additions & 12 deletions cmake/MakeTest.cmake
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
function(make_test)
set(options FULL SIMPLE)
set(single_value_args NAME ENABLE_MATCH)
set(multi_value_args SOURCES ENV_VARS)
set(single_value_args NAME)
set(multi_value_args SOURCES ENV_VARS ENABLE_IF LABELS LINK_LIBRARIES)
cmake_parse_arguments(
MAKE_TEST
"${options}"
Expand All @@ -10,22 +9,43 @@ function(make_test)
${ARGN}
)

message(STATUS "Enable match: ${${MAKE_TEST_ENABLE_MATCH}}")
if((MAKE_TEST_SIMPLE) AND (NOT ${MAKE_TEST_ENABLE_MATCH} OR ${MAKE_TEST_ENABLE_MATCH} STREQUAL "SIMPLE"))
set(TEST_ENABLED ON)
elseif(MAKE_TEST_FULL AND ${MAKE_TEST_ENABLE_MATCH} STREQUAL "FULL")
set(TEST_ENABLED ON)
if(NOT MAKE_TEST_LABELS)
set(MAKE_TEST_LABELS "default-tests")
endif()

if (NOT TEST_ENABLED)
return()
endif()
add_executable(${MAKE_TEST_NAME} ${MAKE_TEST_SOURCES})
target_link_libraries(${MAKE_TEST_NAME} PRIVATE testing shadow-cast-obj)
target_link_libraries(${MAKE_TEST_NAME} PRIVATE testing embedded_glsl shadow-cast-obj ${MAKE_TEST_LINK_LIBRARIES})
add_test(NAME ${MAKE_TEST_NAME} COMMAND ${MAKE_TEST_NAME})
set_tests_properties(
${MAKE_TEST_NAME}
PROPERTIES
ENVIRONMENT "${MAKE_TEST_ENV_VARS}"
LABELS "${MAKE_TEST_LABELS}"
)

# If the test doesn't specify any ENABLE_IF flags then
# it is always included...
list(LENGTH MAKE_TEST_ENABLE_IF enable_if_length)
if(enable_if_length EQUAL 0)
return()
endif()

# Loop through the ENABLE_IF flags. If any are found in
# the test properties then we return early and the test
# is included...
while(enable_if_length GREATER 0)
list(POP_FRONT MAKE_TEST_ENABLE_IF enable_if_val)
if(${enable_if_val} IN_LIST SHADOW_CAST_ENABLE_TEST_CATEGORIES)
return()
endif()
list(LENGTH MAKE_TEST_ENABLE_IF enable_if_length)
endwhile()

# At the point, there were ENABLE_IF flags specified but
# non were found in the test properties, so disable it...
set_tests_properties(
${MAKE_TEST_NAME}
PROPERTIES
DISABLED ON
)
endfunction()
15 changes: 15 additions & 0 deletions src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,15 @@ add_library(shadow-cast-obj
drm/messaging.cpp
drm/planes.cpp

gl/buffer.cpp
gl/core.cpp
gl/error.cpp
gl/framebuffer.cpp
gl/program.cpp
gl/shader.cpp
gl/texture.cpp
gl/vertex_array_object.cpp

handlers/audio_chunk_writer.cpp
handlers/drm_video_frame_writer.cpp
handlers/stream_finalizer.cpp
Expand All @@ -30,9 +39,11 @@ add_library(shadow-cast-obj
io/unix_socket.cpp

platform/egl.cpp
platform/opengl.cpp
platform/wayland.cpp

services/audio_service.cpp
services/color_converter.cpp
services/context.cpp
services/drm_video_service.cpp
services/encoder.cpp
Expand Down Expand Up @@ -78,12 +89,15 @@ target_link_libraries(shadow-cast-obj
wayland-egl
)

add_subdirectory(glsl)

add_executable(shadow-cast
main.cpp
)

target_link_libraries(shadow-cast
PRIVATE
embedded_glsl
shadow-cast-obj
)

Expand All @@ -105,6 +119,7 @@ set_target_properties(

target_link_libraries(shadow-cast-kms
PRIVATE
embedded_glsl
shadow-cast-obj
DRM::drm
)
38 changes: 38 additions & 0 deletions src/gl/buffer.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
#include "gl/buffer.hpp"
#include "gl/error.hpp"

namespace sc::opengl
{
auto BufferTraits::create() const -> GLuint
{
GLuint name;
gl().glGenBuffers(1, &name);
SC_CHECK_GL_ERROR("glGenBuffers");
return name;
}

auto BufferTraits::destroy(GLuint name) const noexcept -> void
{
gl().glDeleteBuffers(1, &name);
SC_CHECK_GL_ERROR_NOEXCEPT("glDeleteBuffers");
}

auto BufferTraits::bind(GLenum target, GLint name) const noexcept -> void
{
gl().glBindBuffer(target, name);
SC_CHECK_GL_ERROR("glBindBuffer");
}

auto vertex_attrib_pointer(
BoundTarget<BufferTarget<GL_ARRAY_BUFFER>, Buffer> const& /*array_buffer*/,
GLuint index,
GLint size,
GLenum type,
GLboolean normalized,
GLsizei stride,
void const* pointer) -> void
{
gl().glVertexAttribPointer(index, size, type, normalized, stride, pointer);
SC_CHECK_GL_ERROR("glVertexAttribPointer");
}
} // namespace sc::opengl
82 changes: 82 additions & 0 deletions src/gl/buffer.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
#ifndef SHADOW_CAST_GL_BUFFER_HPP_INCLUDED
#define SHADOW_CAST_GL_BUFFER_HPP_INCLUDED

#include "gl/error.hpp"
#include "gl/object.hpp"
#include "platform/opengl.hpp"
#include <GL/gl.h>
#include <GL/glext.h>
#include <span>
#include <tuple>
#include <type_traits>
namespace sc
{

namespace opengl
{
template <typename T>
concept BufferableConcept = std::is_arithmetic_v<T>;

struct BufferCategory
{
};

struct BufferTraits
{
using category = BufferCategory;

auto create() const -> GLuint;
auto destroy(GLuint name) const noexcept -> void;
auto bind(GLenum target, GLint name) const noexcept -> void;
};

using Buffer = ObjectBase<BufferTraits>;
template <GLenum T>
using BufferTarget = TargetBase<T, BufferTraits>;

template <typename T>
concept BufferConcept =
std::is_convertible_v<typename T::category, BufferCategory>;

template <typename T>
concept BoundBufferConcept =
BindingConcept<std::decay_t<T>> && BufferConcept<T>;

template <BoundBufferConcept A, BufferableConcept T>
auto named_buffer_data(A& array_buffer, std::span<T const> data, GLenum usage)
-> void
{
const auto [id, sz, d] =
std::make_tuple(array_buffer.name(), data.size(), data.data());

gl().glNamedBufferData(id, sz * sizeof(T), d, usage);
SC_CHECK_GL_ERROR("glNamedBufferData");
}

template <BoundBufferConcept A, BufferableConcept T>
auto buffer_data(A& array_buffer, std::span<T> data, GLenum usage) -> void
{
const auto [target, sz, d] =
std::make_tuple(array_buffer.target(), data.size(), data.data());

gl().glBufferData(target, sz * sizeof(T), d, usage);
SC_CHECK_GL_ERROR("glBufferData");
}

auto vertex_attrib_pointer(
BoundTarget<BufferTarget<GL_ARRAY_BUFFER>, Buffer> const& array_buffer,
GLuint index,
GLint size,
GLenum type,
GLboolean normalized,
GLsizei stride,
void const* pointer) -> void;

constexpr BufferTarget<GL_ARRAY_BUFFER> array_buffer_target {};
constexpr BufferTarget<GL_ELEMENT_ARRAY_BUFFER> element_array_buffer_target {};

} // namespace opengl

} // namespace sc

#endif // SHADOW_CAST_GL_BUFFER_HPP_INCLUDED
26 changes: 26 additions & 0 deletions src/gl/core.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
#include "gl/core.hpp"
#include "gl/error.hpp"
#include "platform/opengl.hpp"

namespace sc::opengl
{

auto viewport(GLint x, GLint y, GLsizei width, GLsizei height) -> void
{
gl().glViewport(x, y, width, height);
SC_CHECK_GL_ERROR("glViewport");
}

auto clear(GLenum mask) -> void
{
gl().glClear(mask);
SC_CHECK_GL_ERROR("glClear");
}

auto clear_color(float red, float green, float blue, float alpha) noexcept
-> void
{
gl().glClearColor(red, green, blue, alpha);
}

} // namespace sc::opengl
15 changes: 15 additions & 0 deletions src/gl/core.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
#ifndef SHADOW_CAST_GL_CORE_HPP_INCLUDED
#define SHADOW_CAST_GL_CORE_HPP_INCLUDED

#include <GL/gl.h>

namespace sc::opengl
{
auto viewport(GLint x, GLint y, GLsizei width, GLsizei height) -> void;
auto clear(GLenum mask) -> void;
auto clear_color(float red, float green, float blue, float alpha) noexcept
-> void;

} // namespace sc::opengl

#endif // SHADOW_CAST_GL_CORE_HPP_INCLUDED
Loading

0 comments on commit 0431b9f

Please sign in to comment.