option (WITH_WAYLAND "Build plugin of Wayland GBS" OFF)
option (WITH_WAYLAND_FBDEV "Build Wayland with FBDEV backend" OFF)
option (WITH_WAYLAND_X11 "Build Wayland with X11 backend" OFF)
+option (WITH_WAYLAND_DRM "Build Wayland with drm backend" OFF)
set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra")
endif(WITH_DESKTOP)
if (WITH_WAYLAND)
- if (NOT WITH_WAYLAND_FBDEV AND NOT WITH_WAYLAND_X11)
- message(FATAL_ERROR "Consider to specify WITH_WAYLAND_FBDEV or WITH_WAYLAND_X11")
- endif(NOT WITH_WAYLAND_FBDEV AND NOT WITH_WAYLAND_X11)
+ if (NOT WITH_WAYLAND_FBDEV AND NOT WITH_WAYLAND_X11 AND NOT WITH_WAYLAND_DRM)
+ message(FATAL_ERROR "Consider to specify WITH_WAYLAND_FBDEV or WITH_WAYLAND_X11 or WITH_WAYLAND_DRM")
+ endif(NOT WITH_WAYLAND_FBDEV AND NOT WITH_WAYLAND_X11 AND NOT WITH_WAYLAND_DRM)
if (WITH_WAYLAND_FBDEV AND WITH_WAYLAND_X11)
message(FATAL_ERROR "WITH_WAYLAND_FBDEV and WITH_WAYLAND_X11 can't be specified at the same time")
endif(WITH_WAYLAND_FBDEV AND WITH_WAYLAND_X11)
file(GLOB GRAPHIC_GRAPHICSYSTEM_INCLUDES
include/GraphicSystems/BaseGraphicSystem.h
include/GraphicSystems/GLESGraphicSystem.h
+ include/GraphicSystems/DrmGLESGraphicSystem.h
)
file(GLOB GRAPHIC_TEXTUREBINDERS_INCLUDES
if (WITH_WAYLAND)
set(GRAPHIC_LIB_NAME LayerManagerGraphicWaylandGLESv2)
+if (WITH_WAYLAND_FBDEV)
file(GLOB SOURCES
../Base/src/BaseRenderer.cpp
src/GraphicSystems/GLESGraphicSystem.cpp
src/WindowSystems/WaylandBaseWindowSystem.cpp
src/WindowSystems/WaylandFbdevWindowSystem.cpp
+ src/WindowSystems/WaylandServerinfoProtocol.cpp
+ src/TextureBinders/WaylandCopyGLES.cpp
+ src/TextureBinders/WaylandEglImage.cpp
+ src/Transformation/ViewportTransform.cpp
+ )
+elseif (WITH_WAYLAND_X11)
+file(GLOB SOURCES
+ ../Base/src/BaseRenderer.cpp
+ src/GraphicSystems/GLESGraphicSystem.cpp
+ src/WindowSystems/WaylandBaseWindowSystem.cpp
src/WindowSystems/WaylandX11WindowSystem.cpp
src/WindowSystems/WaylandServerinfoProtocol.cpp
src/TextureBinders/WaylandCopyGLES.cpp
src/TextureBinders/WaylandEglImage.cpp
src/Transformation/ViewportTransform.cpp
)
+elseif (WITH_WAYLAND_DRM)
+file(GLOB SOURCES
+ ../Base/src/BaseRenderer.cpp
+ src/GraphicSystems/GLESGraphicSystem.cpp
+ src/GraphicSystems/DrmGLESGraphicSystem.cpp
+ src/WindowSystems/WaylandBaseWindowSystem.cpp
+ src/WindowSystems/WaylandDrmWindowSystem.cpp
+ src/WindowSystems/WaylandServerinfoProtocol.cpp
+ src/TextureBinders/WaylandCopyGLES.cpp
+ src/TextureBinders/WaylandEglImage.cpp
+ src/Transformation/ViewportTransform.cpp
+ )
+endif ()
file(GLOB GRAPHIC_BASE_INCLUDES
../Base/include/*.h
file(GLOB GRAPHIC_GRAPHICSYSTEM_INCLUDES
include/GraphicSystems/BaseGraphicSystem.h
include/GraphicSystems/GLESGraphicSystem.h
+ include/GraphicSystems/DrmGLESGraphicSystem.h
)
file(GLOB GRAPHIC_TEXTUREBINDERS_INCLUDES
include/WindowSystems/WaylandBaseWindowSystem.h
include/WindowSystems/WaylandFbdevWindowSystem.h
include/WindowSystems/WaylandX11WindowSystem.h
+ include/WindowSystems/WaylandDrmWindowSystem.h
)
file(GLOB GRAPHIC_TRANSFORM_INCLUDES
set(GRAPHIC_NATIVE_LIBS ${GLX_LIBRARIES})
endif(WITH_GLX_LIB)
+set(GRAPHIC_DRM_LIBS ${UDEV_LIBRARIES} ${GBM_LIBRARIES} ${DRM_LIBRARIES})
+
if (WITH_WAYLAND)
-find_package (Wayland)
-include_directories(${WAYLAND_SERVER_INCLUDE_DIR})
-set(LIBS ${LIBS} ${WAYLAND_SERVER_LIBRARIES})
-if (WITH_WAYLAND_X11)
-set(LIBS ${LIBS} ${X11_X11_LIB})
-endif (WITH_WAYLAND_X11)
+ find_package (Wayland)
+ include_directories(${WAYLAND_SERVER_INCLUDE_DIR})
+ if (WITH_WAYLAND_DRM)
+ find_package (DRM)
+ include_directories(${DRM_INCLUDE_DIR})
+ set(LIBS ${LIBS} ${GRAPHIC_NATIVE_LIBS} ${GRAPHIC_DRM_LIBS} ${WAYLAND_SERVER_LIBRARIES} ${WAYLAND_EGL_LIBRARIES})
+ target_link_libraries(${GRAPHIC_LIB_NAME} ${LIBS})
+ else (WITH_WAYLAND_DRM)
+ set(LIBS ${LIBS} ${WAYLAND_SERVER_LIBRARIES})
+ endif (WITH_WAYLAND_DRM)
+ if (WITH_WAYLAND_X11)
+ set(LIBS ${LIBS} ${X11_X11_LIB})
+ endif (WITH_WAYLAND_X11)
else(WITH_WAYLAND)
-set(LIBS ${LIBS} ${CMAKE_THREAD_LIBS_INIT} ${X11_X11_LIB} ${X11_Xcomposite_LIB} ${X11_Xdamage_LIB} ${GRAPHIC_NATIVE_LIBS} LayerManagerUtils )
+ set(LIBS ${LIBS} ${CMAKE_THREAD_LIBS_INIT} ${X11_X11_LIB} ${X11_Xcomposite_LIB} ${X11_Xdamage_LIB} ${GRAPHIC_NATIVE_LIBS} LayerManagerUtils )
endif(WITH_WAYLAND)
target_link_libraries(${GRAPHIC_LIB_NAME} ${LIBS})
--- /dev/null
+/***************************************************************************
+ *
+ * Copyright 2010,2011 BMW Car IT GmbH
+ * Copyright (C) 2011 DENSO CORPORATION and Robert Bosch Car Multimedia Gmbh
+ *
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ****************************************************************************/
+
+#ifndef _DRMGLESGRAPHICSYSTEM_H_
+#define _DRMGLESGRAPHICSYSTEM_H_
+
+#include "GraphicSystems/BaseGraphicSystem.h"
+#include "GraphicSystems/GLESGraphicSystem.h"
+#include "ShaderProgramFactory.h"
+#include "EGL/egl.h"
+#include "EGL/eglext.h"
+#include "GLES2/gl2.h"
+#include "GLES2/gl2ext.h"
+#include "Log.h"
+#include "Shader.h"
+
+#include "wayland-util.h"
+
+#include <xf86drm.h>
+#include <xf86drmMode.h>
+
+struct gbm_device;
+
+struct DrmMode {
+ uint32_t flags;
+ int32_t width;
+ int32_t height;
+ uint32_t refresh;
+ drmModeModeInfo modeInfo;
+ wl_list link;
+};
+
+struct DrmOutput {
+ struct wl_list link;
+ struct DrmMode* currentMode;
+ struct wl_list modeList;
+ uint32_t crtcID;
+ uint32_t connectorID;
+ drmModeCrtcPtr orgCrtc;
+ GLuint rbo[2];
+ uint32_t fbID[2];
+ EGLImageKHR image[2];
+ struct gbm_bo* bo[2];
+ uint32_t current;
+ int fdDev;
+};
+
+class DrmGLESGraphicSystem: public GLESGraphicsystem
+{
+// functions
+public:
+ DrmGLESGraphicSystem(int windowWidth, int windowHeight,
+ PfnShaderProgramCreator shaderProgram);
+ virtual ~DrmGLESGraphicSystem();
+
+ virtual bool init(EGLNativeDisplayType display, EGLNativeWindowType window);
+ virtual void activateGraphicContext();
+ virtual void releaseGraphicContext();
+ virtual void swapBuffers();
+ virtual void applyLayerMatrix(IlmMatrix& matrix);
+
+// proterties
+private:
+ struct wl_list m_outputList;
+
+ gbm_device* m_gbm;
+ int m_fdDev;
+ uint32_t* m_crtcs;
+ int m_crtcsNum;
+ uint32_t m_crtcAllocator;
+ uint32_t m_connectorAllocator;
+
+ PFNGLEGLIMAGETARGETRENDERBUFFERSTORAGEOESPROC m_pfGLEglImageTargetRenderbufferStorageOES;
+ PFNEGLCREATEIMAGEKHRPROC m_pfEglCreateImageKHR;
+ PFNEGLDESTROYIMAGEKHRPROC m_pfEglDestroyImageKHR;
+ PFNEGLBINDWAYLANDDISPLAYWL m_pfEglBindWaylandDisplayWL;
+ PFNEGLUNBINDWAYLANDDISPLAYWL m_pfEglUnbindWaylandDisplayWL;
+
+// private functions
+private:
+ bool initializeSystem();
+ bool createOutputs();
+ int createOutputForConnector(drmModeRes* resources, drmModeConnector* connector, int x, int y);
+ int drmOutputAddMode(struct DrmOutput* output, drmModeModeInfo* info);
+ int drmOutputPrepareRender(struct DrmOutput* output);
+};
+
+#endif /* _DRMGLESGRAPHICSYSTEM_H_ */
#include "EGL/egl.h"
#include "Log.h"
#include "Shader.h"
+
+class IlmMatrix;
+
/* uncomment if layer drawing needed */
/* #define DRAW_LAYER_DEBUG */
class GLESGraphicsystem: public BaseGraphicSystem<EGLNativeDisplayType, EGLNativeWindowType>
}
virtual void renderSurface(Surface* surface);
- virtual Shader *pickOptimizedShader(Shader* currentShader, const ShaderProgram::CommonUniforms curUniforms);
+ virtual Shader *pickOptimizedShader(Shader* currentShader, const ShaderProgram::CommonUniforms& curUniforms);
+ virtual void applyLayerMatrix(IlmMatrix& matrix);
protected:
int m_windowWidth;
{
public:
WaylandBaseWindowSystem(const char* displayname, int width, int height, Scene* pScene);
- ~WaylandBaseWindowSystem();
+ virtual ~WaylandBaseWindowSystem();
bool init(BaseGraphicSystem<EGLNativeDisplayType, EGLNativeWindowType>* sys);
bool start();
void stop();
--- /dev/null
+/***************************************************************************
+ *
+ * Copyright 2010, 2011 BMW Car IT GmbH
+ * Copyright (C) 2011 DENSO CORPORATION and Robert Bosch Car Multimedia Gmbh
+ *
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *
+ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
+ * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
+ * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
+ * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ ****************************************************************************/
+
+#ifndef _WAYLANDDRMWINDOWSYSTEM_H_
+#define _WAYLANDDRMWINDOWSYSTEM_H_
+#include "WindowSystems/WaylandBaseWindowSystem.h"
+
+struct gbm_device;
+
+class WaylandDrmWindowSystem: public WaylandBaseWindowSystem
+{
+public:
+ WaylandDrmWindowSystem(const char* displayname, int width, int height, Scene* pScene);
+ virtual ~WaylandDrmWindowSystem();
+
+protected:
+ virtual bool createNativeContext();
+ virtual bool initGraphicSystem();
+
+private:
+ int m_fdDev;
+ gbm_device* m_gbm;
+};
+
+#endif /* _WAYLANDDRMWINDOWSYSTEM_H_ */
--- /dev/null
+/***************************************************************************
+ *
+ * Copyright 2010,2011 BMW Car IT GmbH
+ * Copyright (C) 2011 DENSO CORPORATION and Robert Bosch Car Multimedia Gmbh
+ *
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ****************************************************************************/
+
+#include "GraphicSystems/DrmGLESGraphicSystem.h"
+#include "IlmMatrix.h"
+#include "string.h"
+#include "EGL/egl.h"
+#include "EGL/eglext.h"
+#include "GLES2/gl2.h"
+#include "Bitmap.h"
+#include "Transformation/ViewportTransform.h"
+#include "PlatformSurfaces/WaylandPlatformSurface.h"
+#include "WindowSystems/WaylandBaseWindowSystem.h"
+
+#include "wayland-server.h"
+
+#include <errno.h>
+#include <drm_fourcc.h>
+#include <drm_mode.h>
+#include <gbm.h>
+#include <libudev.h>
+
+static drmModeModeInfo builtin_800x480_for_Crossville = {
+ 31746,
+ 800, 859, 999, 999, 0,
+ 480, 507, 538, 524, 0,
+ 0,
+ DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC,
+ 0,
+ "800x480"
+};
+
+DrmGLESGraphicSystem::DrmGLESGraphicSystem(int windowWidth, int windowHeight,
+ PfnShaderProgramCreator shaderProgram)
+: GLESGraphicsystem(windowWidth, windowHeight, shaderProgram)
+, m_gbm(NULL)
+, m_fdDev(-1)
+, m_crtcs(NULL)
+, m_crtcsNum(0)
+, m_crtcAllocator(0)
+, m_connectorAllocator(0)
+{
+ LOG_DEBUG("DrmGLESGraphicSystem", "creating DrmGLESGraphicSystem");
+
+ m_pfGLEglImageTargetRenderbufferStorageOES =
+ (PFNGLEGLIMAGETARGETRENDERBUFFERSTORAGEOESPROC)eglGetProcAddress("glEGLImageTargetRenderbufferStorageOES");
+ m_pfEglCreateImageKHR = (PFNEGLCREATEIMAGEKHRPROC)eglGetProcAddress("eglCreateImageKHR");
+ m_pfEglDestroyImageKHR = (PFNEGLDESTROYIMAGEKHRPROC)eglGetProcAddress("eglDestroyImageKHR");
+ m_pfEglBindWaylandDisplayWL = (PFNEGLBINDWAYLANDDISPLAYWL)eglGetProcAddress("eglBindWaylandDisplayWL");
+ m_pfEglUnbindWaylandDisplayWL = (PFNEGLUNBINDWAYLANDDISPLAYWL)eglGetProcAddress("eglUnbindWaylandDisplayWL");
+
+ if (!m_pfGLEglImageTargetRenderbufferStorageOES ||
+ !m_pfEglCreateImageKHR ||
+ !m_pfEglDestroyImageKHR ||
+ !m_pfEglBindWaylandDisplayWL ||
+ !m_pfEglUnbindWaylandDisplayWL)
+ {
+ LOG_ERROR("DrmGLESGraphicSystem", "Query EGL extensions failed.");
+ }
+}
+
+DrmGLESGraphicSystem::~DrmGLESGraphicSystem()
+{
+ WaylandBaseWindowSystem* windowSystem = dynamic_cast<WaylandBaseWindowSystem*>(m_baseWindowSystem);
+ struct wl_display* wlDisplay = windowSystem->getNativeDisplayHandle();
+
+ glFramebufferRenderbuffer(GL_FRAMEBUFFER,
+ GL_COLOR_ATTACHMENT0,
+ GL_RENDERBUFFER,
+ 0);
+ glBindRenderbuffer(GL_RENDERBUFFER, 0);
+
+ struct DrmOutput* output = NULL;
+ wl_list_for_each(output, &m_outputList, link) {
+ glDeleteRenderbuffers(2, output->rbo);
+ for (int i = 0; i < 2; ++i){
+ drmModeRmFB(m_fdDev, output->fbID[i]);
+ gbm_bo_destroy(output->bo[i]);
+ }
+ free(output);
+ }
+
+ if (wlDisplay)
+ m_pfEglUnbindWaylandDisplayWL(m_eglDisplay, wlDisplay);
+}
+
+bool DrmGLESGraphicSystem::init(EGLNativeDisplayType display, EGLNativeWindowType NativeWindow)
+{
+ bool ret = true;
+ LOG_DEBUG("DrmGLESGraphicSystem", "init..display:" << display <<
+ ", NativeWindow:" << NativeWindow);
+
+ m_nativeDisplay = display;
+ m_nativeWindow = NativeWindow;
+
+ wl_list_init(&m_outputList);
+
+ m_gbm = (gbm_device*)display;
+ if (m_gbm == NULL)
+ {
+ LOG_ERROR("DrmGLESGraphicSystem", "gbm device is NULL.");
+ return false;
+ }
+
+ m_fdDev = gbm_device_get_fd(m_gbm);
+ if (m_fdDev < 0)
+ {
+ LOG_ERROR("DrmGLESGraphicSystem", "failed to get device fd.");
+ return false;
+ }
+
+ m_eglDisplay = eglGetDisplay((EGLNativeDisplayType)m_gbm);
+ if (m_eglDisplay == EGL_NO_DISPLAY)
+ {
+ LOG_ERROR("DrmGLESGraphicSystem", "failed to get EGL display.");
+ return false;
+ }
+
+ EGLint major, minor;
+ if (!eglInitialize(m_eglDisplay, &major, &minor))
+ {
+ LOG_ERROR("DrmGLESGraphicSystem", "failed to initialising EGL.");
+ return false;
+ }
+
+ const char* ext = eglQueryString(m_eglDisplay, EGL_EXTENSIONS);
+ if (!strstr(ext, "EGL_KHR_surfaceless_gles2"))
+ {
+ LOG_ERROR("DrmGLESGraphicSystem", "EGL_KHR_surfaceless_gles2 not avaiable.");
+ return false;
+ }
+
+ eglBindAPI(EGL_OPENGL_ES_API);
+
+ EGLint contextAttrs[] = {
+ EGL_CONTEXT_CLIENT_VERSION, 2,
+ EGL_NONE
+ };
+ m_eglContext = eglCreateContext(m_eglDisplay, NULL, EGL_NO_CONTEXT, contextAttrs);
+ if (!m_eglContext)
+ {
+ LOG_ERROR("DrmGLESGraphicSystem", "failed to create EGL context.");
+ return false;
+ }
+
+ if (!eglMakeCurrent(m_eglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, m_eglContext))
+ {
+ LOG_ERROR("DrmGLESGraphicSystem", "failed to make context current.");
+ return false;
+ }
+ LOG_INFO("DrmGLESGraphicSystem", "make context current.");
+
+ eglSwapInterval(m_eglDisplay, 1); // TODO: does not seem to work
+
+ if (!initializeSystem())
+ {
+ LOG_ERROR("DrmGLESGraphicSystem", "failed to initialize system.");
+ return false;
+ }
+
+ if (!GLESGraphicsystem::initOpenGLES(m_windowWidth, m_windowHeight))
+ {
+ LOG_ERROR("DrmGLESGraphicSystem", "failed to initialize gles.");
+ return false;
+ }
+
+ return ret;
+}
+
+void DrmGLESGraphicSystem::activateGraphicContext()
+{
+ struct DrmOutput* output = NULL;
+ wl_list_for_each(output, &m_outputList, link)
+ {
+ drmOutputPrepareRender(output);
+ }
+}
+
+void DrmGLESGraphicSystem::releaseGraphicContext()
+{
+ glFramebufferRenderbuffer(GL_FRAMEBUFFER,
+ GL_COLOR_ATTACHMENT0,
+ GL_RENDERBUFFER,
+ NULL);
+}
+
+bool DrmGLESGraphicSystem::initializeSystem()
+{
+ LOG_DEBUG("DrmGLESGraphicSystem", "initializeSystem IN");
+
+ WaylandBaseWindowSystem* windowSystem = dynamic_cast<WaylandBaseWindowSystem*>(m_baseWindowSystem);
+ struct wl_display* wlDisplay = windowSystem->getNativeDisplayHandle();
+
+ GLuint fbo;
+ glGenFramebuffers(1, &fbo);
+ glBindFramebuffer(GL_FRAMEBUFFER, fbo);
+
+ // bind display
+ m_pfEglBindWaylandDisplayWL(m_eglDisplay, wlDisplay);
+
+ if (!createOutputs())
+ return false;
+
+ LOG_DEBUG("DrmGLESGraphicSystem", "initializeSystem OUT");
+
+ return true;
+}
+
+bool DrmGLESGraphicSystem::createOutputs()
+{
+ LOG_DEBUG("DrmGLESGraphicSystem", "createOutputs IN");
+
+ drmModeConnector* connector;
+ drmModeRes* resources;
+ int x = 0, y = 0;
+
+ resources = drmModeGetResources(m_fdDev);
+ if (!resources)
+ {
+ LOG_DEBUG("DrmGLESGraphicSystem", "drmModeGetResources failed.");
+ return false;
+ }
+
+ m_crtcs = (uint32_t*)calloc(resources->count_crtcs, sizeof(uint32_t));
+ if (!m_crtcs)
+ {
+ return false;
+ }
+ m_crtcsNum = resources->count_crtcs;
+
+ memcpy(m_crtcs, resources->crtcs, sizeof(uint32_t) * m_crtcsNum);
+
+ for (int ii = 0; ii < resources->count_connectors; ++ii)
+ {
+ connector = drmModeGetConnector(m_fdDev, resources->connectors[ii]);
+ if (connector == NULL)
+ continue;
+
+ if (connector->connection == DRM_MODE_CONNECTED)
+ {
+ if (createOutputForConnector(resources, connector, x, y) < 0)
+ {
+ drmModeFreeConnector(connector);
+ continue;
+ }
+
+ //x += container_of(m_outputList.prev, struct DrmOutput, link)->currentMode->width;
+ }
+
+ drmModeFreeConnector(connector);
+ break;
+ }
+
+ if (wl_list_empty(&m_outputList))
+ {
+ LOG_ERROR("DrmGLESGraphicSystem", "DrmOutput list is empty.");
+ return false;
+ }
+
+ drmModeFreeResources(resources);
+
+ LOG_DEBUG("DrmGLESGraphicSystem", "createOutputs OUT");
+ return true;
+}
+
+int DrmGLESGraphicSystem::createOutputForConnector(drmModeRes* resources,
+ drmModeConnector* connector,
+ int, int)
+{
+ LOG_DEBUG("DrmGLESGraphicSystem", "createOutputForConnector IN");
+ int ret;
+ int ii;
+ drmModeEncoder* encoder;
+ unsigned handle, stride;
+ struct DrmMode* drmMode = NULL;
+
+ encoder = drmModeGetEncoder(m_fdDev, connector->encoders[0]);
+ if (encoder == NULL){
+ LOG_ERROR("DrmGLESGraphicSystem", "No encoder for connector.");
+ return -1;
+ }
+
+ for (ii = 0; ii < resources->count_crtcs; ++ii)
+ {
+ if (encoder->possible_crtcs & (1 << ii) &&
+ !(m_crtcAllocator & (1 << resources->crtcs[ii])))
+ {
+ break;
+ }
+ }
+ if (ii == resources->count_crtcs)
+ {
+ LOG_ERROR("DrmGLESGraphicSystem", "No usable crtc for encoder.");
+ return -1;
+ }
+
+ DrmOutput* output = (DrmOutput*)malloc(sizeof *output);
+ if (output == NULL)
+ {
+ drmModeFreeEncoder(encoder);
+ return -1;
+ }
+ memset(output, 0x00, sizeof *output);
+
+ output->fdDev = m_fdDev;
+ output->crtcID = resources->crtcs[ii];
+ output->connectorID = connector->connector_id;
+
+ m_crtcAllocator |= (1 << output->crtcID);
+ m_connectorAllocator |= (1 << output->connectorID);
+
+ wl_list_init(&output->modeList);
+
+ output->orgCrtc = drmModeGetCrtc(m_fdDev, output->crtcID);
+ drmModeFreeEncoder(encoder);
+
+ for (ii = 0; ii < connector->count_modes; ++ii)
+ {
+ if (drmOutputAddMode(output, &connector->modes[ii]))
+ goto err_free;
+ }
+
+ if (connector->count_modes == 0)
+ {
+ if (drmOutputAddMode(output, &builtin_800x480_for_Crossville))
+ goto err_free;
+ }
+
+ drmMode = container_of(output->modeList.next, struct DrmMode, link);
+ output->currentMode = drmMode;
+ drmMode->flags = WL_OUTPUT_MODE_CURRENT | WL_OUTPUT_MODE_PREFERRED;
+
+ glGenRenderbuffers(2, output->rbo);
+ for (ii = 0; ii < 2; ++ii)
+ {
+ glBindRenderbuffer(GL_RENDERBUFFER, output->rbo[ii]);
+
+ output->bo[ii] = gbm_bo_create(m_gbm,
+ output->currentMode->width,
+ output->currentMode->height,
+ GBM_BO_FORMAT_XRGB8888,
+ GBM_BO_USE_SCANOUT |
+ GBM_BO_USE_RENDERING);
+ if (!output->bo[ii])
+ {
+ LOG_ERROR("DrmGLESGraphicSystem", "failed to create bo.");
+ goto err_bufs;
+ }
+
+ output->image[ii] = m_pfEglCreateImageKHR(m_eglDisplay,
+ NULL,
+ EGL_NATIVE_PIXMAP_KHR,
+ output->bo[ii],
+ NULL);
+ if (!output->image[ii])
+ goto err_bufs;
+
+ m_pfGLEglImageTargetRenderbufferStorageOES(GL_RENDERBUFFER,
+ output->image[ii]);
+
+ stride = gbm_bo_get_pitch(output->bo[ii]);
+ handle = gbm_bo_get_handle(output->bo[ii]).u32;
+
+ ret = drmModeAddFB(m_fdDev, drmMode->width, drmMode->height,
+ 24, 32, stride, handle, &output->fbID[ii]);
+ if (ret)
+ {
+ LOG_ERROR("DrmGLESGraphicSystem", "failed to add fb(" << ii << ")");
+ goto err_bufs;
+ }
+ }
+
+ output->current = 0;
+ glFramebufferRenderbuffer(GL_FRAMEBUFFER,
+ GL_COLOR_ATTACHMENT0,
+ GL_RENDERBUFFER,
+ output->rbo[output->current]);
+
+ ret = drmModeSetCrtc(m_fdDev, output->crtcID,
+ output->fbID[output->current ^ 1], 0, 0,
+ &output->connectorID, 1,
+ &drmMode->modeInfo);
+ if (ret)
+ {
+ LOG_ERROR("DrmGLESGraphicSystem", "failed to set mode.");
+ goto err_fb;
+ }
+
+ wl_list_insert(m_outputList.prev, &output->link);
+
+ LOG_DEBUG("DrmGLESGraphicSystem", "createOutputForConnector OUT (NORMAL)");
+ return 0;
+
+err_fb:
+ glFramebufferRenderbuffer(GL_FRAMEBUFFER,
+ GL_COLOR_ATTACHMENT0,
+ GL_RENDERBUFFER,
+ 0);
+
+err_bufs:
+ for (ii = 0; ii < 2; ++ii){
+ if (output->fbID[ii] != 0)
+ drmModeRmFB(m_fdDev, output->fbID[ii]);
+ if (output->image[ii])
+ m_pfEglDestroyImageKHR(m_eglDisplay, output->image[ii]);
+ if (output->bo[ii])
+ gbm_bo_destroy(output->bo[ii]);
+ }
+ glBindRenderbuffer(GL_RENDERBUFFER, 0);
+ glDeleteRenderbuffers(2, output->rbo);
+
+err_free:
+ drmModeFreeCrtc(output->orgCrtc);
+ m_crtcAllocator &= ~(1 << output->crtcID);
+ m_connectorAllocator &= ~(1 << output->connectorID);
+
+ free(output);
+ LOG_DEBUG("DrmGLESGraphicSystem", "createOutputForConnector OUT (ERROR)");
+ return -1;
+}
+
+int DrmGLESGraphicSystem::drmOutputAddMode(struct DrmOutput* output, drmModeModeInfo* info)
+{
+ struct DrmMode* mode;
+
+ mode = (struct DrmMode*)malloc(sizeof *mode);
+ if (mode == NULL)
+ return -1;
+
+ mode->flags = 0;
+ mode->width = info->hdisplay;
+ mode->height = info->vdisplay;
+ mode->refresh = info->vrefresh;
+ mode->modeInfo = *info;
+ wl_list_insert(output->modeList.prev, &mode->link);
+
+ return 0;
+}
+
+int DrmGLESGraphicSystem::drmOutputPrepareRender(struct DrmOutput* output)
+{
+ glFramebufferRenderbuffer(GL_FRAMEBUFFER,
+ GL_COLOR_ATTACHMENT0,
+ GL_RENDERBUFFER,
+ output->rbo[output->current]);
+
+ if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
+ {
+ LOG_ERROR("DrmGLESGraphicSystem", "glCheckFramebufferStatus() failed.");
+ return -1;
+ }
+ return 0;
+}
+
+void DrmGLESGraphicSystem::swapBuffers()
+{
+ LOG_DEBUG("DrmGLESGraphicSystem", "swapBuffers IN");
+
+ struct DrmOutput* output = NULL;
+
+ wl_list_for_each(output, &m_outputList, link)
+ {
+ glFinish();
+
+ output->current ^= 1;
+ uint32_t fbID = output->fbID[output->current ^ 1];
+#if 0
+ LOG_INFO("DrmGLESGraphicSystem", "fbID = " << fbID << ", current = " << output->current);
+#endif
+ if (drmModePageFlip(m_fdDev, output->crtcID, fbID, 0, NULL) < 0)
+ {
+ LOG_ERROR("DrmGLESGraphicSystem", "queueing pageflip failed");
+ }
+ }
+
+ LOG_DEBUG("DrmGLESGraphicSystem", "swapBuffers OUT");
+}
+
+void DrmGLESGraphicSystem::applyLayerMatrix(IlmMatrix& matrix)
+{
+ GLESGraphicsystem::applyLayerMatrix(matrix);
+ // reverse Y axis
+ matrix.f[5] *= -1.0f;
+}
}
//this is a particularly simple function currently, but it will likely be expanded as more shaders and effects are implemented.
-Shader *GLESGraphicsystem::pickOptimizedShader(Shader* currentShader, const ShaderProgram::CommonUniforms curUniforms)
+Shader *GLESGraphicsystem::pickOptimizedShader(Shader* currentShader, const ShaderProgram::CommonUniforms& curUniforms)
{
Shader * retShader = currentShader;
}
+void GLESGraphicsystem::applyLayerMatrix(IlmMatrix& matrix)
+{
+ IlmMatrixRotateZ(matrix, m_currentLayer->getOrientation() * 90.0f);
+}
+
void GLESGraphicsystem::renderSurface(Surface* surface)
{
// LOG_DEBUG("GLESGraphicsystem", "renderSurface " << surface->getID());
ViewportTransform::transformRectangleToTextureCoordinates(targetSurfaceSource, surface->OriginalSourceWidth, surface->OriginalSourceHeight, textureCoordinates);
glBindBuffer(GL_ARRAY_BUFFER, m_vbo);
- IlmMatrixRotateZ(layerMatrix, m_currentLayer->getOrientation() * 90.0f);
+ applyLayerMatrix(layerMatrix);
// update all common uniforms, scale values to display size
uniforms.x = (float)targetSurfaceDestination.x / m_displayWidth;
uniforms.y = (float)targetSurfaceDestination.y / m_displayHeight;;
****************************************************************************/
#include "TextureBinders/WaylandEglImage.h"
+#include "config.h"
#include <EGL/egl.h>
#include <EGL/eglext.h>
#include <GLES2/gl2ext.h>
LOG_DEBUG("WaylandEglImage", "creating EGL Image from client buffer");
if (nativeSurface->eglImage)
{
+#ifdef WITH_WAYLAND_DRM
+ if (nativeSurface->texture){
+ glBindTexture(GL_TEXTURE_2D, 0);
+ glDeleteTextures(1,&nativeSurface->texture);
+ }
+#else
m_pfEglDestroyImageKHR(m_eglDisplay, nativeSurface->eglImage);
glDeleteTextures(1,&nativeSurface->texture);
+#endif // WITH_WAYLAND_DRM
nativeSurface->eglImage = 0;
nativeSurface->texture = 0;
}
--- /dev/null
+/***************************************************************************
+*
+* Copyright 2010, 2011 BMW Car IT GmbH
+* Copyright (C) 2011 DENSO CORPORATION and Robert Bosch Car Multimedia Gmbh
+*
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*
+*
+* THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
+* SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+* FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
+* SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
+* RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
+* CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+*
+****************************************************************************/
+
+#include "WindowSystems/WaylandDrmWindowSystem.h"
+#include "Log.h"
+#include <linux/fb.h>
+#include <fcntl.h>
+#include <iomanip>
+
+#include <gbm.h>
+#include <libudev.h>
+#include <xf86drm.h>
+#include <xf86drmMode.h>
+
+static const char default_seat[] = "seat0";
+
+WaylandDrmWindowSystem::WaylandDrmWindowSystem(const char* displayname, int width, int height, Scene* pScene)
+: WaylandBaseWindowSystem(displayname, width, height, pScene)
+, m_fdDev(-1), m_gbm(NULL)
+{
+ LOG_DEBUG("WaylandDrmWindowSystem", "creating WaylandDrmWindowSystem width:" << width << " height:" << height);
+}
+
+WaylandDrmWindowSystem::~WaylandDrmWindowSystem()
+{
+ if (m_gbm != NULL)
+ gbm_device_destroy(m_gbm);
+ if (m_fdDev >= 0)
+ drmDropMaster(m_fdDev);
+}
+
+bool WaylandDrmWindowSystem::initGraphicSystem()
+{
+ graphicSystem->setBaseWindowSystem(this);
+ return graphicSystem->init((EGLNativeDisplayType)m_gbm, (EGLNativeWindowType)NULL);
+}
+
+bool WaylandDrmWindowSystem::createNativeContext()
+{
+ struct udev* udev;
+ struct udev_device *device, *drm_device;
+ struct udev_enumerate* e;
+ struct udev_list_entry* entry;
+ const char *path, *device_seat;
+ const char *seat = default_seat;
+
+ udev = udev_new();
+ if (udev == NULL)
+ {
+ LOG_ERROR("WaylandDrmWindowSystem", "failed to initialize udev context.");
+ return false;
+ }
+
+ e = udev_enumerate_new(udev);
+ udev_enumerate_add_match_subsystem(e, "drm");
+ udev_enumerate_add_match_sysname(e, "card[0-9]*");
+
+ udev_enumerate_scan_devices(e);
+ drm_device = NULL;
+ udev_list_entry_foreach(entry, udev_enumerate_get_list_entry(e))
+ {
+ path = udev_list_entry_get_name(entry);
+ device = udev_device_new_from_syspath(udev, path);
+ device_seat = udev_device_get_property_value(device, "ID_SEAT");
+ if (!device_seat)
+ device_seat = default_seat;
+ if (strcmp(device_seat, seat) == 0)
+ {
+ drm_device = device;
+ break;
+ }
+ udev_device_unref(device);
+ }
+
+ if (drm_device == NULL)
+ {
+ LOG_ERROR("WaylandDrmWindowSystem", "no drm device found");
+ return false;
+ }
+
+ const char* filename;
+
+ filename = udev_device_get_devnode(drm_device);
+ m_fdDev = open(filename, O_RDWR | O_CLOEXEC);
+ if (m_fdDev < 0)
+ {
+ LOG_ERROR("WaylandDrmWindowSystem", "failed to open device");
+ return false;
+ }
+
+ LOG_DEBUG("WaylandDrmWindowSystem", "Device name: " << filename << " fd: " << m_fdDev);
+
+ m_gbm = gbm_create_device(m_fdDev);
+ if (m_gbm == NULL)
+ {
+ LOG_ERROR("WaylandDrmWindowSystem", "failed to create gbm device");
+ return false;
+ }
+
+ udev_device_unref(drm_device);
+
+ LOG_DEBUG("WaylandDrmWindowSystem", "SUCCESS:create gbm device");
+ return true;
+}
find_package(Wayland REQUIRED)
include_directories(${WAYLAND_SERVER_INCLUDE_DIR})
+include_directories(${DRM_INCLUDE_DIR})
find_package(EGL REQUIRED)
include_directories(${EGL_INCLUDE_DIR})
#include "ShaderProgramGLES.h"
#include "TextureBinders/WaylandCopyGLES.h"
#include "TextureBinders/WaylandEglImage.h"
+#ifdef WITH_WAYLAND_FBDEV
#include "WindowSystems/WaylandFbdevWindowSystem.h"
+#endif // WITH_WAYLAND_FBDEV
+#ifdef WITH_WAYLAND_X11
#include "WindowSystems/WaylandX11WindowSystem.h"
+#endif // WITH_WAYLAND_X11
+#ifdef WITH_WAYLAND_DRM
+#include "WindowSystems/WaylandDrmWindowSystem.h"
+#include "GraphicSystems/DrmGLESGraphicSystem.h"
+#endif // WITH_WAYLAND_DRM
WaylandGLESRenderer::WaylandGLESRenderer(Scene* pScene)
: BaseRenderer(pScene)
#ifdef WITH_WAYLAND_X11
m_pWindowSystem = new WaylandX11WindowSystem(displayname, width, height, m_pScene);
#endif
+#ifdef WITH_WAYLAND_DRM
+ m_pWindowSystem = new WaylandDrmWindowSystem(displayname, width, height, m_pScene);
+#endif
if( m_pWindowSystem == NULL )
{
LOG_ERROR("WaylandGLESRenderer", "Window system is not specified. Consider to specify WITH_WAYLAND_X11 or WITH_WAYLAND_FBDEV");
goto fail; // TODO bad style
}
+#ifdef WITH_WAYLAND_DRM
+ m_pGraphicSystem = new DrmGLESGraphicSystem(width,height, ShaderProgramGLES::createProgram);
+#else
m_pGraphicSystem = new GLESGraphicsystem(width,height, ShaderProgramGLES::createProgram);
+#endif
if (!m_pWindowSystem->init((BaseGraphicSystem<EGLNativeDisplayType, EGLNativeWindowType>*) m_pGraphicSystem))
{
--- /dev/null
+############################################################################
+#
+# Copyright 2010, 2011 BMW Car IT GmbH
+# Copyright (C) 2011 DENSO CORPORATION and Robert Bosch Car Multimedia Gmbh
+#
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+############################################################################
+
+FIND_PATH(UDEV_INCLUDE_DIR /libudev.h
+/usr/include
+)
+
+FIND_LIBRARY(UDEV_LIBRARIES
+NAMES udev
+PATHS /usr/lib
+)
+
+FIND_PATH(GBM_INCLUDE_DIR /gbm.h
+/usr/include
+)
+
+FIND_LIBRARY(GBM_LIBRARIES
+NAMES gbm
+PATHS /usr/lib
+)
+
+FIND_PATH(DRM_INCLUDE_DIR /drm.h
+/usr/include/drm /usr/include/libdrm
+)
+
+FIND_LIBRARY(DRM_LIBRARIES
+NAMES drm
+PATHS /usr/lib
+)
+
+SET( DRM_FOUND "NO" )
+IF(UDEV_LIBRARIES AND GBM_LIBRARIES AND DRM_LIBRARIES)
+ SET( DRM_FOUND "YES" )
+ message(STATUS "Found udev libs: ${UDEV_LIBRARIES}")
+ message(STATUS "Found udev includes: ${UDEV_INCLUDE_DIR}")
+ message(STATUS "Found gbm libs: ${GBM_LIBRARIES}")
+ message(STATUS "Found gbm includes: ${GBM_INCLUDE_DIR}")
+ message(STATUS "Found drm includes: ${DRM_INCLUDE_DIR}")
+ message(STATUS "Found drm libs: ${DRM_LIBRARIES}")
+ENDIF(UDEV_LIBRARIES AND GBM_LIBRARIES AND DRM_LIBRARIES)
+
+MARK_AS_ADVANCED(
+ UDEV_INCLUDE_DIR
+ UDEV_LIBRARIES
+ GBM_INCLUDE_DIR
+ GBM_LIBRARIES
+ DRM_INCLUDE_DIR
+ DRM_LIBRARIES
+)
// use automotive dlt for logging
#cmakedefine WITH_DLT
+// use wayland-drm compositor
+#cmakedefine WITH_WAYLAND_DRM
+
//-----------------------------------------------------------------------------
// human readable report
//-----------------------------------------------------------------------------
LOG_DEBUG("Config", "WITH_WAYLAND = ${WITH_WAYLAND}"); \
LOG_DEBUG("Config", "WITH_WAYLAND_FBDEV = ${WITH_WAYLAND_FBDEV}"); \
LOG_DEBUG("Config", "WITH_WAYLAND_X11 = ${WITH_WAYLAND_X11}"); \
+ LOG_DEBUG("Config", "WITH_WAYLAND_DRM = ${WITH_WAYLAND_DRM}"); \
LOG_DEBUG("Config", "WITH_XTHREADS = ${WITH_XTHREADS}"); \
LOG_DEBUG("Config", "WITH_DLT = ${WITH_DLT}");