Managing to get GBM working
This commit is contained in:
@ -4,7 +4,7 @@
|
|||||||
# https://opensource.org/licenses/MIT
|
# https://opensource.org/licenses/MIT
|
||||||
|
|
||||||
#################################### CMAKE #####################################
|
#################################### CMAKE #####################################
|
||||||
cmake_minimum_required(VERSION 3.15)
|
cmake_minimum_required(VERSION 3.13)
|
||||||
set(CMAKE_C_STANDARD 99)
|
set(CMAKE_C_STANDARD 99)
|
||||||
set(CMAKE_C_STANDARD_REQUIRED ON)
|
set(CMAKE_C_STANDARD_REQUIRED ON)
|
||||||
|
|
||||||
@ -14,15 +14,19 @@ include(FetchContent)
|
|||||||
#Vars
|
#Vars
|
||||||
set(DEPS_DIR "${PROJECT_BINARY_DIR}/_deps")
|
set(DEPS_DIR "${PROJECT_BINARY_DIR}/_deps")
|
||||||
|
|
||||||
set(SDL2_DIR ${CMAKE_CURRENT_LIST_DIR}/lib/SDL2)
|
|
||||||
|
set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/modules)
|
||||||
|
|
||||||
|
# set(SDL2_DIR ${CMAKE_CURRENT_LIST_DIR}/lib/SDL2)
|
||||||
|
|
||||||
################################## Settings ####################################
|
################################## Settings ####################################
|
||||||
# Platform Settings
|
# Platform Settings
|
||||||
set(SETTING_PLATFORM_GLFW 1)
|
set(SETTING_PLATFORM_GLFW 1)
|
||||||
set(SETTING_PLATFORM_SDL 2)
|
set(SETTING_PLATFORM_SDL 2)
|
||||||
set(SETTING_PLATFORM SETTING_PLATFORM_SDL)
|
set(SETTING_PLATFORM_GBM 3)
|
||||||
|
set(SETTING_PLATFORM SETTING_PLATFORM_GBM)
|
||||||
|
|
||||||
set(SETTING_USE_GLAD 1)
|
set(SETTING_USE_GLAD 0)
|
||||||
|
|
||||||
# Game Settings
|
# Game Settings
|
||||||
set(SETTING_GAME_POKER 1)
|
set(SETTING_GAME_POKER 1)
|
||||||
@ -57,12 +61,22 @@ if(${SETTING_PLATFORM} EQUAL ${SETTING_PLATFORM_SDL})
|
|||||||
list(APPEND HEADER_FILES ${HDRS})
|
list(APPEND HEADER_FILES ${HDRS})
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
# GBM Sources
|
||||||
|
if(${SETTING_PLATFORM} EQUAL ${SETTING_PLATFORM_GBM})
|
||||||
|
file(GLOB_RECURSE SRC ${CMAKE_SOURCE_DIR}/platform/gbm/*.c)
|
||||||
|
file(GLOB_RECURSE HDRS ${CMAKE_SOURCE_DIR}/platform/gbm/*.h)
|
||||||
|
list(APPEND SOURCE_FILES ${SRC})
|
||||||
|
list(APPEND HEADER_FILES ${HDRS})
|
||||||
|
endif()
|
||||||
|
|
||||||
file(COPY ${CMAKE_CURRENT_LIST_DIR}/assets DESTINATION ${CMAKE_CURRENT_BINARY_DIR})
|
file(COPY ${CMAKE_CURRENT_LIST_DIR}/assets DESTINATION ${CMAKE_CURRENT_BINARY_DIR})
|
||||||
|
|
||||||
##################################### LIBS #####################################
|
##################################### LIBS #####################################
|
||||||
include_directories(${CMAKE_SOURCE_DIR}/lib/stb)
|
include_directories(${CMAKE_SOURCE_DIR}/lib/stb)
|
||||||
include_directories(${CMAKE_SOURCE_DIR}/include)
|
include_directories(${CMAKE_SOURCE_DIR}/include)
|
||||||
include_directories(${CMAKE_CURRENT_BINARY_DIR})
|
include_directories(${CMAKE_CURRENT_BINARY_DIR})
|
||||||
|
include_directories(/usr/lib/aarch64-linux-gnu/)
|
||||||
|
|
||||||
|
|
||||||
################################## EXECUTABLE ##################################
|
################################## EXECUTABLE ##################################
|
||||||
add_executable(${PROJECT_NAME} ${HEADER_FILES} ${SOURCE_FILES})
|
add_executable(${PROJECT_NAME} ${HEADER_FILES} ${SOURCE_FILES})
|
||||||
@ -72,6 +86,7 @@ add_executable(${PROJECT_NAME} ${HEADER_FILES} ${SOURCE_FILES})
|
|||||||
# Math
|
# Math
|
||||||
if(NOT WIN32)
|
if(NOT WIN32)
|
||||||
target_link_libraries(${PROJECT_NAME} m)
|
target_link_libraries(${PROJECT_NAME} m)
|
||||||
|
target_link_libraries(${PROJECT_NAME} ${CMAKE_DL_LIBS})
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# GLAD
|
# GLAD
|
||||||
@ -95,22 +110,31 @@ endif()
|
|||||||
|
|
||||||
# SDL
|
# SDL
|
||||||
if(${SETTING_PLATFORM} EQUAL ${SETTING_PLATFORM_SDL})
|
if(${SETTING_PLATFORM} EQUAL ${SETTING_PLATFORM_SDL})
|
||||||
# add_subdirectory(${CMAKE_SOURCE_DIR}/lib/glad)
|
|
||||||
# target_link_libraries(${PROJECT_NAME} glad)
|
|
||||||
find_package(SDL2 REQUIRED)
|
find_package(SDL2 REQUIRED)
|
||||||
include_directories(${SDL2_INCLUDE_DIRS})
|
include_directories(${SDL2_INCLUDE_DIRS})
|
||||||
target_link_libraries(${PROJECT_NAME} ${SDL2_LIBRARIES})
|
target_link_libraries(${PROJECT_NAME} ${SDL2_LIBRARIES})
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# CGLM
|
#GBM
|
||||||
if(NOT cglm_FOUND)
|
if(${SETTING_PLATFORM} EQUAL ${SETTING_PLATFORM_GBM})
|
||||||
FetchContent_Declare(
|
find_package(Libdrm REQUIRED)
|
||||||
cglm
|
find_package(gbm REQUIRED)
|
||||||
GIT_REPOSITORY https://github.com/recp/cglm
|
target_link_libraries(${PROJECT_NAME} Libdrm::Libdrm)
|
||||||
GIT_TAG v0.8.3
|
target_link_libraries(${PROJECT_NAME} gbm::gbm)
|
||||||
)
|
target_link_libraries(${PROJECT_NAME} EGL GLESv2)
|
||||||
FetchContent_MakeAvailable(cglm)
|
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
|
||||||
|
# CGLM
|
||||||
|
add_subdirectory(${CMAKE_SOURCE_DIR}/lib/cglm)
|
||||||
|
# if(NOT cglm_FOUND)
|
||||||
|
# FetchContent_Declare(
|
||||||
|
# cglm
|
||||||
|
# GIT_REPOSITORY https://github.com/recp/cglm
|
||||||
|
# GIT_TAG v0.8.3
|
||||||
|
# )
|
||||||
|
# FetchContent_MakeAvailable(cglm)
|
||||||
|
# endif()
|
||||||
target_link_libraries(${PROJECT_NAME} cglm)
|
target_link_libraries(${PROJECT_NAME} cglm)
|
||||||
|
|
||||||
# OpenGL
|
# OpenGL
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
// Platform Settings
|
// Platform Settings
|
||||||
#cmakedefine SETTING_PLATFORM_GLFW @SETTING_PLATFORM_GLFW@
|
#cmakedefine SETTING_PLATFORM_GLFW @SETTING_PLATFORM_GLFW@
|
||||||
#cmakedefine SETTING_PLATFORM_SDL @SETTING_PLATFORM_SDL@
|
#cmakedefine SETTING_PLATFORM_SDL @SETTING_PLATFORM_SDL@
|
||||||
|
#cmakedefine SETTING_PLATFORM_GBM @SETTING_PLATFORM_GBM@
|
||||||
#cmakedefine SETTING_PLATFORM @SETTING_PLATFORM@
|
#cmakedefine SETTING_PLATFORM @SETTING_PLATFORM@
|
||||||
|
|
||||||
#cmakedefine SETTING_USE_GLAD @SETTING_USE_GLAD@
|
#cmakedefine SETTING_USE_GLAD @SETTING_USE_GLAD@
|
||||||
|
@ -17,9 +17,19 @@
|
|||||||
|
|
||||||
#if SETTING_PLATFORM == SETTING_PLATFORM_GLFW
|
#if SETTING_PLATFORM == SETTING_PLATFORM_GLFW
|
||||||
#elif SETTING_PLATFORM == SETTING_PLATFORM_SDL
|
#elif SETTING_PLATFORM == SETTING_PLATFORM_SDL
|
||||||
#include <SDL.h>
|
#include <SDL2/SDL.h>
|
||||||
#include <SDL_opengl.h>
|
#include <SDL2/SDL_opengl.h>
|
||||||
#include <SDL_opengles2.h>
|
#include <SDL2/SDL_opengles2.h>
|
||||||
|
#elif SETTING_PLATFORM == SETTING_PLATFORM_GBM
|
||||||
|
#include <xf86drm.h>
|
||||||
|
#include <xf86drmMode.h>
|
||||||
|
#include <gbm.h>
|
||||||
|
|
||||||
|
#define GL_GLEXT_PROTOTYPES 1
|
||||||
|
#include <GLES2/gl2.h>
|
||||||
|
#include <GLES2/gl2ext.h>
|
||||||
|
#include <EGL/egl.h>
|
||||||
|
#include <EGL/eglext.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <stb_image.h>
|
#include <stb_image.h>
|
||||||
|
105
modules/FindLibdrm.cmake
Normal file
105
modules/FindLibdrm.cmake
Normal file
@ -0,0 +1,105 @@
|
|||||||
|
#.rst:
|
||||||
|
# FindLibdrm
|
||||||
|
# -------
|
||||||
|
#
|
||||||
|
# Try to find libdrm on a Unix system.
|
||||||
|
#
|
||||||
|
# This will define the following variables:
|
||||||
|
#
|
||||||
|
# ``Libdrm_FOUND``
|
||||||
|
# True if (the requested version of) libdrm is available
|
||||||
|
# ``Libdrm_VERSION``
|
||||||
|
# The version of libdrm
|
||||||
|
# ``Libdrm_LIBRARIES``
|
||||||
|
# This can be passed to target_link_libraries() instead of the ``Libdrm::Libdrm``
|
||||||
|
# target
|
||||||
|
# ``Libdrm_INCLUDE_DIRS``
|
||||||
|
# This should be passed to target_include_directories() if the target is not
|
||||||
|
# used for linking
|
||||||
|
# ``Libdrm_DEFINITIONS``
|
||||||
|
# This should be passed to target_compile_options() if the target is not
|
||||||
|
# used for linking
|
||||||
|
#
|
||||||
|
# If ``Libdrm_FOUND`` is TRUE, it will also define the following imported target:
|
||||||
|
#
|
||||||
|
# ``Libdrm::Libdrm``
|
||||||
|
# The libdrm library
|
||||||
|
#
|
||||||
|
# In general we recommend using the imported target, as it is easier to use.
|
||||||
|
# Bear in mind, however, that if the target is in the link interface of an
|
||||||
|
# exported library, it must be made available by the package config file.
|
||||||
|
|
||||||
|
#=============================================================================
|
||||||
|
# SPDX-FileCopyrightText: 2014 Alex Merry <alex.merry@kde.org>
|
||||||
|
# SPDX-FileCopyrightText: 2014 Martin Gräßlin <mgraesslin@kde.org>
|
||||||
|
#
|
||||||
|
# SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
#=============================================================================
|
||||||
|
|
||||||
|
if(CMAKE_VERSION VERSION_LESS 2.8.12)
|
||||||
|
message(FATAL_ERROR "CMake 2.8.12 is required by FindLibdrm.cmake")
|
||||||
|
endif()
|
||||||
|
if(CMAKE_MINIMUM_REQUIRED_VERSION VERSION_LESS 2.8.12)
|
||||||
|
message(AUTHOR_WARNING "Your project should require at least CMake 2.8.12 to use FindLibdrm.cmake")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(NOT WIN32)
|
||||||
|
# Use pkg-config to get the directories and then use these values
|
||||||
|
# in the FIND_PATH() and FIND_LIBRARY() calls
|
||||||
|
find_package(PkgConfig)
|
||||||
|
pkg_check_modules(PKG_Libdrm QUIET libdrm)
|
||||||
|
|
||||||
|
set(Libdrm_DEFINITIONS ${PKG_Libdrm_CFLAGS_OTHER})
|
||||||
|
set(Libdrm_VERSION ${PKG_Libdrm_VERSION})
|
||||||
|
|
||||||
|
find_path(Libdrm_INCLUDE_DIR
|
||||||
|
NAMES
|
||||||
|
xf86drm.h
|
||||||
|
HINTS
|
||||||
|
${PKG_Libdrm_INCLUDE_DIRS}
|
||||||
|
)
|
||||||
|
find_library(Libdrm_LIBRARY
|
||||||
|
NAMES
|
||||||
|
drm
|
||||||
|
HINTS
|
||||||
|
${PKG_Libdrm_LIBRARY_DIRS}
|
||||||
|
)
|
||||||
|
|
||||||
|
include(FindPackageHandleStandardArgs)
|
||||||
|
find_package_handle_standard_args(Libdrm
|
||||||
|
FOUND_VAR
|
||||||
|
Libdrm_FOUND
|
||||||
|
REQUIRED_VARS
|
||||||
|
Libdrm_LIBRARY
|
||||||
|
Libdrm_INCLUDE_DIR
|
||||||
|
VERSION_VAR
|
||||||
|
Libdrm_VERSION
|
||||||
|
)
|
||||||
|
|
||||||
|
if(Libdrm_FOUND AND NOT TARGET Libdrm::Libdrm)
|
||||||
|
add_library(Libdrm::Libdrm UNKNOWN IMPORTED)
|
||||||
|
set_target_properties(Libdrm::Libdrm PROPERTIES
|
||||||
|
IMPORTED_LOCATION "${Libdrm_LIBRARY}"
|
||||||
|
INTERFACE_COMPILE_OPTIONS "${Libdrm_DEFINITIONS}"
|
||||||
|
INTERFACE_INCLUDE_DIRECTORIES "${Libdrm_INCLUDE_DIR}"
|
||||||
|
INTERFACE_INCLUDE_DIRECTORIES "${Libdrm_INCLUDE_DIR}/libdrm"
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
mark_as_advanced(Libdrm_LIBRARY Libdrm_INCLUDE_DIR)
|
||||||
|
|
||||||
|
# compatibility variables
|
||||||
|
set(Libdrm_LIBRARIES ${Libdrm_LIBRARY})
|
||||||
|
set(Libdrm_INCLUDE_DIRS ${Libdrm_INCLUDE_DIR} "${Libdrm_INCLUDE_DIR}/libdrm")
|
||||||
|
set(Libdrm_VERSION_STRING ${Libdrm_VERSION})
|
||||||
|
|
||||||
|
else()
|
||||||
|
message(STATUS "FindLibdrm.cmake cannot find libdrm on Windows systems.")
|
||||||
|
set(Libdrm_FOUND FALSE)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
include(FeatureSummary)
|
||||||
|
set_package_properties(Libdrm PROPERTIES
|
||||||
|
URL "https://wiki.freedesktop.org/dri/"
|
||||||
|
DESCRIPTION "Userspace interface to kernel DRM services."
|
||||||
|
)
|
104
modules/Findgbm.cmake
Normal file
104
modules/Findgbm.cmake
Normal file
@ -0,0 +1,104 @@
|
|||||||
|
#.rst:
|
||||||
|
# Findgbm
|
||||||
|
# -------
|
||||||
|
#
|
||||||
|
# Try to find gbm on a Unix system.
|
||||||
|
#
|
||||||
|
# This will define the following variables:
|
||||||
|
#
|
||||||
|
# ``gbm_FOUND``
|
||||||
|
# True if (the requested version of) gbm is available
|
||||||
|
# ``gbm_VERSION``
|
||||||
|
# The version of gbm
|
||||||
|
# ``gbm_LIBRARIES``
|
||||||
|
# This can be passed to target_link_libraries() instead of the ``gbm::gbm``
|
||||||
|
# target
|
||||||
|
# ``gbm_INCLUDE_DIRS``
|
||||||
|
# This should be passed to target_include_directories() if the target is not
|
||||||
|
# used for linking
|
||||||
|
# ``gbm_DEFINITIONS``
|
||||||
|
# This should be passed to target_compile_options() if the target is not
|
||||||
|
# used for linking
|
||||||
|
#
|
||||||
|
# If ``gbm_FOUND`` is TRUE, it will also define the following imported target:
|
||||||
|
#
|
||||||
|
# ``gbm::gbm``
|
||||||
|
# The gbm library
|
||||||
|
#
|
||||||
|
# In general we recommend using the imported target, as it is easier to use.
|
||||||
|
# Bear in mind, however, that if the target is in the link interface of an
|
||||||
|
# exported library, it must be made available by the package config file.
|
||||||
|
|
||||||
|
#=============================================================================
|
||||||
|
# SPDX-FileCopyrightText: 2014 Alex Merry <alex.merry@kde.org>
|
||||||
|
# SPDX-FileCopyrightText: 2014 Martin Gräßlin <mgraesslin@kde.org>
|
||||||
|
#
|
||||||
|
# SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
#=============================================================================
|
||||||
|
|
||||||
|
if(CMAKE_VERSION VERSION_LESS 2.8.12)
|
||||||
|
message(FATAL_ERROR "CMake 2.8.12 is required by Findgbm.cmake")
|
||||||
|
endif()
|
||||||
|
if(CMAKE_MINIMUM_REQUIRED_VERSION VERSION_LESS 2.8.12)
|
||||||
|
message(AUTHOR_WARNING "Your project should require at least CMake 2.8.12 to use Findgbm.cmake")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(NOT WIN32)
|
||||||
|
# Use pkg-config to get the directories and then use these values
|
||||||
|
# in the FIND_PATH() and FIND_LIBRARY() calls
|
||||||
|
find_package(PkgConfig)
|
||||||
|
pkg_check_modules(PKG_gbm QUIET gbm)
|
||||||
|
|
||||||
|
set(gbm_DEFINITIONS ${PKG_gbm_CFLAGS_OTHER})
|
||||||
|
set(gbm_VERSION ${PKG_gbm_VERSION})
|
||||||
|
|
||||||
|
find_path(gbm_INCLUDE_DIR
|
||||||
|
NAMES
|
||||||
|
gbm.h
|
||||||
|
HINTS
|
||||||
|
${PKG_gbm_INCLUDE_DIRS}
|
||||||
|
)
|
||||||
|
find_library(gbm_LIBRARY
|
||||||
|
NAMES
|
||||||
|
gbm
|
||||||
|
HINTS
|
||||||
|
${PKG_gbm_LIBRARY_DIRS}
|
||||||
|
)
|
||||||
|
|
||||||
|
include(FindPackageHandleStandardArgs)
|
||||||
|
find_package_handle_standard_args(gbm
|
||||||
|
FOUND_VAR
|
||||||
|
gbm_FOUND
|
||||||
|
REQUIRED_VARS
|
||||||
|
gbm_LIBRARY
|
||||||
|
gbm_INCLUDE_DIR
|
||||||
|
VERSION_VAR
|
||||||
|
gbm_VERSION
|
||||||
|
)
|
||||||
|
|
||||||
|
if(gbm_FOUND AND NOT TARGET gbm::gbm)
|
||||||
|
add_library(gbm::gbm UNKNOWN IMPORTED)
|
||||||
|
set_target_properties(gbm::gbm PROPERTIES
|
||||||
|
IMPORTED_LOCATION "${gbm_LIBRARY}"
|
||||||
|
INTERFACE_COMPILE_OPTIONS "${gbm_DEFINITIONS}"
|
||||||
|
INTERFACE_INCLUDE_DIRECTORIES "${gbm_INCLUDE_DIR}"
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
mark_as_advanced(gbm_LIBRARY gbm_INCLUDE_DIR)
|
||||||
|
|
||||||
|
# compatibility variables
|
||||||
|
set(gbm_LIBRARIES ${gbm_LIBRARY})
|
||||||
|
set(gbm_INCLUDE_DIRS ${gbm_INCLUDE_DIR})
|
||||||
|
set(gbm_VERSION_STRING ${gbm_VERSION})
|
||||||
|
|
||||||
|
else()
|
||||||
|
message(STATUS "Findgbm.cmake cannot find gbm on Windows systems.")
|
||||||
|
set(gbm_FOUND FALSE)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
include(FeatureSummary)
|
||||||
|
set_package_properties(gbm PROPERTIES
|
||||||
|
URL "https://www.mesa3d.org"
|
||||||
|
DESCRIPTION "Mesa gbm library."
|
||||||
|
)
|
434
platform/gbm/gbm.c
Normal file
434
platform/gbm/gbm.c
Normal file
@ -0,0 +1,434 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2021 Dominic Masters
|
||||||
|
*
|
||||||
|
* This software is released under the MIT License.
|
||||||
|
* https://opensource.org/licenses/MIT
|
||||||
|
*/
|
||||||
|
#include "gbm.h"
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
|
#include <xf86drm.h>
|
||||||
|
#include <xf86drmMode.h>
|
||||||
|
#include <gbm.h>
|
||||||
|
|
||||||
|
#define GL_GLEXT_PROTOTYPES 1
|
||||||
|
#include <GLES2/gl2.h>
|
||||||
|
#include <GLES2/gl2ext.h>
|
||||||
|
#include <EGL/egl.h>
|
||||||
|
#include <EGL/eglext.h>
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
|
#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
|
||||||
|
|
||||||
|
|
||||||
|
static struct {
|
||||||
|
EGLDisplay display;
|
||||||
|
EGLConfig config;
|
||||||
|
EGLContext context;
|
||||||
|
EGLSurface surface;
|
||||||
|
GLuint program;
|
||||||
|
GLint modelviewmatrix, modelviewprojectionmatrix, normalmatrix;
|
||||||
|
GLuint vbo;
|
||||||
|
GLuint positionsoffset, colorsoffset, normalsoffset;
|
||||||
|
} gl;
|
||||||
|
|
||||||
|
static struct {
|
||||||
|
struct gbm_device *dev;
|
||||||
|
struct gbm_surface *surface;
|
||||||
|
} gbm;
|
||||||
|
|
||||||
|
static struct {
|
||||||
|
int fd;
|
||||||
|
drmModeModeInfo *mode;
|
||||||
|
uint32_t crtc_id;
|
||||||
|
uint32_t connector_id;
|
||||||
|
} drm;
|
||||||
|
|
||||||
|
struct drm_fb {
|
||||||
|
struct gbm_bo *bo;
|
||||||
|
uint32_t fb_id;
|
||||||
|
};
|
||||||
|
|
||||||
|
static uint32_t find_crtc_for_encoder(
|
||||||
|
const drmModeRes *resources, const drmModeEncoder *encoder
|
||||||
|
) {
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < resources->count_crtcs; i++) {
|
||||||
|
/* possible_crtcs is a bitmask as described here:
|
||||||
|
* https://dvdhrm.wordpress.com/2012/09/13/linux-drm-mode-setting-api
|
||||||
|
*/
|
||||||
|
const uint32_t crtc_mask = 1 << i;
|
||||||
|
const uint32_t crtc_id = resources->crtcs[i];
|
||||||
|
if(encoder->possible_crtcs & crtc_mask) {
|
||||||
|
return crtc_id;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* no match found */
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint32_t find_crtc_for_connector(
|
||||||
|
const drmModeRes *resources, const drmModeConnector *connector
|
||||||
|
) {
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < connector->count_encoders; i++) {
|
||||||
|
const uint32_t encoder_id = connector->encoders[i];
|
||||||
|
drmModeEncoder *encoder = drmModeGetEncoder(drm.fd, encoder_id);
|
||||||
|
|
||||||
|
if(encoder) {
|
||||||
|
const uint32_t crtc_id = find_crtc_for_encoder(resources, encoder);
|
||||||
|
|
||||||
|
drmModeFreeEncoder(encoder);
|
||||||
|
if(crtc_id != 0) {
|
||||||
|
return crtc_id;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* no match found */
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int32_t drmInit(void) {
|
||||||
|
drmModeRes *resources;
|
||||||
|
drmModeConnector *connector = NULL;
|
||||||
|
drmModeEncoder *encoder = NULL;
|
||||||
|
int i, area;
|
||||||
|
|
||||||
|
drm.fd = open("/dev/dri/card0", O_RDWR);
|
||||||
|
|
||||||
|
if(drm.fd < 0) {
|
||||||
|
printf("could not open drm device\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
resources = drmModeGetResources(drm.fd);
|
||||||
|
if(!resources) {
|
||||||
|
printf("drmModeGetResources failed: %s\n", strerror(errno));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Find an existing connected connector.
|
||||||
|
for (i = 0; i < resources->count_connectors; i++) {
|
||||||
|
connector = drmModeGetConnector(drm.fd, resources->connectors[i]);
|
||||||
|
if(connector->connection == DRM_MODE_CONNECTED) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
drmModeFreeConnector(connector);
|
||||||
|
connector = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Did we find a connector?
|
||||||
|
if(!connector) {
|
||||||
|
printf("No connected connector!\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Now get the mode to use, based on resolution.
|
||||||
|
for (i = 0, area = 0; i < connector->count_modes; i++) {
|
||||||
|
drmModeModeInfo *current_mode = &connector->modes[i];
|
||||||
|
|
||||||
|
if(current_mode->type & DRM_MODE_TYPE_PREFERRED) drm.mode = current_mode;
|
||||||
|
|
||||||
|
int current_area = current_mode->hdisplay * current_mode->vdisplay;
|
||||||
|
if(current_area >= area) {
|
||||||
|
drm.mode = current_mode;
|
||||||
|
area = current_area;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Did we find the best mode?
|
||||||
|
if(!drm.mode) {
|
||||||
|
printf("could not find mode!\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Now find a display encoder
|
||||||
|
for (i = 0; i < resources->count_encoders; i++) {
|
||||||
|
encoder = drmModeGetEncoder(drm.fd, resources->encoders[i]);
|
||||||
|
if(encoder->encoder_id == connector->encoder_id) break;
|
||||||
|
drmModeFreeEncoder(encoder);
|
||||||
|
encoder = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Is there an encoder?
|
||||||
|
if(encoder) {
|
||||||
|
drm.crtc_id = encoder->crtc_id;
|
||||||
|
} else {
|
||||||
|
// No, use a CRTC
|
||||||
|
uint32_t crtc_id = find_crtc_for_connector(resources, connector);
|
||||||
|
if(crtc_id == 0) {
|
||||||
|
printf("no crtc found!\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
drm.crtc_id = crtc_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update the DRM with the new connector ID.
|
||||||
|
drm.connector_id = connector->connector_id;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int32_t gbmInit(void) {
|
||||||
|
gbm.dev = gbm_create_device(drm.fd);
|
||||||
|
|
||||||
|
gbm.surface = gbm_surface_create(
|
||||||
|
gbm.dev,
|
||||||
|
drm.mode->vdisplay, drm.mode->vdisplay,
|
||||||
|
GBM_FORMAT_XRGB8888,
|
||||||
|
GBM_BO_USE_SCANOUT | GBM_BO_USE_RENDERING
|
||||||
|
);
|
||||||
|
if(!gbm.surface) {
|
||||||
|
printf("failed to create gbm surface\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int32_t glInit(void) {
|
||||||
|
EGLint major, minor, n;
|
||||||
|
GLuint vertex_shader, fragment_shader;
|
||||||
|
GLint ret;
|
||||||
|
|
||||||
|
// Set up the attributes for the EGL
|
||||||
|
static const EGLint context_attribs[] = {
|
||||||
|
EGL_CONTEXT_CLIENT_VERSION, 2,
|
||||||
|
EGL_NONE
|
||||||
|
};
|
||||||
|
|
||||||
|
static const EGLint config_attribs[] = {
|
||||||
|
EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
|
||||||
|
EGL_RED_SIZE, 1,
|
||||||
|
EGL_GREEN_SIZE, 1,
|
||||||
|
EGL_BLUE_SIZE, 1,
|
||||||
|
EGL_ALPHA_SIZE, 0,
|
||||||
|
EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
|
||||||
|
EGL_NONE
|
||||||
|
};
|
||||||
|
|
||||||
|
// Get the "display getter".
|
||||||
|
PFNEGLGETPLATFORMDISPLAYEXTPROC getDisplay = NULL;
|
||||||
|
getDisplay = (void *)eglGetProcAddress("eglGetPlatformDisplayEXT");
|
||||||
|
if(getDisplay == NULL) {
|
||||||
|
printf("Failed to get GBM-EGL Display.\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Now get the display with that getter.
|
||||||
|
gl.display = getDisplay(EGL_PLATFORM_GBM_KHR, gbm.dev, NULL);
|
||||||
|
|
||||||
|
// Initialize EGL
|
||||||
|
if(!eglInitialize(gl.display, &major, &minor)) {
|
||||||
|
printf("failed to initialize\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Bind OpenGL API
|
||||||
|
if(!eglBindAPI(EGL_OPENGL_ES_API)) {
|
||||||
|
printf("Failed to bind api\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!eglChooseConfig(gl.display, config_attribs, &gl.config, 1, &n) || n != 1) {
|
||||||
|
printf("failed to choose config: %d\n", n);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create a new EGL Context.
|
||||||
|
gl.context = eglCreateContext(
|
||||||
|
gl.display, gl.config, EGL_NO_CONTEXT, context_attribs
|
||||||
|
);
|
||||||
|
if(gl.context == NULL) {
|
||||||
|
printf("failed to create context\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create the EGL Surface to render to.
|
||||||
|
gl.surface = eglCreateWindowSurface(gl.display, gl.config, gbm.surface, NULL);
|
||||||
|
if(gl.surface == EGL_NO_SURFACE) {
|
||||||
|
printf("failed to create egl surface\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update the current EGL Context
|
||||||
|
eglMakeCurrent(gl.display, gl.surface, gl.surface, gl.context);
|
||||||
|
printf("GL Extensions: \"%s\"\n", glGetString(GL_EXTENSIONS));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void drm_fb_destroy_callback(struct gbm_bo *bo, void *data) {
|
||||||
|
struct drm_fb *fb = data;
|
||||||
|
struct gbm_device *gbm = gbm_bo_get_device(bo);
|
||||||
|
|
||||||
|
if(fb->fb_id) drmModeRmFB(drm.fd, fb->fb_id);
|
||||||
|
free(fb);
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct drm_fb * drm_fb_get_from_bo(struct gbm_bo *bo) {
|
||||||
|
struct drm_fb *fb = gbm_bo_get_user_data(bo);
|
||||||
|
uint32_t width, height, stride, handle;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
if(fb)
|
||||||
|
return fb;
|
||||||
|
|
||||||
|
fb = calloc(1, sizeof *fb);
|
||||||
|
fb->bo = bo;
|
||||||
|
|
||||||
|
width = gbm_bo_get_width(bo);
|
||||||
|
height = gbm_bo_get_height(bo);
|
||||||
|
stride = gbm_bo_get_stride(bo);
|
||||||
|
handle = gbm_bo_get_handle(bo).u32;
|
||||||
|
|
||||||
|
ret = drmModeAddFB(drm.fd, width, height, 24, 32, stride, handle, &fb->fb_id);
|
||||||
|
if(ret) {
|
||||||
|
printf("failed to create fb: %s\n", strerror(errno));
|
||||||
|
free(fb);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
gbm_bo_set_user_data(bo, fb, drm_fb_destroy_callback);
|
||||||
|
return fb;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void page_flip_handler(
|
||||||
|
int fd, unsigned int frame, unsigned int sec, unsigned int usec, void *data
|
||||||
|
) {
|
||||||
|
int *waiting_for_flip = data;
|
||||||
|
*waiting_for_flip = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t main(int argc, char *argv[]) {
|
||||||
|
fd_set fds;
|
||||||
|
drmEventContext evctx = {
|
||||||
|
.version = DRM_EVENT_CONTEXT_VERSION,
|
||||||
|
.page_flip_handler = page_flip_handler,
|
||||||
|
};
|
||||||
|
struct gbm_bo *bo;
|
||||||
|
struct drm_fb *fb;
|
||||||
|
int32_t ret;
|
||||||
|
int32_t width, height;
|
||||||
|
|
||||||
|
// Init the DRM
|
||||||
|
ret = drmInit();
|
||||||
|
if(ret) {
|
||||||
|
printf("failed to initialize DRM\n");
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ???
|
||||||
|
FD_ZERO(&fds);
|
||||||
|
FD_SET(0, &fds);
|
||||||
|
FD_SET(drm.fd, &fds);
|
||||||
|
|
||||||
|
// Init the GBM
|
||||||
|
ret = gbmInit();
|
||||||
|
if(ret) {
|
||||||
|
printf("failed to initialize GBM\n");
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Now Initialize OpenGL/OpenGL ES
|
||||||
|
ret = glInit();
|
||||||
|
if(ret) {
|
||||||
|
printf("failed to initialize EGL\n");
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Do a once clear of the color buffer
|
||||||
|
eglSwapBuffers(gl.display, gl.surface);
|
||||||
|
|
||||||
|
// Now uh?
|
||||||
|
bo = gbm_surface_lock_front_buffer(gbm.surface);
|
||||||
|
fb = drm_fb_get_from_bo(bo);
|
||||||
|
width = gbm_bo_get_width(bo);
|
||||||
|
height = gbm_bo_get_height(bo);
|
||||||
|
stride = gbm_bo_get_stride(bo);
|
||||||
|
|
||||||
|
// ?
|
||||||
|
ret = drmModeSetCrtc(
|
||||||
|
drm.fd, drm.crtc_id, fb->fb_id, 0, 0, &drm.connector_id, 1, drm.mode
|
||||||
|
);
|
||||||
|
if(ret) {
|
||||||
|
printf("failed to set mode: %s\n", strerror(errno));
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Init Game
|
||||||
|
game_t *game = malloc(sizeof(game_t));
|
||||||
|
printf("Game is %zu bytes.\n", sizeof(game_t));
|
||||||
|
printf("Resolution is %i x %i x %i\n", width, height, stride);
|
||||||
|
renderSetResolution(&game->engine.render, (int32_t)width, (int32_t)height);
|
||||||
|
if(!gameInit(game)) {
|
||||||
|
printf("Game Init Error\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (1) {
|
||||||
|
struct gbm_bo *next_bo;
|
||||||
|
int waiting_for_flip = 1;
|
||||||
|
|
||||||
|
// Draw
|
||||||
|
float fDelta = 0.016f;
|
||||||
|
if(!gameUpdate(game, fDelta)) break;
|
||||||
|
// Drawn
|
||||||
|
|
||||||
|
// Swap the EGL Buffers
|
||||||
|
eglSwapBuffers(gl.display, gl.surface);
|
||||||
|
|
||||||
|
// Now do a back buffer flip
|
||||||
|
next_bo = gbm_surface_lock_front_buffer(gbm.surface);
|
||||||
|
fb = drm_fb_get_from_bo(next_bo);
|
||||||
|
|
||||||
|
// ?
|
||||||
|
ret = drmModePageFlip(drm.fd, drm.crtc_id, fb->fb_id,
|
||||||
|
DRM_MODE_PAGE_FLIP_EVENT, &waiting_for_flip
|
||||||
|
);
|
||||||
|
if(ret) {
|
||||||
|
printf("Failed to queue page flip: %s\n", strerror(errno));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ?
|
||||||
|
while(waiting_for_flip) {
|
||||||
|
ret = select(drm.fd + 1, &fds, NULL, NULL, NULL);
|
||||||
|
if(ret < 0) {
|
||||||
|
printf("select err: %s\n", strerror(errno));
|
||||||
|
return ret;
|
||||||
|
} else if(ret == 0) {
|
||||||
|
printf("select timeout!\n");
|
||||||
|
return -1;
|
||||||
|
} else if(FD_ISSET(0, &fds)) {
|
||||||
|
printf("user interrupted!\n");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
drmHandleEvent(drm.fd, &evctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ?
|
||||||
|
gbm_surface_release_buffer(gbm.surface, bo);
|
||||||
|
bo = next_bo;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Game has finished running, cleanup.
|
||||||
|
gameDispose(game);
|
||||||
|
free(game);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
34
platform/gbm/gbm.h
Normal file
34
platform/gbm/gbm.h
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
// Copyright (c) 2021 Dominic Masters
|
||||||
|
//
|
||||||
|
// This software is released under the MIT License.
|
||||||
|
// https://opensource.org/licenses/MIT
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
|
#include <xf86drm.h>
|
||||||
|
#include <xf86drmMode.h>
|
||||||
|
#include <gbm.h>
|
||||||
|
|
||||||
|
#define GL_GLEXT_PROTOTYPES 1
|
||||||
|
#include <GLES2/gl2.h>
|
||||||
|
#include <GLES2/gl2ext.h>
|
||||||
|
#include <EGL/egl.h>
|
||||||
|
#include <EGL/eglext.h>
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#include <dawn/dawn.h>
|
||||||
|
#include "../../src/display/render.h"
|
||||||
|
#include "../../src/game/game.h"
|
||||||
|
#include "../../src/input/input.h"
|
||||||
|
int32_t main(int32_t argc, char *argv[]);
|
@ -25,11 +25,11 @@ void frameBufferInit(framebuffer_t *fb, int32_t w, int32_t h) {
|
|||||||
// Render Buffer
|
// Render Buffer
|
||||||
glGenRenderbuffers(1, &fb->rboId);
|
glGenRenderbuffers(1, &fb->rboId);
|
||||||
glBindRenderbuffer(GL_RENDERBUFFER, fb->rboId);
|
glBindRenderbuffer(GL_RENDERBUFFER, fb->rboId);
|
||||||
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, w, h);
|
// glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, w, h);
|
||||||
glBindRenderbuffer(GL_RENDERBUFFER, 0);
|
glBindRenderbuffer(GL_RENDERBUFFER, 0);
|
||||||
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT,
|
// glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT,
|
||||||
GL_RENDERBUFFER, fb->rboId
|
// GL_RENDERBUFFER, fb->rboId
|
||||||
);
|
// );
|
||||||
|
|
||||||
if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {
|
if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {
|
||||||
uint32_t error;
|
uint32_t error;
|
||||||
|
@ -17,6 +17,8 @@ void renderInit() {
|
|||||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||||
glDepthMask(GL_TRUE);
|
glDepthMask(GL_TRUE);
|
||||||
glDepthFunc(GL_LEQUAL);
|
glDepthFunc(GL_LEQUAL);
|
||||||
|
|
||||||
|
glClearColor(1.0, 0, 0, 1.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void renderFrameStart(render_t *render) {
|
void renderFrameStart(render_t *render) {
|
||||||
|
@ -30,8 +30,10 @@ void textureInit(texture_t *texture, int32_t width, int32_t height,
|
|||||||
// glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
// glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||||
// glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
// glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||||
|
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
|
// glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
|
// glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user