This commit is contained in:
Jason Daly 2016-11-08 12:56:57 +00:00 committed by GitHub
commit f8300cc884
16 changed files with 2101 additions and 0 deletions

View 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 ()

View File

@ -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
#-------------------------------------------------------------------- #--------------------------------------------------------------------

View File

@ -1,5 +1,6 @@
Copyright (c) 2002-2006 Marcus Geelnard Copyright (c) 2002-2006 Marcus Geelnard
Copyright (c) 2006-2016 Camilla Berglund <elmindreda@glfw.org> Copyright (c) 2006-2016 Camilla Berglund <elmindreda@glfw.org>
Copyright (c) 2016 Google Inc.
This software is provided 'as-is', without any express or implied This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages warranty. In no event will the authors be held liable for any damages

View File

@ -35,8 +35,16 @@ add_executable(particles WIN32 MACOSX_BUNDLE particles.c ${ICON} ${TINYCTHREAD}
add_executable(simple WIN32 MACOSX_BUNDLE simple.c ${ICON} ${GLAD}) add_executable(simple WIN32 MACOSX_BUNDLE simple.c ${ICON} ${GLAD})
add_executable(splitview WIN32 MACOSX_BUNDLE splitview.c ${ICON} ${GLAD}) add_executable(splitview WIN32 MACOSX_BUNDLE splitview.c ${ICON} ${GLAD})
add_executable(wave WIN32 MACOSX_BUNDLE wave.c ${ICON} ${GLAD}) add_executable(wave WIN32 MACOSX_BUNDLE wave.c ${ICON} ${GLAD})
if (GLFW_USE_OSMESA)
add_executable(simple_osmesa WIN32 MACOSX_BUNDLE simple_osmesa.c ${ICON} ${GLAD})
add_executable(particles_osmesa WIN32 MACOSX_BUNDLE particles_osmesa.c ${ICON} ${TINYCTHREAD} ${GETOPT} ${GLAD})
endif()
target_link_libraries(particles "${CMAKE_THREAD_LIBS_INIT}" "${RT_LIBRARY}") target_link_libraries(particles "${CMAKE_THREAD_LIBS_INIT}" "${RT_LIBRARY}")
if (GLFW_USE_OSMESA)
target_link_libraries(particles_osmesa "${CMAKE_THREAD_LIBS_INIT}" "${RT_LIBRARY}")
endif()
set(WINDOWS_BINARIES boing gears heightmap particles simple splitview wave) set(WINDOWS_BINARIES boing gears heightmap particles simple splitview wave)

1117
examples/particles_osmesa.c Normal file

File diff suppressed because it is too large Load Diff

209
examples/simple_osmesa.c Normal file
View File

@ -0,0 +1,209 @@
//========================================================================
// Simple GLFW example
// Copyright (c) Camilla Berglund <elmindreda@glfw.org>
//
// This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages
// arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it
// freely, subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented; you must not
// claim that you wrote the original software. If you use this software
// in a product, an acknowledgment in the product documentation would
// be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such, and must not
// be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source
// distribution.
//
//========================================================================
//! [code]
//
#include <glad/glad.h>
#include <GLFW/glfw3.h>
#include "linmath.h"
#include <stdlib.h>
#include <stdio.h>
static const struct
{
float x, y;
float r, g, b;
} vertices[3] =
{
{ -0.6f, -0.4f, 1.f, 0.f, 0.f },
{ 0.6f, -0.4f, 0.f, 1.f, 0.f },
{ 0.f, 0.6f, 0.f, 0.f, 1.f }
};
static const char* vertex_shader_text =
"uniform mat4 MVP;\n"
"attribute vec3 vCol;\n"
"attribute vec2 vPos;\n"
"varying vec3 color;\n"
"void main()\n"
"{\n"
" gl_Position = MVP * vec4(vPos, 0.0, 1.0);\n"
" color = vCol;\n"
"}\n";
static const char* fragment_shader_text =
"varying vec3 color;\n"
"void main()\n"
"{\n"
" gl_FragColor = vec4(color, 1.0);\n"
"}\n";
static void error_callback(int error, const char* description)
{
fprintf(stderr, "Error: %s\n", description);
}
static void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods)
{
if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS)
glfwSetWindowShouldClose(window, GLFW_TRUE);
}
// Dumps the window's color buffer in ImageMagick .miff format.
void dumpFramebuffer(GLFWwindow* window)
{
// Switch to the given context.
GLFWwindow* old = glfwGetCurrentContext();
glfwMakeContextCurrent(window);
// Fetch the framebuffer.
int width;
int height;
void* buffer;
glfwGetFramebufferSize(window, &width, &height);
buffer = malloc(width * height * 4);
glReadPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, buffer);
// Write to an ImageMagick .miff file.
FILE *fp = fopen("simple.miff", "w");
fprintf(fp, "id=ImageMagick version=1.0\n");
fprintf(fp, "class=DirectClass matte=True\n");
fprintf(fp, "columns=%d rows=%d\n", width, height);
fprintf(fp, "\f\n:\032");
void* ptr;
for (ptr = buffer + (height - 1) * width * 4;
ptr >= buffer;
ptr -= width * 4)
{
fwrite(ptr, 1, width * 4, fp);
}
fclose(fp);
printf("Wrote simple.miff!\n");
// Toss the buffer.
free(buffer);
// Restore the original context.
glfwMakeContextCurrent(old);
}
int main(void)
{
GLFWwindow* window;
GLuint vertex_buffer, vertex_shader, fragment_shader, program;
GLint mvp_location, vpos_location, vcol_location;
glfwSetErrorCallback(error_callback);
if (!glfwInit())
exit(EXIT_FAILURE);
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 2);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 0);
window = glfwCreateWindow(640, 480, "Simple example", NULL, NULL);
if (!window)
{
glfwTerminate();
exit(EXIT_FAILURE);
}
glfwSetKeyCallback(window, key_callback);
glfwMakeContextCurrent(window);
gladLoadGLLoader((GLADloadproc) glfwGetProcAddress);
glfwSwapInterval(1);
// NOTE: OpenGL error checks have been omitted for brevity
glGenBuffers(1, &vertex_buffer);
glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
vertex_shader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertex_shader, 1, &vertex_shader_text, NULL);
glCompileShader(vertex_shader);
fragment_shader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragment_shader, 1, &fragment_shader_text, NULL);
glCompileShader(fragment_shader);
program = glCreateProgram();
glAttachShader(program, vertex_shader);
glAttachShader(program, fragment_shader);
glLinkProgram(program);
mvp_location = glGetUniformLocation(program, "MVP");
vpos_location = glGetAttribLocation(program, "vPos");
vcol_location = glGetAttribLocation(program, "vCol");
glEnableVertexAttribArray(vpos_location);
glVertexAttribPointer(vpos_location, 2, GL_FLOAT, GL_FALSE,
sizeof(float) * 5, (void*) 0);
glEnableVertexAttribArray(vcol_location);
glVertexAttribPointer(vcol_location, 3, GL_FLOAT, GL_FALSE,
sizeof(float) * 5, (void*) (sizeof(float) * 2));
int snap = 5;
while (!glfwWindowShouldClose(window))
{
float ratio;
int width, height;
mat4x4 m, p, mvp;
glfwGetFramebufferSize(window, &width, &height);
ratio = width / (float) height;
glViewport(0, 0, width, height);
glClear(GL_COLOR_BUFFER_BIT);
mat4x4_identity(m);
mat4x4_rotate_Z(m, m, (float) glfwGetTime());
mat4x4_ortho(p, -ratio, ratio, -1.f, 1.f, 1.f, -1.f);
mat4x4_mul(mvp, p, m);
glUseProgram(program);
glUniformMatrix4fv(mvp_location, 1, GL_FALSE, (const GLfloat*) mvp);
glDrawArrays(GL_TRIANGLES, 0, 3);
glfwSwapBuffers(window);
glfwPollEvents();
if (--snap == 0)
{
dumpFramebuffer(window);
glfwSetWindowShouldClose(window, GLFW_TRUE);
}
}
glfwDestroyWindow(window);
glfwTerminate();
exit(EXIT_SUCCESS);
}
//! [code]

View File

@ -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

View File

@ -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)

View File

@ -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

View File

@ -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
View 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
View 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
View 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
View 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
View 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
View 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;
}