Add support for offscreen rendering with EGL. Added new class CanvasEGL, and a test.

This commit is contained in:
Dave Pugmire 2016-06-15 09:48:45 -04:00
parent dfc160a155
commit af1daf2f66
6 changed files with 360 additions and 0 deletions

92
CMake/FindEGL.cmake Normal file

@ -0,0 +1,92 @@
# Try to find EGL library and include dir.
# Once done this will define
#
# EGL_FOUND - true if EGL has been found
# EGL_INCLUDE_DIR - where the EGL/egl.h and KHR/khrplatform.h can be found
# EGL_LIBRARY - link this to use libEGL.so.1
# EGL_opengl_LIBRARY - link with these two libraries instead of the gl library
# EGL_gldispatch_LIBRARY for full OpenGL support through EGL
# EGL_LIBRARIES - all EGL related libraries: EGL, OpenGL, GLdispatch
if(NOT EGL_INCLUDE_DIR)
# If we have a root defined look there first
if(EGL_ROOT)
find_path(EGL_INCLUDE_DIR EGL/egl.h PATHS ${EGL_ROOT}/include
NO_DEFAULT_PATH
)
endif()
if(NOT EGL_INCLUDE_DIR)
find_path(EGL_INCLUDE_DIR EGL/egl.h PATHS
/usr/local/include
/usr/include
)
endif()
endif()
if(NOT EGL_LIBRARY)
# If we have a root defined look there first
if(EGL_ROOT)
find_library(EGL_LIBRARY EGL PATHS ${EGL_ROOT}/lib
NO_DEFAULT_PATH
)
endif()
if(NOT EGL_LIBRARY)
find_library(EGL_LIBRARY EGL PATHS
/usr/local/lib
/usr/lib
)
endif()
endif()
if(NOT EGL_opengl_LIBRARY)
# If we have a root defined look there first
if(EGL_ROOT)
find_library(EGL_opengl_LIBRARY OpenGL PATHS ${EGL_ROOT}/lib
NO_DEFAULT_PATH
)
endif()
if(NOT EGL_opengl_LIBRARY)
find_library(EGL_opengl_LIBRARY OpenGL PATHS
/usr/local/lib
/usr/lib
)
endif()
endif()
if(NOT EGL_gldispatch_LIBRARY)
# If we have a root defined look there first
if(EGL_ROOT)
find_library(EGL_gldispatch_LIBRARY GLdispatch PATHS ${EGL_ROOT}/lib
NO_DEFAULT_PATH
)
endif()
if(NOT EGL_gldispatch_LIBRARY)
find_library(EGL_gldispatch_LIBRARY GLdispatch PATHS
/usr/local/lib
/usr/lib
)
endif()
# For the NVIDIA 358 drivers there isn't a libGLdispath.so. The
# proper one gets installed as libGLdispatch.so.0.
if(NOT EGL_gldispatch_LIBRARY)
find_library(EGL_gldispatch_LIBRARY libGLdispatch.so.0 PATHS
/usr/local/lib
/usr/lib
)
endif()
endif()
set(EGL_LIBRARIES ${EGL_LIBRARY} ${EGL_opengl_LIBRARY} ${EGL_gldispatch_LIBRARY})
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(EGL DEFAULT_MSG
EGL_LIBRARY EGL_opengl_LIBRARY EGL_gldispatch_LIBRARY EGL_INCLUDE_DIR)
mark_as_advanced(EGL_DIR EGL_INCLUDE_DIR EGL_LIBRARY EGL_opengl_LIBRARY EGL_gldispatch_LIBRARY)

@ -186,6 +186,7 @@ include(CMakeDependentOption)
find_package(OpenGL)
find_package(GLEW)
find_package(GLUT)
find_package(EGL)
#dependent option reads, value to set, if condition is true, otherwise
#use last value

