mirror of
https://github.com/glfw/glfw.git
synced 2024-11-25 22:14:34 +00:00
Add headless OSMesa backend
Allows creation and drawing to in-memory OpenGL contexts. This backend does not provide input. Related to #850.
This commit is contained in:
parent
a90ee65f7b
commit
368fa9475d
18
CMake/modules/Findosmesa.cmake
Normal file
18
CMake/modules/Findosmesa.cmake
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
# Try to find OSMesa on a Unix system
|
||||||
|
#
|
||||||
|
# This will define:
|
||||||
|
#
|
||||||
|
# OSMESA_LIBRARIES - Link these to use OSMesa
|
||||||
|
# OSMESA_INCLUDE_DIR - Include directory for OSMesa
|
||||||
|
#
|
||||||
|
# Copyright (c) 2014 Brandon Schaefer <brandon.schaefer@canonical.com>
|
||||||
|
|
||||||
|
if (NOT WIN32)
|
||||||
|
|
||||||
|
find_package (PkgConfig)
|
||||||
|
pkg_check_modules (PKG_OSMESA QUIET osmesa)
|
||||||
|
|
||||||
|
set (OSMESA_INCLUDE_DIR ${PKG_OSMESA_INCLUDE_DIRS})
|
||||||
|
set (OSMESA_LIBRARIES ${PKG_OSMESA_LIBRARIES})
|
||||||
|
|
||||||
|
endif ()
|
@ -41,6 +41,7 @@ endif()
|
|||||||
if (UNIX AND NOT APPLE)
|
if (UNIX AND NOT APPLE)
|
||||||
option(GLFW_USE_WAYLAND "Use Wayland for window creation" OFF)
|
option(GLFW_USE_WAYLAND "Use Wayland for window creation" OFF)
|
||||||
option(GLFW_USE_MIR "Use Mir for window creation" OFF)
|
option(GLFW_USE_MIR "Use Mir for window creation" OFF)
|
||||||
|
option(GLFW_USE_OSMESA "Use OSMesa for offscreen context creation" OFF)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if (MSVC)
|
if (MSVC)
|
||||||
@ -154,6 +155,9 @@ elseif (UNIX)
|
|||||||
elseif (GLFW_USE_MIR)
|
elseif (GLFW_USE_MIR)
|
||||||
set(_GLFW_MIR 1)
|
set(_GLFW_MIR 1)
|
||||||
message(STATUS "Using Mir for window creation")
|
message(STATUS "Using Mir for window creation")
|
||||||
|
elseif (GLFW_USE_OSMESA)
|
||||||
|
set(_GLFW_OSMESA 1)
|
||||||
|
message(STATUS "Using OSMesa for windowless context creation")
|
||||||
else()
|
else()
|
||||||
set(_GLFW_X11 1)
|
set(_GLFW_X11 1)
|
||||||
message(STATUS "Using X11 for window creation")
|
message(STATUS "Using X11 for window creation")
|
||||||
@ -318,6 +322,18 @@ if (_GLFW_MIR)
|
|||||||
list(APPEND glfw_LIBRARIES "${XKBCOMMON_LIBRARY}")
|
list(APPEND glfw_LIBRARIES "${XKBCOMMON_LIBRARY}")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
#--------------------------------------------------------------------
|
||||||
|
# Use OSMesa for offscreen context creation
|
||||||
|
#--------------------------------------------------------------------
|
||||||
|
if (_GLFW_OSMESA)
|
||||||
|
find_package(osmesa REQUIRED)
|
||||||
|
list(APPEND glfw_PKG_DEPS "osmesa")
|
||||||
|
|
||||||
|
list(APPEND glfw_INCLUDE_DIRS "${OSMESA_INCLUDE_DIR}")
|
||||||
|
list(APPEND glfw_LIBRARIES "${OSMESA_LIBRARIES}"
|
||||||
|
"${CMAKE_THREAD_LIBS_INIT}")
|
||||||
|
endif()
|
||||||
|
|
||||||
#--------------------------------------------------------------------
|
#--------------------------------------------------------------------
|
||||||
# Use Cocoa for window creation and NSOpenGL for context creation
|
# Use Cocoa for window creation and NSOpenGL for context creation
|
||||||
#--------------------------------------------------------------------
|
#--------------------------------------------------------------------
|
||||||
|
@ -448,6 +448,30 @@ GLFWAPI EGLContext glfwGetEGLContext(GLFWwindow* window);
|
|||||||
GLFWAPI EGLSurface glfwGetEGLSurface(GLFWwindow* window);
|
GLFWAPI EGLSurface glfwGetEGLSurface(GLFWwindow* window);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if defined(GLFW_EXPOSE_NATIVE_OSMESA)
|
||||||
|
/*! @brief Returns the color buffer associated with the specified window.
|
||||||
|
*
|
||||||
|
* @param[out] width The width of the color buffer.
|
||||||
|
* @param[out] height The height of the color buffer.
|
||||||
|
* @param[out] format The pixel format of the color buffer (OSMESA_FORMAT_*).
|
||||||
|
* @param[out] buffer The buffer data.
|
||||||
|
* @return 1 if successful, or 0 if not.
|
||||||
|
*/
|
||||||
|
GLFWAPI int glfwGetOSMesaColorBuffer(GLFWwindow* window, int* width,
|
||||||
|
int* height, int* format, void** buffer);
|
||||||
|
|
||||||
|
/*! @brief Returns the depth buffer associated with the specified window.
|
||||||
|
*
|
||||||
|
* @param[out] width The width of the depth buffer.
|
||||||
|
* @param[out] height The height of the depth buffer.
|
||||||
|
* @param[out] bytesPerValue The number of bytes per depth buffer element.
|
||||||
|
* @param[out] buffer The buffer data.
|
||||||
|
* @return 1 if successful, or 0 if not.
|
||||||
|
*/
|
||||||
|
GLFWAPI int glfwGetOSMesaDepthBuffer(GLFWwindow* window, int* width,
|
||||||
|
int* height, int* bytesPerValue, void** buffer);
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -45,6 +45,12 @@ elseif (_GLFW_MIR)
|
|||||||
set(glfw_SOURCES ${common_SOURCES} mir_init.c mir_monitor.c mir_window.c
|
set(glfw_SOURCES ${common_SOURCES} mir_init.c mir_monitor.c mir_window.c
|
||||||
linux_joystick.c posix_time.c posix_tls.c xkb_unicode.c
|
linux_joystick.c posix_time.c posix_tls.c xkb_unicode.c
|
||||||
egl_context.c)
|
egl_context.c)
|
||||||
|
elseif (_GLFW_OSMESA)
|
||||||
|
set(glfw_HEADERS ${common_HEADERS} osmesa_platform.h
|
||||||
|
posix_time.h posix_tls.h osmesa_context.h)
|
||||||
|
set(glfw_SOURCES ${common_SOURCES} osmesa_init.c osmesa_monitor.c
|
||||||
|
osmesa_window.c posix_time.c posix_tls.c
|
||||||
|
osmesa_context.c)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if (APPLE)
|
if (APPLE)
|
||||||
|
@ -44,6 +44,8 @@
|
|||||||
#cmakedefine _GLFW_WAYLAND
|
#cmakedefine _GLFW_WAYLAND
|
||||||
// Define this to 1 if building GLFW for Mir
|
// Define this to 1 if building GLFW for Mir
|
||||||
#cmakedefine _GLFW_MIR
|
#cmakedefine _GLFW_MIR
|
||||||
|
// Define this to 1 if building GLFW for OSMesa
|
||||||
|
#cmakedefine _GLFW_OSMESA
|
||||||
|
|
||||||
// Define this to 1 if building as a shared library / dynamic library / DLL
|
// Define this to 1 if building as a shared library / dynamic library / DLL
|
||||||
#cmakedefine _GLFW_BUILD_DLL
|
#cmakedefine _GLFW_BUILD_DLL
|
||||||
|
@ -172,6 +172,8 @@ typedef void (APIENTRY * PFN_vkVoidFunction)(void);
|
|||||||
#include "wl_platform.h"
|
#include "wl_platform.h"
|
||||||
#elif defined(_GLFW_MIR)
|
#elif defined(_GLFW_MIR)
|
||||||
#include "mir_platform.h"
|
#include "mir_platform.h"
|
||||||
|
#elif defined(_GLFW_OSMESA)
|
||||||
|
#include "osmesa_platform.h"
|
||||||
#else
|
#else
|
||||||
#error "No supported window creation API selected"
|
#error "No supported window creation API selected"
|
||||||
#endif
|
#endif
|
||||||
|
213
src/osmesa_context.c
Normal file
213
src/osmesa_context.c
Normal file
@ -0,0 +1,213 @@
|
|||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "internal.h"
|
||||||
|
#include "osmesa_context.h"
|
||||||
|
|
||||||
|
static void makeContextCurrentOSMesa(_GLFWwindow* window)
|
||||||
|
{
|
||||||
|
if (window)
|
||||||
|
{
|
||||||
|
// Check to see if we need to allocate a new buffer.
|
||||||
|
if ((window->context.osmesa.buffer == NULL) ||
|
||||||
|
(window->osmesa.width != window->context.osmesa.width) ||
|
||||||
|
(window->osmesa.height != window->context.osmesa.height))
|
||||||
|
{
|
||||||
|
// Free the current buffer, if necessary.
|
||||||
|
if (window->context.osmesa.buffer != NULL)
|
||||||
|
{
|
||||||
|
free(window->context.osmesa.buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Allocate the new buffer (width * height * 1 byte per RGBA
|
||||||
|
// channel).
|
||||||
|
window->context.osmesa.buffer = (unsigned char *) malloc(
|
||||||
|
window->osmesa.width * window->osmesa.height * 4);
|
||||||
|
|
||||||
|
// Update the context size.
|
||||||
|
window->context.osmesa.width = window->osmesa.width;
|
||||||
|
window->context.osmesa.height = window->osmesa.height;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Make the context current.
|
||||||
|
if (!OSMesaMakeCurrent(window->context.osmesa.handle,
|
||||||
|
window->context.osmesa.buffer,
|
||||||
|
0x1401, // GL_UNSIGNED_BYTE
|
||||||
|
window->osmesa.width, window->osmesa.height))
|
||||||
|
{
|
||||||
|
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||||
|
"OSMesa: Failed to make context current.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||||
|
"OSMesa: Releasing the current context is not supported.");
|
||||||
|
}
|
||||||
|
|
||||||
|
_glfwPlatformSetCurrentContext(window);
|
||||||
|
}
|
||||||
|
|
||||||
|
static GLFWglproc getProcAddressOSMesa(const char* procname)
|
||||||
|
{
|
||||||
|
_GLFWwindow* window = _glfwPlatformGetCurrentContext();
|
||||||
|
|
||||||
|
if (window->context.osmesa.handle)
|
||||||
|
{
|
||||||
|
return (GLFWglproc) OSMesaGetProcAddress(procname);
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void destroyContextOSMesa(_GLFWwindow* window)
|
||||||
|
{
|
||||||
|
if (window->context.osmesa.handle != NULL)
|
||||||
|
{
|
||||||
|
OSMesaDestroyContext(window->context.osmesa.handle);
|
||||||
|
window->context.osmesa.handle = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (window->context.osmesa.buffer != NULL)
|
||||||
|
{
|
||||||
|
free(window->context.osmesa.buffer);
|
||||||
|
window->context.osmesa.width = 0;
|
||||||
|
window->context.osmesa.height = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void swapBuffersOSMesa(_GLFWwindow* window) {}
|
||||||
|
|
||||||
|
static void swapIntervalOSMesa(int interval) {}
|
||||||
|
|
||||||
|
static int extensionSupportedOSMesa()
|
||||||
|
{
|
||||||
|
return GLFW_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
////// GLFW internal API //////
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
GLFWbool _glfwInitOSMesa(void)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
const char* sonames[] =
|
||||||
|
{
|
||||||
|
#if defined(_GLFW_WIN32)
|
||||||
|
"libOSMesa.dll",
|
||||||
|
"OSMesa.dll",
|
||||||
|
#elif defined(_GLFW_COCOA)
|
||||||
|
"libOSMesa.dylib",
|
||||||
|
#else
|
||||||
|
"libOSMesa.so.6",
|
||||||
|
#endif
|
||||||
|
NULL
|
||||||
|
};
|
||||||
|
|
||||||
|
if (_glfw.osmesa.handle)
|
||||||
|
return GLFW_TRUE;
|
||||||
|
|
||||||
|
for (i = 0; sonames[i]; i++)
|
||||||
|
{
|
||||||
|
_glfw.osmesa.handle = _glfw_dlopen(sonames[i]);
|
||||||
|
if (_glfw.osmesa.handle)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!_glfw.osmesa.handle)
|
||||||
|
{
|
||||||
|
_glfwInputError(GLFW_API_UNAVAILABLE, "OSMesa: Library not found");
|
||||||
|
return GLFW_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
_glfw.osmesa.prefix = (strncmp(sonames[i], "lib", 3) == 0);
|
||||||
|
|
||||||
|
_glfw.osmesa.CreateContext = (PFNOSMESACREATECONTEXTPROC)
|
||||||
|
_glfw_dlsym(_glfw.osmesa.handle, "OSMesaCreateContext");
|
||||||
|
_glfw.osmesa.DestroyContext = (PFNOSMESADESTROYCONTEXTPROC)
|
||||||
|
_glfw_dlsym(_glfw.osmesa.handle, "OSMesaDestroyContext");
|
||||||
|
_glfw.osmesa.MakeCurrent = (PFNOSMESAMAKECURRENTPROC)
|
||||||
|
_glfw_dlsym(_glfw.osmesa.handle, "OSMesaMakeCurrent");
|
||||||
|
_glfw.osmesa.GetCurrentContext = (PFNOSMESAGETCURRENTCONTEXTPROC)
|
||||||
|
_glfw_dlsym(_glfw.osmesa.handle, "OSMesaGetCurrentContext");
|
||||||
|
_glfw.osmesa.PixelStore = (PFNOSMESAPIXELSTOREPROC)
|
||||||
|
_glfw_dlsym(_glfw.osmesa.handle, "OSMesaPixelStore");
|
||||||
|
_glfw.osmesa.GetIntegerv = (PFNOSMESAGETINTEGERVPROC)
|
||||||
|
_glfw_dlsym(_glfw.osmesa.handle, "OSMesaGetIntegerv");
|
||||||
|
_glfw.osmesa.GetColorBuffer = (PFNOSMESAGETCOLORBUFFERPROC)
|
||||||
|
_glfw_dlsym(_glfw.osmesa.handle, "OSMesaGetColorBuffer");
|
||||||
|
_glfw.osmesa.GetDepthBuffer = (PFNOSMESAGETDEPTHBUFFERPROC)
|
||||||
|
_glfw_dlsym(_glfw.osmesa.handle, "OSMesaGetDepthBuffer");
|
||||||
|
_glfw.osmesa.GetProcAddress = (PFNOSMESAGETPROCADDRESSPROC)
|
||||||
|
_glfw_dlsym(_glfw.osmesa.handle, "OSMesaGetProcAddress");
|
||||||
|
|
||||||
|
if (!_glfw.osmesa.CreateContext ||
|
||||||
|
!_glfw.osmesa.DestroyContext ||
|
||||||
|
!_glfw.osmesa.MakeCurrent ||
|
||||||
|
!_glfw.osmesa.GetCurrentContext ||
|
||||||
|
!_glfw.osmesa.PixelStore ||
|
||||||
|
!_glfw.osmesa.GetIntegerv ||
|
||||||
|
!_glfw.osmesa.GetColorBuffer ||
|
||||||
|
!_glfw.osmesa.GetDepthBuffer ||
|
||||||
|
!_glfw.osmesa.GetProcAddress)
|
||||||
|
{
|
||||||
|
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||||
|
"OSMesa: Failed to load required entry points");
|
||||||
|
|
||||||
|
_glfwTerminateOSMesa();
|
||||||
|
return GLFW_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return GLFW_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
void _glfwTerminateOSMesa(void)
|
||||||
|
{
|
||||||
|
if (_glfw.osmesa.handle)
|
||||||
|
{
|
||||||
|
_glfw_dlclose(_glfw.osmesa.handle);
|
||||||
|
_glfw.osmesa.handle = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
GLFWbool _glfwCreateContextOSMesa(_GLFWwindow* window,
|
||||||
|
const _GLFWctxconfig* ctxconfig,
|
||||||
|
const _GLFWfbconfig* fbconfig)
|
||||||
|
{
|
||||||
|
OSMesaContext share;
|
||||||
|
|
||||||
|
if (ctxconfig->share)
|
||||||
|
share = ctxconfig->share->context.osmesa.handle;
|
||||||
|
|
||||||
|
// Initialize the context.
|
||||||
|
window->context.osmesa.buffer = NULL;
|
||||||
|
window->context.osmesa.width = 0;
|
||||||
|
window->context.osmesa.height = 0;
|
||||||
|
|
||||||
|
// Create to create an OSMesa context.
|
||||||
|
window->context.osmesa.handle = OSMesaCreateContext(OSMESA_RGBA, share);
|
||||||
|
if (window->context.osmesa.handle == 0)
|
||||||
|
{
|
||||||
|
_glfwInputError(GLFW_VERSION_UNAVAILABLE,
|
||||||
|
"OSMesa: Failed to create context.");
|
||||||
|
return GLFW_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set up the context API.
|
||||||
|
window->context.makeCurrent = makeContextCurrentOSMesa;
|
||||||
|
window->context.swapBuffers = swapBuffersOSMesa;
|
||||||
|
window->context.swapInterval = swapIntervalOSMesa;
|
||||||
|
window->context.extensionSupported = extensionSupportedOSMesa;
|
||||||
|
window->context.getProcAddress = getProcAddressOSMesa;
|
||||||
|
window->context.destroy = destroyContextOSMesa;
|
||||||
|
|
||||||
|
return GLFW_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
////// GLFW native API //////
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
87
src/osmesa_context.h
Normal file
87
src/osmesa_context.h
Normal file
@ -0,0 +1,87 @@
|
|||||||
|
|
||||||
|
#ifndef _glfw3_osmesa_context_h_
|
||||||
|
#define _glfw3_osmesa_context_h_
|
||||||
|
|
||||||
|
#define OSMESA_COLOR_INDEX GL_COLOR_INDEX
|
||||||
|
#define OSMESA_RGBA 0x1908
|
||||||
|
#define OSMESA_BGRA 0x1
|
||||||
|
#define OSMESA_ARGB 0x2
|
||||||
|
#define OSMESA_RGB 0x1907
|
||||||
|
#define OSMESA_BGR 0x4
|
||||||
|
#define OSMESA_RGB_565 0x5
|
||||||
|
|
||||||
|
#define OSMESA_ROW_LENGTH 0x10
|
||||||
|
#define OSMESA_Y_UP 0x11
|
||||||
|
|
||||||
|
#define OSMESA_WIDTH 0x20
|
||||||
|
#define OSMESA_HEIGHT 0x21
|
||||||
|
#define OSMESA_FORMAT 0x22
|
||||||
|
#define OSMESA_TYPE 0x23
|
||||||
|
#define OSMESA_MAX_WIDTH 0x24
|
||||||
|
#define OSMESA_MAX_HEIGHT 0x25
|
||||||
|
|
||||||
|
typedef void* OSMesaContext;
|
||||||
|
typedef void (*OSMESAproc)();
|
||||||
|
|
||||||
|
typedef OSMesaContext (* PFNOSMESACREATECONTEXTPROC)(GLenum, OSMesaContext);
|
||||||
|
typedef void (* PFNOSMESADESTROYCONTEXTPROC)(OSMesaContext);
|
||||||
|
typedef int (* PFNOSMESAMAKECURRENTPROC)(OSMesaContext, void*, int, int, int);
|
||||||
|
typedef OSMesaContext (* PFNOSMESAGETCURRENTCONTEXTPROC)();
|
||||||
|
typedef void (* PFNOSMESAPIXELSTOREPROC)(int, int);
|
||||||
|
typedef void (* PFNOSMESAGETINTEGERVPROC)(int, int*);
|
||||||
|
typedef int (* PFNOSMESAGETCOLORBUFFERPROC)(OSMesaContext, int*, int*, int*, void**);
|
||||||
|
typedef int (* PFNOSMESAGETDEPTHBUFFERPROC)(OSMesaContext, int*, int*, int*, void**);
|
||||||
|
typedef GLFWglproc (* PFNOSMESAGETPROCADDRESSPROC)(const char*);
|
||||||
|
#define OSMesaCreateContext _glfw.osmesa.CreateContext
|
||||||
|
#define OSMesaDestroyContext _glfw.osmesa.DestroyContext
|
||||||
|
#define OSMesaMakeCurrent _glfw.osmesa.MakeCurrent
|
||||||
|
#define OSMesaGetCurrentContext _glfw.osmesa.GetCurrentContext
|
||||||
|
#define OSMesaPixelStore _glfw.osmesa.PixelStore
|
||||||
|
#define OSMesaGetIntegerv _glfw.osmesa.GetIntegerv
|
||||||
|
#define OSMesaGetColorBuffer _glfw.osmesa.GetColorBuffer
|
||||||
|
#define OSMesaGetDepthBuffer _glfw.osmesa.GetDepthBuffer
|
||||||
|
#define OSMesaGetProcAddress _glfw.osmesa.GetProcAddress
|
||||||
|
|
||||||
|
#define _GLFW_PLATFORM_CONTEXT_STATE _GLFWcontextOSMesa osmesa
|
||||||
|
#define _GLFW_PLATFORM_LIBRARY_CONTEXT_STATE _GLFWctxlibraryOSMesa osmesa
|
||||||
|
|
||||||
|
|
||||||
|
// OSMesa-specific per-context data
|
||||||
|
//
|
||||||
|
typedef struct _GLFWcontextOSMesa
|
||||||
|
{
|
||||||
|
OSMesaContext handle;
|
||||||
|
int width;
|
||||||
|
int height;
|
||||||
|
void * buffer;
|
||||||
|
|
||||||
|
} _GLFWcontextOSMesa;
|
||||||
|
|
||||||
|
// OSMesa-specific global data
|
||||||
|
//
|
||||||
|
typedef struct _GLFWctxlibraryOSMesa
|
||||||
|
{
|
||||||
|
GLFWbool prefix;
|
||||||
|
|
||||||
|
void* handle;
|
||||||
|
|
||||||
|
PFNOSMESACREATECONTEXTPROC CreateContext;
|
||||||
|
PFNOSMESADESTROYCONTEXTPROC DestroyContext;
|
||||||
|
PFNOSMESAMAKECURRENTPROC MakeCurrent;
|
||||||
|
PFNOSMESAGETCURRENTCONTEXTPROC GetCurrentContext;
|
||||||
|
PFNOSMESAPIXELSTOREPROC PixelStore;
|
||||||
|
PFNOSMESAGETINTEGERVPROC GetIntegerv;
|
||||||
|
PFNOSMESAGETCOLORBUFFERPROC GetColorBuffer;
|
||||||
|
PFNOSMESAGETDEPTHBUFFERPROC GetDepthBuffer;
|
||||||
|
PFNOSMESAGETPROCADDRESSPROC GetProcAddress;
|
||||||
|
|
||||||
|
} _GLFWctxlibraryOSMesa;
|
||||||
|
|
||||||
|
|
||||||
|
GLFWbool _glfwInitOSMesa(void);
|
||||||
|
void _glfwTerminateOSMesa(void);
|
||||||
|
GLFWbool _glfwCreateContextOSMesa(_GLFWwindow* window,
|
||||||
|
const _GLFWctxconfig* ctxconfig,
|
||||||
|
const _GLFWfbconfig* fbconfig);
|
||||||
|
|
||||||
|
#endif // _glfw3_osmesa_context_h_
|
35
src/osmesa_init.c
Normal file
35
src/osmesa_init.c
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
|
||||||
|
#include "internal.h"
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
////// GLFW internal API //////
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
////// GLFW platform API //////
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
int _glfwPlatformInit(void)
|
||||||
|
{
|
||||||
|
if (!_glfwInitThreadLocalStoragePOSIX()) {
|
||||||
|
return GLFW_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
_glfwInitTimerPOSIX();
|
||||||
|
|
||||||
|
return GLFW_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
void _glfwPlatformTerminate(void)
|
||||||
|
{
|
||||||
|
_glfwTerminateOSMesa();
|
||||||
|
_glfwTerminateThreadLocalStoragePOSIX();
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* _glfwPlatformGetVersionString(void)
|
||||||
|
{
|
||||||
|
const char* version = _GLFW_VERSION_NUMBER " OSMESA";
|
||||||
|
return version;
|
||||||
|
}
|
||||||
|
|
43
src/osmesa_monitor.c
Normal file
43
src/osmesa_monitor.c
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
|
||||||
|
#include "internal.h"
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
////// GLFW internal API //////
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
////// GLFW platform API //////
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
_GLFWmonitor** _glfwPlatformGetMonitors(int* count)
|
||||||
|
{
|
||||||
|
// OSMesa is headless, so no monitors.
|
||||||
|
_GLFWmonitor** monitors = NULL;
|
||||||
|
if (count != NULL) {
|
||||||
|
*count = 0;
|
||||||
|
}
|
||||||
|
return monitors;
|
||||||
|
}
|
||||||
|
|
||||||
|
int _glfwPlatformIsSameMonitor(_GLFWmonitor* first, _GLFWmonitor* second)
|
||||||
|
{
|
||||||
|
return GLFW_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
void _glfwPlatformGetMonitorPos(_GLFWmonitor* monitor, int* xpos, int* ypos) {}
|
||||||
|
|
||||||
|
GLFWvidmode* _glfwPlatformGetVideoModes(_GLFWmonitor* monitor, int* found)
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void _glfwPlatformGetVideoMode(_GLFWmonitor* monitor, GLFWvidmode* mode) {}
|
||||||
|
|
||||||
|
void _glfwPlatformGetGammaRamp(_GLFWmonitor* monitor, GLFWgammaramp* ramp) {}
|
||||||
|
|
||||||
|
void _glfwPlatformSetGammaRamp(_GLFWmonitor* monitor,
|
||||||
|
const GLFWgammaramp* ramp) {}
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
////// GLFW native API //////
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
61
src/osmesa_platform.h
Normal file
61
src/osmesa_platform.h
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
|
||||||
|
#ifndef _osmesa_platform_h_
|
||||||
|
#define _osmesa_platform_h_
|
||||||
|
|
||||||
|
#include <dlfcn.h>
|
||||||
|
|
||||||
|
#define _GLFW_PLATFORM_WINDOW_STATE _GLFWwindowOSMesa osmesa
|
||||||
|
#define _GLFW_PLATFORM_MONITOR_STATE _GLFWmonitorOSMesa osmesa
|
||||||
|
#define _GLFW_PLATFORM_CURSOR_STATE _GLFWcursorOSMesa osmesa
|
||||||
|
|
||||||
|
#define _GLFW_PLATFORM_LIBRARY_WINDOW_STATE _GLFWwinlibraryOSMesa osmesawin
|
||||||
|
|
||||||
|
#define _GLFW_PLATFORM_LIBRARY_JOYSTICK_STATE
|
||||||
|
#define _GLFW_EGL_CONTEXT_STATE
|
||||||
|
#define _GLFW_EGL_LIBRARY_CONTEXT_STATE
|
||||||
|
|
||||||
|
#include "osmesa_context.h"
|
||||||
|
#include "posix_time.h"
|
||||||
|
#include "posix_tls.h"
|
||||||
|
|
||||||
|
#define _glfw_dlopen(name) dlopen(name, RTLD_LAZY | RTLD_LOCAL)
|
||||||
|
#define _glfw_dlclose(handle) dlclose(handle)
|
||||||
|
#define _glfw_dlsym(handle, name) dlsym(handle, name)
|
||||||
|
|
||||||
|
// TODO(dalyj) "PLACEHOLDER" variables are there to silence "empty struct"
|
||||||
|
// warnings
|
||||||
|
|
||||||
|
// OSMesa-specific per-window data
|
||||||
|
//
|
||||||
|
typedef struct _GLFWwindowOSMesa
|
||||||
|
{
|
||||||
|
int width;
|
||||||
|
int height;
|
||||||
|
} _GLFWwindowOSMesa;
|
||||||
|
|
||||||
|
|
||||||
|
// OSMesa-specific global data
|
||||||
|
//
|
||||||
|
typedef struct _GLFWwinlibraryOSMesa
|
||||||
|
{
|
||||||
|
int PLACEHOLDER;
|
||||||
|
} _GLFWwinlibraryOSMesa;
|
||||||
|
|
||||||
|
|
||||||
|
// OSMesa-specific per-monitor data
|
||||||
|
//
|
||||||
|
typedef struct _GLFWmonitorOSMesa
|
||||||
|
{
|
||||||
|
int PLACEHOLDER;
|
||||||
|
} _GLFWmonitorOSMesa;
|
||||||
|
|
||||||
|
|
||||||
|
// OSMesa-specific per-cursor data
|
||||||
|
//
|
||||||
|
typedef struct _GLFWcursorOSMesa
|
||||||
|
{
|
||||||
|
int PLACEHOLDER;
|
||||||
|
} _GLFWcursorOSMesa;
|
||||||
|
|
||||||
|
|
||||||
|
#endif // _osmesa_platform_h_
|
259
src/osmesa_window.c
Normal file
259
src/osmesa_window.c
Normal file
@ -0,0 +1,259 @@
|
|||||||
|
|
||||||
|
#include "internal.h"
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
|
int createWindow(_GLFWwindow* window, const _GLFWwndconfig* wndconfig)
|
||||||
|
{
|
||||||
|
window->osmesa.width = wndconfig->width;
|
||||||
|
window->osmesa.height = wndconfig->height;
|
||||||
|
|
||||||
|
return GLFW_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
////// GLFW internal API //////
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
////// GLFW platform API //////
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
int _glfwPlatformCreateWindow(_GLFWwindow* window,
|
||||||
|
const _GLFWwndconfig* wndconfig,
|
||||||
|
const _GLFWctxconfig* ctxconfig,
|
||||||
|
const _GLFWfbconfig* fbconfig)
|
||||||
|
{
|
||||||
|
if (!_glfwInitOSMesa())
|
||||||
|
return GLFW_FALSE;
|
||||||
|
|
||||||
|
if (!_glfwCreateContextOSMesa(window, ctxconfig, fbconfig))
|
||||||
|
return GLFW_FALSE;
|
||||||
|
|
||||||
|
if (!createWindow(window, wndconfig))
|
||||||
|
return GLFW_FALSE;
|
||||||
|
|
||||||
|
return GLFW_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
void _glfwPlatformDestroyWindow(_GLFWwindow* window)
|
||||||
|
{
|
||||||
|
if (window->context.destroy)
|
||||||
|
window->context.destroy(window);
|
||||||
|
}
|
||||||
|
|
||||||
|
void _glfwPlatformSetWindowTitle(_GLFWwindow* window, const char* title) {}
|
||||||
|
|
||||||
|
void _glfwPlatformSetWindowIcon(_GLFWwindow* window, int count,
|
||||||
|
const GLFWimage* images) {}
|
||||||
|
|
||||||
|
void _glfwPlatformSetWindowMonitor(_GLFWwindow* window,
|
||||||
|
_GLFWmonitor* monitor,
|
||||||
|
int xpos, int ypos,
|
||||||
|
int width, int height,
|
||||||
|
int refreshRate) {}
|
||||||
|
|
||||||
|
void _glfwPlatformGetWindowPos(_GLFWwindow* window, int* xpos, int* ypos)
|
||||||
|
{
|
||||||
|
if (xpos != NULL) *xpos = 0;
|
||||||
|
if (ypos != NULL) *ypos = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void _glfwPlatformSetWindowPos(_GLFWwindow* window, int xpos, int ypos) {}
|
||||||
|
|
||||||
|
void _glfwPlatformGetWindowSize(_GLFWwindow* window, int* width, int* height)
|
||||||
|
{
|
||||||
|
if (width != NULL) *width = window->osmesa.width;
|
||||||
|
if (height != NULL) *height = window->osmesa.height;
|
||||||
|
}
|
||||||
|
|
||||||
|
void _glfwPlatformSetWindowSize(_GLFWwindow* window, int width, int height)
|
||||||
|
{
|
||||||
|
window->osmesa.width = width;
|
||||||
|
window->osmesa.height = height;
|
||||||
|
}
|
||||||
|
|
||||||
|
void _glfwPlatformSetWindowSizeLimits(_GLFWwindow* window,
|
||||||
|
int minwidth, int minheight,
|
||||||
|
int maxwidth, int maxheight) {}
|
||||||
|
|
||||||
|
void _glfwPlatformSetWindowAspectRatio(_GLFWwindow* window, int n, int d) {}
|
||||||
|
|
||||||
|
void _glfwPlatformGetFramebufferSize(_GLFWwindow* window, int* width,
|
||||||
|
int* height)
|
||||||
|
{
|
||||||
|
if (width != NULL) *width = window->osmesa.width;
|
||||||
|
if (height != NULL) *height = window->osmesa.height;
|
||||||
|
}
|
||||||
|
|
||||||
|
void _glfwPlatformGetWindowFrameSize(_GLFWwindow* window, int* left, int* top,
|
||||||
|
int* right, int* bottom)
|
||||||
|
{
|
||||||
|
if (left != NULL) *left = 0;
|
||||||
|
if (top != NULL) *top = 0;
|
||||||
|
if (right != NULL) *right = window->osmesa.width;
|
||||||
|
if (bottom != NULL) *top = window->osmesa.height;
|
||||||
|
}
|
||||||
|
|
||||||
|
void _glfwPlatformIconifyWindow(_GLFWwindow* window) {}
|
||||||
|
|
||||||
|
void _glfwPlatformRestoreWindow(_GLFWwindow* window) {}
|
||||||
|
|
||||||
|
void _glfwPlatformMaximizeWindow(_GLFWwindow* window) {}
|
||||||
|
|
||||||
|
int _glfwPlatformWindowMaximized(_GLFWwindow* window) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void _glfwPlatformShowWindow(_GLFWwindow* window) {}
|
||||||
|
|
||||||
|
void _glfwPlatformUnhideWindow(_GLFWwindow* window) {}
|
||||||
|
|
||||||
|
void _glfwPlatformHideWindow(_GLFWwindow* window) {}
|
||||||
|
|
||||||
|
void _glfwPlatformFocusWindow(_GLFWwindow* window) {}
|
||||||
|
|
||||||
|
int _glfwPlatformWindowFocused(_GLFWwindow* window) { return GLFW_FALSE; }
|
||||||
|
|
||||||
|
int _glfwPlatformWindowIconified(_GLFWwindow* window) { return GLFW_FALSE; }
|
||||||
|
|
||||||
|
int _glfwPlatformWindowVisible(_GLFWwindow* window) { return GLFW_FALSE; }
|
||||||
|
|
||||||
|
void _glfwPlatformPollEvents(void) {}
|
||||||
|
|
||||||
|
void _glfwPlatformWaitEvents(void) {}
|
||||||
|
|
||||||
|
void _glfwPlatformWaitEventsTimeout(double timeout) {}
|
||||||
|
|
||||||
|
void _glfwPlatformPostEmptyEvent(void) {}
|
||||||
|
|
||||||
|
void _glfwPlatformGetCursorPos(_GLFWwindow* window, double* xpos, double* ypos) {
|
||||||
|
if (xpos != NULL) *xpos = 0;
|
||||||
|
if (ypos != NULL) *ypos = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void _glfwPlatformSetCursorPos(_GLFWwindow* window, double x, double y) {}
|
||||||
|
|
||||||
|
void _glfwPlatformSetCursorMode(_GLFWwindow* window, int mode) {}
|
||||||
|
|
||||||
|
void _glfwPlatformApplyCursorMode(_GLFWwindow* window) {}
|
||||||
|
|
||||||
|
int _glfwPlatformCreateCursor(_GLFWcursor* cursor, const GLFWimage* image,
|
||||||
|
int xhot, int yhot)
|
||||||
|
{
|
||||||
|
return GLFW_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
int _glfwPlatformCreateStandardCursor(_GLFWcursor* cursor, int shape)
|
||||||
|
{
|
||||||
|
return GLFW_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
void _glfwPlatformDestroyCursor(_GLFWcursor* cursor) {}
|
||||||
|
|
||||||
|
void _glfwPlatformSetCursor(_GLFWwindow* window, _GLFWcursor* cursor) {}
|
||||||
|
|
||||||
|
void _glfwPlatformSetClipboardString(_GLFWwindow* window, const char* string) {}
|
||||||
|
|
||||||
|
const char* _glfwPlatformGetClipboardString(_GLFWwindow* window)
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* _glfwPlatformGetKeyName(int key, int scancode) { return ""; }
|
||||||
|
|
||||||
|
int _glfwPlatformJoystickPresent(int joy) { return 0; }
|
||||||
|
|
||||||
|
const float* _glfwPlatformGetJoystickAxes(int joy, int* count)
|
||||||
|
{
|
||||||
|
if (count != NULL) *count = 0;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
const unsigned char* _glfwPlatformGetJoystickButtons(int joy, int* count)
|
||||||
|
{
|
||||||
|
if (count != NULL) *count = 0;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* _glfwPlatformGetJoystickName(int joy) { return NULL; }
|
||||||
|
|
||||||
|
char** _glfwPlatformGetRequiredInstanceExtensions(uint32_t* count)
|
||||||
|
{
|
||||||
|
if (count != NULL) *count = 0;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
int _glfwPlatformGetPhysicalDevicePresentationSupport(VkInstance instance,
|
||||||
|
VkPhysicalDevice device,
|
||||||
|
uint32_t queuefamily)
|
||||||
|
{
|
||||||
|
return GLFW_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
VkResult _glfwPlatformCreateWindowSurface(VkInstance instance,
|
||||||
|
_GLFWwindow* window,
|
||||||
|
const VkAllocationCallbacks* allocator,
|
||||||
|
VkSurfaceKHR* surface)
|
||||||
|
{
|
||||||
|
// This seems like the most appropriate error to return here.
|
||||||
|
return VK_ERROR_INITIALIZATION_FAILED;
|
||||||
|
}
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
////// GLFW native API //////
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
GLFWAPI int glfwGetOSMesaColorBuffer(GLFWwindow* window, int* width,
|
||||||
|
int* height, int* format, void** buffer)
|
||||||
|
{
|
||||||
|
GLint mesaWidth;
|
||||||
|
GLint mesaHeight;
|
||||||
|
GLint mesaFormat;
|
||||||
|
void* mesaBuffer;
|
||||||
|
|
||||||
|
assert(window != NULL);
|
||||||
|
|
||||||
|
OSMesaContext ctx = ((_GLFWwindow*) window)->context.osmesa.handle;
|
||||||
|
|
||||||
|
// Query OSMesa for the color buffer data.
|
||||||
|
int result = OSMesaGetColorBuffer(
|
||||||
|
ctx, &mesaWidth, &mesaHeight, &mesaFormat, &mesaBuffer);
|
||||||
|
if (result) {
|
||||||
|
// Copy the values returned by OSMesa.
|
||||||
|
if (width != NULL) *width = mesaWidth;
|
||||||
|
if (height != NULL) *height = mesaHeight;
|
||||||
|
if (format != NULL) *format = mesaFormat;
|
||||||
|
if (buffer != NULL) *buffer = mesaBuffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
GLFWAPI int glfwGetOSMesaDepthBuffer(GLFWwindow* window, int* width,
|
||||||
|
int* height, int* bytesPerValue,
|
||||||
|
void** buffer)
|
||||||
|
{
|
||||||
|
GLint mesaWidth;
|
||||||
|
GLint mesaHeight;
|
||||||
|
GLint mesaBytes;
|
||||||
|
void* mesaBuffer;
|
||||||
|
|
||||||
|
assert(window != NULL);
|
||||||
|
|
||||||
|
OSMesaContext ctx = ((_GLFWwindow*) window)->context.osmesa.handle;
|
||||||
|
|
||||||
|
// Query OSMesa for the color buffer data.
|
||||||
|
int result = OSMesaGetDepthBuffer(
|
||||||
|
ctx, &mesaWidth, &mesaHeight, &mesaBytes, &mesaBuffer);
|
||||||
|
if (result) {
|
||||||
|
// Copy the values returned by OSMesa.
|
||||||
|
if (width != NULL) *width = mesaWidth;
|
||||||
|
if (height != NULL) *height = mesaHeight;
|
||||||
|
if (bytesPerValue != NULL) *bytesPerValue = mesaBytes;
|
||||||
|
if (buffer != NULL) *buffer = mesaBuffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user