Refactor GlOffscreen; remove the GLEW dependency.
It was never really needed, since both Linux and OS X, where GlOffscreen is used, guarantee that the API we need is present, on all OS versions we're interested in. Also, reorganize GlOffscreen consistently with the rest of our codebase, and don't use RAII for OpenGL resource management because of its requirement for an active context.
This commit is contained in:
parent
216091a366
commit
7265121b24
@ -4,5 +4,5 @@ sudo add-apt-repository -y ppa:ubuntu-toolchain-r/test
|
|||||||
sudo apt-get update -qq
|
sudo apt-get update -qq
|
||||||
sudo apt-get install -q -y \
|
sudo apt-get install -q -y \
|
||||||
cmake cmake-data libpng12-dev zlib1g-dev libjson0-dev libfontconfig1-dev \
|
cmake cmake-data libpng12-dev zlib1g-dev libjson0-dev libfontconfig1-dev \
|
||||||
libgtkmm-2.4-dev libpangomm-1.4-dev libgl1-mesa-dev libglu-dev libglew-dev \
|
libgtkmm-2.4-dev libpangomm-1.4-dev libgl1-mesa-dev libglu-dev \
|
||||||
libfreetype6-dev dpkg-dev gcc-5 g++-5
|
libfreetype6-dev dpkg-dev gcc-5 g++-5
|
||||||
|
@ -196,7 +196,6 @@ else() # Linux and compatible systems
|
|||||||
pkg_check_modules(PNG REQUIRED libpng)
|
pkg_check_modules(PNG REQUIRED libpng)
|
||||||
pkg_check_modules(FONTCONFIG REQUIRED fontconfig)
|
pkg_check_modules(FONTCONFIG REQUIRED fontconfig)
|
||||||
pkg_check_modules(JSONC REQUIRED json-c)
|
pkg_check_modules(JSONC REQUIRED json-c)
|
||||||
pkg_check_modules(GLEW REQUIRED glew)
|
|
||||||
pkg_check_modules(FREETYPE REQUIRED freetype2)
|
pkg_check_modules(FREETYPE REQUIRED freetype2)
|
||||||
|
|
||||||
set(HAVE_GTK TRUE)
|
set(HAVE_GTK TRUE)
|
||||||
|
@ -31,7 +31,7 @@ On a Debian derivative (e.g. Ubuntu) these can be installed with:
|
|||||||
|
|
||||||
apt-get install libpng-dev libjson-c-dev libfreetype6-dev \
|
apt-get install libpng-dev libjson-c-dev libfreetype6-dev \
|
||||||
libfontconfig1-dev libgtkmm-2.4-dev libpangomm-1.4-dev \
|
libfontconfig1-dev libgtkmm-2.4-dev libpangomm-1.4-dev \
|
||||||
libgl-dev libglu-dev libglew-dev cmake
|
libgl-dev libglu-dev cmake
|
||||||
|
|
||||||
Before building, check out the necessary submodules:
|
Before building, check out the necessary submodules:
|
||||||
|
|
||||||
|
2
debian/control
vendored
2
debian/control
vendored
@ -4,7 +4,7 @@ Priority: optional
|
|||||||
Maintainer: whitequark <whitequark@whitequark.org>
|
Maintainer: whitequark <whitequark@whitequark.org>
|
||||||
Build-Depends: debhelper (>= 9), cmake, libpng-dev, zlib1g-dev, libjson-c-dev,
|
Build-Depends: debhelper (>= 9), cmake, libpng-dev, zlib1g-dev, libjson-c-dev,
|
||||||
libfontconfig1-dev, libgtkmm-2.4-dev, libpangomm-1.4-dev,
|
libfontconfig1-dev, libgtkmm-2.4-dev, libpangomm-1.4-dev,
|
||||||
libgl-dev, libglu-dev, libglew-dev
|
libgl-dev, libglu-dev
|
||||||
Standards-Version: 3.9.5
|
Standards-Version: 3.9.5
|
||||||
Homepage: http://solvespace.com
|
Homepage: http://solvespace.com
|
||||||
Vcs-Git: git://github.com/whitequark/solvespace
|
Vcs-Git: git://github.com/whitequark/solvespace
|
||||||
|
@ -89,7 +89,7 @@ elseif(APPLE)
|
|||||||
|
|
||||||
set(platform_SOURCES
|
set(platform_SOURCES
|
||||||
platform/cocoamain.mm
|
platform/cocoamain.mm
|
||||||
platform/gloffscreen.cpp)
|
render/rendergl.cpp)
|
||||||
|
|
||||||
set(platform_BUNDLED_LIBS
|
set(platform_BUNDLED_LIBS
|
||||||
${PNG_LIBRARIES}
|
${PNG_LIBRARIES}
|
||||||
@ -101,30 +101,26 @@ elseif(HAVE_GTK)
|
|||||||
include_directories(
|
include_directories(
|
||||||
${GTKMM_INCLUDE_DIRS}
|
${GTKMM_INCLUDE_DIRS}
|
||||||
${JSONC_INCLUDE_DIRS}
|
${JSONC_INCLUDE_DIRS}
|
||||||
${FONTCONFIG_INCLUDE_DIRS}
|
${FONTCONFIG_INCLUDE_DIRS})
|
||||||
${GLEW_INCLUDE_DIRS})
|
|
||||||
|
|
||||||
link_directories(
|
link_directories(
|
||||||
${GTKMM_LIBRARY_DIRS}
|
${GTKMM_LIBRARY_DIRS}
|
||||||
${JSONC_LIBRARY_DIRS}
|
${JSONC_LIBRARY_DIRS}
|
||||||
${FONTCONFIG_LIBRARY_DIRS}
|
${FONTCONFIG_LIBRARY_DIRS})
|
||||||
${GLEW_LIBRARY_DIRS})
|
|
||||||
|
|
||||||
add_definitions(
|
add_definitions(
|
||||||
${GTKMM_CFLAGS_OTHER}
|
${GTKMM_CFLAGS_OTHER}
|
||||||
${JSONC_CFLAGS_OTHER}
|
${JSONC_CFLAGS_OTHER}
|
||||||
${FONTCONFIG_CFLAGS_OTHER}
|
${FONTCONFIG_CFLAGS_OTHER})
|
||||||
${GLEW_CFLAGS_OTHER})
|
|
||||||
|
|
||||||
set(platform_SOURCES
|
set(platform_SOURCES
|
||||||
platform/gtkmain.cpp
|
platform/gtkmain.cpp
|
||||||
platform/gloffscreen.cpp)
|
render/rendergl.cpp)
|
||||||
|
|
||||||
set(platform_LIBRARIES
|
set(platform_LIBRARIES
|
||||||
${GTKMM_LIBRARIES}
|
${GTKMM_LIBRARIES}
|
||||||
${JSONC_LIBRARIES}
|
${JSONC_LIBRARIES}
|
||||||
${FONTCONFIG_LIBRARIES}
|
${FONTCONFIG_LIBRARIES})
|
||||||
${GLEW_LIBRARIES})
|
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# solvespace executable
|
# solvespace executable
|
||||||
|
@ -7,9 +7,6 @@
|
|||||||
// Copyright 2008-2013 Jonathan Westhues.
|
// Copyright 2008-2013 Jonathan Westhues.
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
#include "solvespace.h"
|
#include "solvespace.h"
|
||||||
#ifndef WIN32
|
|
||||||
#include <platform/gloffscreen.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
void SolveSpaceUI::ExportSectionTo(const std::string &filename) {
|
void SolveSpaceUI::ExportSectionTo(const std::string &filename) {
|
||||||
Vector gn = (SS.GW.projRight).Cross(SS.GW.projUp);
|
Vector gn = (SS.GW.projRight).Cross(SS.GW.projUp);
|
||||||
@ -1084,10 +1081,11 @@ void SolveSpaceUI::ExportAsPngTo(const std::string &filename) {
|
|||||||
bool prevShowToolbar = SS.showToolbar;
|
bool prevShowToolbar = SS.showToolbar;
|
||||||
SS.showToolbar = false;
|
SS.showToolbar = false;
|
||||||
#ifndef WIN32
|
#ifndef WIN32
|
||||||
std::unique_ptr<GLOffscreen> gloffscreen(new GLOffscreen);
|
GlOffscreen offscreen;
|
||||||
gloffscreen->begin((int)SS.GW.width, (int)SS.GW.height);
|
offscreen.Render((int)SS.GW.width, (int)SS.GW.height, [&] {
|
||||||
|
SS.GW.Paint();
|
||||||
|
});
|
||||||
#endif
|
#endif
|
||||||
SS.GW.Paint();
|
|
||||||
SS.showToolbar = prevShowToolbar;
|
SS.showToolbar = prevShowToolbar;
|
||||||
|
|
||||||
// Somewhat hacky way to invoke glReadPixels without dragging in all OpenGL headers.
|
// Somewhat hacky way to invoke glReadPixels without dragging in all OpenGL headers.
|
||||||
@ -1100,6 +1098,11 @@ void SolveSpaceUI::ExportAsPngTo(const std::string &filename) {
|
|||||||
Error("Couldn't write to '%s'", filename.c_str());
|
Error("Couldn't write to '%s'", filename.c_str());
|
||||||
}
|
}
|
||||||
if(f) fclose(f);
|
if(f) fclose(f);
|
||||||
|
|
||||||
|
#ifndef WIN32
|
||||||
|
offscreen.Clear();
|
||||||
|
#endif
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -14,7 +14,6 @@
|
|||||||
#include <map>
|
#include <map>
|
||||||
|
|
||||||
#include "solvespace.h"
|
#include "solvespace.h"
|
||||||
#include "gloffscreen.h"
|
|
||||||
#include <config.h>
|
#include <config.h>
|
||||||
|
|
||||||
using SolveSpace::dbp;
|
using SolveSpace::dbp;
|
||||||
@ -126,7 +125,7 @@ const bool SolveSpace::FLIP_FRAMEBUFFER = false;
|
|||||||
|
|
||||||
@implementation GLViewWithEditor
|
@implementation GLViewWithEditor
|
||||||
{
|
{
|
||||||
GLOffscreen *offscreen;
|
SolveSpace::GlOffscreen offscreen;
|
||||||
NSOpenGLContext *glContext;
|
NSOpenGLContext *glContext;
|
||||||
@protected
|
@protected
|
||||||
NSTextField *editor;
|
NSTextField *editor;
|
||||||
@ -156,7 +155,7 @@ const bool SolveSpace::FLIP_FRAMEBUFFER = false;
|
|||||||
}
|
}
|
||||||
|
|
||||||
- (void)dealloc {
|
- (void)dealloc {
|
||||||
delete offscreen;
|
offscreen.Clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
#define CONVERT1(name, to_from) \
|
#define CONVERT1(name, to_from) \
|
||||||
@ -187,19 +186,13 @@ CONVERT(Rect)
|
|||||||
- (void)drawRect:(NSRect)aRect {
|
- (void)drawRect:(NSRect)aRect {
|
||||||
[glContext makeCurrentContext];
|
[glContext makeCurrentContext];
|
||||||
|
|
||||||
if(!offscreen)
|
|
||||||
offscreen = new GLOffscreen;
|
|
||||||
|
|
||||||
NSSize size = [self convertSizeToBacking:[self bounds].size];
|
NSSize size = [self convertSizeToBacking:[self bounds].size];
|
||||||
int width = (int)size.width,
|
int width = (int)size.width,
|
||||||
height = (int)size.height;
|
height = (int)size.height;
|
||||||
offscreen->begin(width, height);
|
offscreen.Render(width, height, [&] { [self drawGL]; });
|
||||||
|
|
||||||
[self drawGL];
|
|
||||||
|
|
||||||
uint8_t *pixels = offscreen->end();
|
|
||||||
CGDataProviderRef provider = CGDataProviderCreateWithData(
|
CGDataProviderRef provider = CGDataProviderCreateWithData(
|
||||||
NULL, pixels, width * height * 4, NULL);
|
NULL, &offscreen.data[0], width * height * 4, NULL);
|
||||||
CGColorSpaceRef colorspace = CGColorSpaceCreateDeviceRGB();
|
CGColorSpaceRef colorspace = CGColorSpaceCreateDeviceRGB();
|
||||||
CGImageRef image = CGImageCreate(width, height, 8, 32,
|
CGImageRef image = CGImageCreate(width, height, 8, 32,
|
||||||
width * 4, colorspace, kCGBitmapByteOrder32Little | kCGImageAlphaNoneSkipFirst,
|
width * 4, colorspace, kCGBitmapByteOrder32Little | kCGImageAlphaNoneSkipFirst,
|
||||||
|
@ -1,74 +0,0 @@
|
|||||||
//-----------------------------------------------------------------------------
|
|
||||||
// Offscreen rendering in OpenGL using framebuffer objects.
|
|
||||||
//
|
|
||||||
// Copyright 2015 <whitequark@whitequark.org>
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
#ifdef __APPLE__
|
|
||||||
#include <OpenGL/GL.h>
|
|
||||||
#else
|
|
||||||
#include <GL/glew.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "gloffscreen.h"
|
|
||||||
#include "solvespace.h"
|
|
||||||
|
|
||||||
GLOffscreen::GLOffscreen() : _pixels(NULL), _width(0), _height(0) {
|
|
||||||
#ifndef __APPLE__
|
|
||||||
ssassert(glewInit() == GLEW_OK, "Unexpected GLEW failure");
|
|
||||||
#endif
|
|
||||||
|
|
||||||
ssassert(GL_EXT_framebuffer_object, "Expected an available FBO extension");
|
|
||||||
|
|
||||||
glGenFramebuffersEXT(1, &_framebuffer);
|
|
||||||
glGenRenderbuffersEXT(1, &_color_renderbuffer);
|
|
||||||
glGenRenderbuffersEXT(1, &_depth_renderbuffer);
|
|
||||||
}
|
|
||||||
|
|
||||||
GLOffscreen::~GLOffscreen() {
|
|
||||||
delete[] _pixels;
|
|
||||||
glDeleteRenderbuffersEXT(1, &_depth_renderbuffer);
|
|
||||||
glDeleteRenderbuffersEXT(1, &_color_renderbuffer);
|
|
||||||
glDeleteFramebuffersEXT(1, &_framebuffer);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool GLOffscreen::begin(int width, int height) {
|
|
||||||
if(_width != width || _height != height) {
|
|
||||||
delete[] _pixels;
|
|
||||||
_pixels = new uint8_t[width * height * 4];
|
|
||||||
|
|
||||||
_width = width;
|
|
||||||
_height = height;
|
|
||||||
}
|
|
||||||
|
|
||||||
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, _framebuffer);
|
|
||||||
|
|
||||||
glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, _color_renderbuffer);
|
|
||||||
glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_RGBA8, _width, _height);
|
|
||||||
glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
|
|
||||||
GL_RENDERBUFFER_EXT, _color_renderbuffer);
|
|
||||||
|
|
||||||
glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, _depth_renderbuffer);
|
|
||||||
glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT24, _width, _height);
|
|
||||||
glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT,
|
|
||||||
GL_RENDERBUFFER_EXT, _depth_renderbuffer);
|
|
||||||
|
|
||||||
if(glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT) == GL_FRAMEBUFFER_COMPLETE_EXT)
|
|
||||||
return true;
|
|
||||||
|
|
||||||
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8_t *GLOffscreen::end() {
|
|
||||||
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
|
|
||||||
glReadPixels(0, 0, _width, _height,
|
|
||||||
GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, _pixels);
|
|
||||||
#else
|
|
||||||
glReadPixels(0, 0, _width, _height,
|
|
||||||
GL_BGRA, GL_UNSIGNED_INT_8_8_8_8, _pixels);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
|
|
||||||
|
|
||||||
return _pixels;
|
|
||||||
}
|
|
@ -1,36 +0,0 @@
|
|||||||
//-----------------------------------------------------------------------------
|
|
||||||
// Offscreen rendering in OpenGL using framebuffer objects.
|
|
||||||
//
|
|
||||||
// Copyright 2015 <whitequark@whitequark.org>
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
#ifndef __GLOFFSCREEN_H
|
|
||||||
#define __GLOFFSCREEN_H
|
|
||||||
|
|
||||||
#include <stdint.h>
|
|
||||||
|
|
||||||
class GLOffscreen {
|
|
||||||
public:
|
|
||||||
/* these allocate and deallocate OpenGL resources.
|
|
||||||
an OpenGL context /must/ be current. */
|
|
||||||
GLOffscreen();
|
|
||||||
~GLOffscreen();
|
|
||||||
|
|
||||||
/* prepare for drawing a frame of specified size.
|
|
||||||
returns true if OpenGL likes our configuration, false
|
|
||||||
otherwise. if it returns false, the OpenGL state is restored. */
|
|
||||||
bool begin(int width, int height);
|
|
||||||
|
|
||||||
/* get pixels out of the frame and restore OpenGL state.
|
|
||||||
the pixel format is ARGB32 with top row at index 0 if
|
|
||||||
flip is true and bottom row at index 0 if flip is false.
|
|
||||||
the returned array is valid until the next call to begin() */
|
|
||||||
uint8_t *end();
|
|
||||||
|
|
||||||
private:
|
|
||||||
unsigned int _framebuffer;
|
|
||||||
unsigned int _color_renderbuffer, _depth_renderbuffer;
|
|
||||||
uint8_t *_pixels;
|
|
||||||
int _width, _height;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
@ -52,7 +52,6 @@
|
|||||||
|
|
||||||
#include "solvespace.h"
|
#include "solvespace.h"
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "gloffscreen.h"
|
|
||||||
|
|
||||||
#ifdef HAVE_SPACEWARE
|
#ifdef HAVE_SPACEWARE
|
||||||
# include <spnav.h>
|
# include <spnav.h>
|
||||||
@ -228,7 +227,7 @@ const bool FLIP_FRAMEBUFFER = true;
|
|||||||
|
|
||||||
class GlWidget : public Gtk::DrawingArea {
|
class GlWidget : public Gtk::DrawingArea {
|
||||||
public:
|
public:
|
||||||
GlWidget() : _offscreen(NULL) {
|
GlWidget() {
|
||||||
_xdisplay = gdk_x11_get_default_xdisplay();
|
_xdisplay = gdk_x11_get_default_xdisplay();
|
||||||
|
|
||||||
int glxmajor, glxminor;
|
int glxmajor, glxminor;
|
||||||
@ -297,7 +296,7 @@ public:
|
|||||||
|
|
||||||
XDestroyWindow(_xdisplay, _xwindow);
|
XDestroyWindow(_xdisplay, _xwindow);
|
||||||
|
|
||||||
delete _offscreen;
|
_offscreen.Clear();
|
||||||
|
|
||||||
glXDestroyContext(_xdisplay, _glcontext);
|
glXDestroyContext(_xdisplay, _glcontext);
|
||||||
}
|
}
|
||||||
@ -314,18 +313,16 @@ protected:
|
|||||||
ssassert(glXMakeCurrent(_xdisplay, _xwindow, _glcontext),
|
ssassert(glXMakeCurrent(_xdisplay, _xwindow, _glcontext),
|
||||||
"Cannot make OpenGL context current");
|
"Cannot make OpenGL context current");
|
||||||
|
|
||||||
if(!_offscreen)
|
|
||||||
_offscreen = new GLOffscreen;
|
|
||||||
|
|
||||||
Gdk::Rectangle allocation = get_allocation();
|
Gdk::Rectangle allocation = get_allocation();
|
||||||
ssassert(_offscreen->begin(allocation.get_width(), allocation.get_height()),
|
bool success = _offscreen.Render(
|
||||||
"Cannot allocate offscreen rendering buffer");
|
allocation.get_width(), allocation.get_height(),
|
||||||
|
sigc::mem_fun(this, &GlWidget::on_gl_draw));
|
||||||
|
ssassert(success, "Cannot allocate offscreen rendering buffer");
|
||||||
|
|
||||||
on_gl_draw();
|
Cairo::RefPtr<Cairo::ImageSurface> surface =
|
||||||
|
Cairo::ImageSurface::create(&_offscreen.data[0], Cairo::FORMAT_RGB24,
|
||||||
Cairo::RefPtr<Cairo::ImageSurface> surface = Cairo::ImageSurface::create(
|
allocation.get_width(), allocation.get_height(),
|
||||||
_offscreen->end(), Cairo::FORMAT_RGB24,
|
allocation.get_width() * 4);
|
||||||
allocation.get_width(), allocation.get_height(), allocation.get_width() * 4);
|
|
||||||
cr->set_source(surface, 0, 0);
|
cr->set_source(surface, 0, 0);
|
||||||
cr->paint();
|
cr->paint();
|
||||||
surface->finish();
|
surface->finish();
|
||||||
@ -338,7 +335,7 @@ protected:
|
|||||||
private:
|
private:
|
||||||
Display *_xdisplay;
|
Display *_xdisplay;
|
||||||
GLXContext _glcontext;
|
GLXContext _glcontext;
|
||||||
GLOffscreen *_offscreen;
|
GlOffscreen _offscreen;
|
||||||
::Window _xwindow;
|
::Window _xwindow;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -204,6 +204,17 @@ public:
|
|||||||
bool Pick(std::function<void()> drawFn);
|
bool Pick(std::function<void()> drawFn);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// An offscreen renderer based on OpenGL framebuffers.
|
||||||
|
class GlOffscreen {
|
||||||
|
public:
|
||||||
|
unsigned int framebuffer;
|
||||||
|
unsigned int colorRenderbuffer, depthRenderbuffer;
|
||||||
|
std::vector<uint8_t> data;
|
||||||
|
|
||||||
|
bool Render(int width, int height, std::function<void()> renderFn);
|
||||||
|
void Clear();
|
||||||
|
};
|
||||||
|
|
||||||
// A canvas that uses the core OpenGL profile, for desktop systems.
|
// A canvas that uses the core OpenGL profile, for desktop systems.
|
||||||
class OpenGl1Renderer : public Canvas {
|
class OpenGl1Renderer : public Canvas {
|
||||||
public:
|
public:
|
||||||
|
57
src/render/rendergl.cpp
Normal file
57
src/render/rendergl.cpp
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Offscreen rendering in OpenGL using EGL and framebuffer objects.
|
||||||
|
//
|
||||||
|
// Copyright 2015-2016 whitequark
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
#ifdef __APPLE__
|
||||||
|
#include <OpenGL/GL.h>
|
||||||
|
#else
|
||||||
|
#define GL_GLEXT_PROTOTYPES
|
||||||
|
#include <GL/gl.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "solvespace.h"
|
||||||
|
|
||||||
|
void GlOffscreen::Clear() {
|
||||||
|
glDeleteRenderbuffersEXT(1, &depthRenderbuffer);
|
||||||
|
glDeleteRenderbuffersEXT(1, &colorRenderbuffer);
|
||||||
|
glDeleteFramebuffersEXT(1, &framebuffer);
|
||||||
|
*this = {};
|
||||||
|
}
|
||||||
|
|
||||||
|
bool GlOffscreen::Render(int width, int height, std::function<void()> renderFn) {
|
||||||
|
data.resize(width * height * 4);
|
||||||
|
|
||||||
|
if(framebuffer == 0) {
|
||||||
|
glGenFramebuffersEXT(1, &framebuffer);
|
||||||
|
glGenRenderbuffersEXT(1, &colorRenderbuffer);
|
||||||
|
glGenRenderbuffersEXT(1, &depthRenderbuffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, framebuffer);
|
||||||
|
|
||||||
|
glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, colorRenderbuffer);
|
||||||
|
glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_RGBA8, width, height);
|
||||||
|
glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
|
||||||
|
GL_RENDERBUFFER_EXT, colorRenderbuffer);
|
||||||
|
|
||||||
|
glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, depthRenderbuffer);
|
||||||
|
glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT24, width, height);
|
||||||
|
glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT,
|
||||||
|
GL_RENDERBUFFER_EXT, depthRenderbuffer);
|
||||||
|
|
||||||
|
bool framebufferComplete =
|
||||||
|
glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT) == GL_FRAMEBUFFER_COMPLETE_EXT;
|
||||||
|
if(framebufferComplete) {
|
||||||
|
renderFn();
|
||||||
|
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
|
||||||
|
glReadPixels(0, 0, width, height, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, &data[0]);
|
||||||
|
#else
|
||||||
|
glReadPixels(0, 0, width, height, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8, &data[0]);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
|
||||||
|
|
||||||
|
return framebufferComplete;
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user