@ -49,6 +49,9 @@ set(opengl_headers
TextureGL.h
WorldAnnotatorGL.h
)
set(egl_headers
CanvasEGL.h
)
set(osmesa_headers
CanvasOSMesa.h

114
vtkm/rendering/CanvasEGL.h Normal file

@ -0,0 +1,114 @@
//============================================================================
// Copyright (c) Kitware, Inc.
// All rights reserved.
// See LICENSE.txt for details.
// This software is distributed WITHOUT ANY WARRANTY; without even
// the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
// PURPOSE. See the above copyright notice for more information.
//
// Copyright 2015 Sandia Corporation.
// Copyright 2015 UT-Battelle, LLC.
// Copyright 2015 Los Alamos National Security.
//
// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
// the U.S. Government retains certain rights in this software.
//
// Under the terms of Contract DE-AC52-06NA25396 with Los Alamos National
// Laboratory (LANL), the U.S. Government retains certain rights in
// this software.
//============================================================================
#ifndef vtk_m_rendering_CanvasEGL_h
#define vtk_m_rendering_CanvasEGL_h
#include <vtkm/Types.h>
#include <vtkm/cont/ArrayPortalToIterators.h>
#include <vtkm/rendering/CanvasGL.h>
#include <vtkm/rendering/Color.h>
#include <EGL/egl.h>
//#include <GL/gl.h>
#include <iostream>
#include <fstream>
namespace vtkm {
namespace rendering {
class CanvasEGL : public CanvasGL
{
public:
VTKM_CONT_EXPORT
CanvasEGL(vtkm::Id width=1024,
vtkm::Id height=1024)
: CanvasGL()
{
ctx = NULL;
this->ResizeBuffers(width, height);
}
VTKM_CONT_EXPORT
virtual void Initialize()
{
if (!(dpy = eglGetDisplay(EGL_DEFAULT_DISPLAY)))
throw vtkm::cont::ErrorControlBadValue("Failed to get EGL display");
EGLint major, minor;
if (!(eglInitialize(dpy, &major, &minor)))
throw vtkm::cont::ErrorControlBadValue("Failed to initialize EGL display");
const EGLint cfgAttrs[] =
{
EGL_SURFACE_TYPE, EGL_PBUFFER_BIT,
EGL_BLUE_SIZE, 8,
EGL_GREEN_SIZE, 8,
EGL_RED_SIZE, 8,
EGL_DEPTH_SIZE, 8,
EGL_RENDERABLE_TYPE, EGL_OPENGL_BIT,
EGL_NONE
};
EGLint nCfgs;
EGLConfig cfg;
if (!(eglChooseConfig(dpy, cfgAttrs, &cfg, 1, &nCfgs)) || nCfgs == 0)
throw vtkm::cont::ErrorControlBadValue("Failed to get EGL config");
const EGLint pbAttrs[] =
{
EGL_WIDTH, static_cast<EGLint>(this->GetWidth()),
EGL_HEIGHT, static_cast<EGLint>(this->GetHeight()),
EGL_NONE,
};
if (!(surf = eglCreatePbufferSurface(dpy, cfg, pbAttrs)))
throw vtkm::cont::ErrorControlBadValue("Failed to create EGL PBuffer surface");
eglBindAPI(EGL_OPENGL_API);
if (!(ctx = eglCreateContext(dpy, cfg, EGL_NO_CONTEXT, NULL)))
throw vtkm::cont::ErrorControlBadValue("Failed to create EGL context");
if (!(eglMakeCurrent(dpy, surf, surf, ctx)))
throw vtkm::cont::ErrorControlBadValue("Failed to create EGL context current");
}
VTKM_CONT_EXPORT
virtual void Activate()
{
glEnable(GL_DEPTH_TEST);
}
VTKM_CONT_EXPORT
virtual void Clear()
{
vtkm::rendering::Color backgroundColor = this->GetBackgroundColor();
glClearColor(backgroundColor.Components[0],
backgroundColor.Components[1],
backgroundColor.Components[2],
1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
}
private:
EGLContext ctx;
EGLDisplay dpy;
EGLSurface surf;
};
}} //namespace vtkm::rendering
#endif //vtk_m_rendering_CanvasEGL_h

@ -26,6 +26,13 @@ set(unit_tests
set(libs)
if (OPENGL_FOUND)
list(APPEND libs ${OPENGL_LIBRARIES})
if (EGL_FOUND)
set(unit_tests ${unit_tests}
UnitTestMapperEGL.cxx
)
list(APPEND libs ${EGL_LIBRARIES})
endif()
if (OSMESA_FOUND)
set(unit_tests ${unit_tests}

@ -0,0 +1,143 @@
//============================================================================
// Copyright (c) Kitware, Inc.
// All rights reserved.
// See LICENSE.txt for details.
// This software is distributed WITHOUT ANY WARRANTY; without even
// the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
// PURPOSE. See the above copyright notice for more information.
//
// Copyright 2015 Sandia Corporation.
// Copyright 2015 UT-Battelle, LLC.
// Copyright 2015 Los Alamos National Security.
//
// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
// the U.S. Government retains certain rights in this software.
//
// Under the terms of Contract DE-AC52-06NA25396 with Los Alamos National
// Laboratory (LANL), the U.S. Government retains certain rights in
// this software.
//============================================================================
#include <vtkm/Bounds.h>
#include <vtkm/cont/testing/MakeTestDataSet.h>
#include <vtkm/rendering/Actor.h>
#include <vtkm/rendering/CanvasEGL.h>
#include <vtkm/rendering/MapperGL.h>
#include <vtkm/rendering/Scene.h>
#include <vtkm/rendering/View.h>
#include <vtkm/cont/DeviceAdapter.h>
#include <vtkm/cont/testing/Testing.h>
namespace {
void Set3DView(vtkm::rendering::Camera &camera,
const vtkm::cont::CoordinateSystem &coords)
{
vtkm::Bounds coordsBounds = coords.GetBounds(VTKM_DEFAULT_DEVICE_ADAPTER_TAG());
//set up a default view
camera = vtkm::rendering::Camera();
camera.ResetToBounds(coordsBounds);
camera.Azimuth(static_cast<vtkm::Float32>(vtkm::Pi_4()));
camera.Elevation(static_cast<vtkm::Float32>(vtkm::Pi_4()));
std::cout << "Camera3d: pos: " << camera.GetPosition() << std::endl;
std::cout << " lookAt: " << camera.GetLookAt() << std::endl;
std::cout << " up: " << camera.GetViewUp() << std::endl;
std::cout << " near/far: " << camera.GetClippingRange() << std::endl;
std::cout << " fieldOfView: " << camera.GetFieldOfView() << std::endl;
}
void Set2DView(vtkm::rendering::Camera &camera,
const vtkm::cont::CoordinateSystem &coords)
{
vtkm::Bounds coordsBounds = coords.GetBounds(VTKM_DEFAULT_DEVICE_ADAPTER_TAG());
//set up a default view
camera = vtkm::rendering::Camera(vtkm::rendering::Camera::MODE_2D);
camera.SetViewRange2D(coordsBounds);
camera.SetClippingRange(1.f, 100.f);
// Give it some space for other annotations like a color bar
camera.SetViewport(-0.7f, +0.7f, -0.7f, +0.7f);
std::cout << "Camera2D: Viewport: " << camera.GetViewport() << std::endl;
std::cout << " ClippingRange: " << camera.GetClippingRange() << std::endl;
}
void Render3D(const vtkm::cont::DataSet &ds,
const std::string &fieldNm,
const std::string &ctName,
const std::string &outputFile)
{
const vtkm::Int32 W = 512, H = 512;
const vtkm::cont::CoordinateSystem coords = ds.GetCoordinateSystem();
vtkm::rendering::MapperGL<VTKM_DEFAULT_DEVICE_ADAPTER_TAG> mapper;
vtkm::rendering::Camera camera;
Set3DView(camera, coords);
vtkm::rendering::Scene scene;
vtkm::rendering::Color bg(0.2f, 0.2f, 0.2f, 1.0f);
vtkm::rendering::CanvasEGL canvas(W,H);
scene.AddActor(vtkm::rendering::Actor(ds.GetCellSet(),
ds.GetCoordinateSystem(),
ds.GetField(fieldNm),
vtkm::rendering::ColorTable(ctName)));
//TODO: W/H in view. bg in view (view sets canvas/renderer).
vtkm::rendering::View3D view(scene, mapper, canvas, camera, bg);
view.Initialize();
view.Paint();
view.SaveAs(outputFile);
}
void Render2D(const vtkm::cont::DataSet &ds,
const std::string &fieldNm,
const std::string &ctName,
const std::string &outputFile)
{
const vtkm::Int32 W = 512, H = 512;
const vtkm::cont::CoordinateSystem coords = ds.GetCoordinateSystem();
vtkm::rendering::MapperGL<VTKM_DEFAULT_DEVICE_ADAPTER_TAG> mapper;
vtkm::rendering::Camera camera;
Set2DView(camera, coords);
vtkm::rendering::Scene scene;
vtkm::rendering::Color bg(0.2f, 0.2f, 0.2f, 1.0f);
vtkm::rendering::CanvasEGL canvas(W,H);
scene.AddActor(vtkm::rendering::Actor(ds.GetCellSet(),
ds.GetCoordinateSystem(),
ds.GetField(fieldNm),
vtkm::rendering::ColorTable(ctName)));
vtkm::rendering::View2D view(scene, mapper, canvas, camera, bg);
view.Initialize();
view.Paint();
view.SaveAs(outputFile);
}
void RenderTests()
{
vtkm::cont::testing::MakeTestDataSet maker;
//3D tests.
Render3D(maker.Make3DRegularDataSet0(),
"pointvar", "thermal", "reg3D.pnm");
Render3D(maker.Make3DRectilinearDataSet0(),
"pointvar", "thermal", "rect3D.pnm");
Render3D(maker.Make3DExplicitDataSet4(),
"pointvar", "thermal", "expl3D.pnm");
//2D tests.
Render2D(maker.Make2DRectilinearDataSet0(),
"pointvar", "thermal", "rect2D.pnm");
}
} //namespace
int UnitTestMapperEGL(int, char *[])
{
return vtkm::cont::testing::Testing::Run(RenderTests);
}