Merge pull request #1250 from bgK/wip-multisampling

Multisampling for framebuffers
This commit is contained in:
Bastien Bouclet 2016-06-12 19:53:14 +02:00 committed by GitHub
commit fe4aac9ada
7 changed files with 260 additions and 116 deletions

View File

@ -75,6 +75,7 @@ SurfaceSdlGraphicsManager::SurfaceSdlGraphicsManager(SdlEventSource *sdlEventSou
{
ConfMan.registerDefault("fullscreen_res", "desktop");
ConfMan.registerDefault("aspect_ratio", true);
ConfMan.registerDefault("antialiasing", 0);
const SDL_VideoInfo *vi = SDL_GetVideoInfo();
_desktopW = vi->current_w;
@ -193,7 +194,7 @@ void SurfaceSdlGraphicsManager::setupScreen(uint gameWidth, uint gameHeight, boo
#ifdef USE_OPENGL
_opengl = accel3d;
_antialiasing = 0;
_antialiasing = ConfMan.getInt("antialiasing");
#endif
_fullscreen = fullscreen;
_lockAspectRatio = ConfMan.getBool("aspect_ratio");
@ -223,80 +224,19 @@ void SurfaceSdlGraphicsManager::setupScreen(uint gameWidth, uint gameHeight, boo
// Compute the rectangle where to draw the game inside the effective screen
_gameRect = computeGameRect(gameRenderTarget, gameWidth, gameHeight, effectiveWidth, effectiveHeight);
uint32 sdlflags;
int bpp;
#ifdef USE_OPENGL
if (_opengl) {
if (ConfMan.hasKey("antialiasing"))
_antialiasing = ConfMan.getInt("antialiasing");
SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8);
SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8);
SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8);
SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, 8);
SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24);
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 8);
setAntialiasing(true);
sdlflags = SDL_OPENGL;
bpp = 24;
createScreenOpenGL(effectiveWidth, effectiveHeight, gameRenderTarget);
} else
#endif
{
bpp = 16;
sdlflags = SDL_SWSURFACE;
}
uint32 sdlflags = SDL_SWSURFACE;
if (_fullscreen)
sdlflags |= SDL_FULLSCREEN;
if (_fullscreen)
sdlflags |= SDL_FULLSCREEN;
_screen = SDL_SetVideoMode(effectiveWidth, effectiveHeight, bpp, sdlflags);
#ifdef USE_OPENGL
// If 32-bit with antialiasing failed, try 32-bit without antialiasing
if (!_screen && _opengl && _antialiasing) {
warning("Couldn't create 32-bit visual with AA, trying 32-bit without AA");
setAntialiasing(false);
_screen = SDL_SetVideoMode(effectiveWidth, effectiveHeight, bpp, sdlflags);
_screen = SDL_SetVideoMode(effectiveWidth, effectiveHeight, 16, sdlflags);
}
// If 32-bit failed, try 16-bit
if (!_screen && _opengl) {
warning("Couldn't create 32-bit visual, trying 16-bit");
SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 5);
SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 5);
SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 5);
SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, 1);
setAntialiasing(true);
_screen = SDL_SetVideoMode(effectiveWidth, effectiveHeight, 0, sdlflags);
}
// If 16-bit with antialiasing failed, try 16-bit without antialiasing
if (!_screen && _opengl && _antialiasing) {
warning("Couldn't create 16-bit visual with AA, trying 16-bit without AA");
setAntialiasing(false);
_screen = SDL_SetVideoMode(effectiveWidth, effectiveHeight, 0, sdlflags);
}
// If 16-bit with alpha failed, try 16-bit without alpha
if (!_screen && _opengl) {
warning("Couldn't create 16-bit visual with alpha, trying without alpha");
SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 5);
SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 6);
SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 5);
SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, 0);
setAntialiasing(true);
_screen = SDL_SetVideoMode(effectiveWidth, effectiveHeight, 0, sdlflags);
}
// If 16-bit without alpha and with antialiasing didn't work, try without antialiasing
if (!_screen && _opengl && _antialiasing) {
warning("Couldn't create 16-bit visual with AA, trying 16-bit without AA");
setAntialiasing(false);
_screen = SDL_SetVideoMode(effectiveWidth, effectiveHeight, 0, sdlflags);
}
#endif
if (!_screen) {
warning("Error: %s", SDL_GetError());
g_system->quit();
@ -404,12 +344,12 @@ void SurfaceSdlGraphicsManager::setupScreen(uint gameWidth, uint gameHeight, boo
#if defined(USE_OPENGL) && !defined(AMIGAOS)
if (gameRenderTarget == kFramebuffer) {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
_frameBuffer = new OpenGL::FrameBuffer(gameWidth, gameHeight);
_frameBuffer = createFramebuffer(gameWidth, gameHeight);
_frameBuffer->attach();
}
#endif
if (gameRenderTarget == kSubScreen) {
_subScreen = SDL_CreateRGBSurface(SDL_SWSURFACE, gameWidth, gameHeight, bpp, _screen->format->Rmask, _screen->format->Gmask, _screen->format->Bmask, _screen->format->Amask);
_subScreen = SDL_CreateRGBSurface(SDL_SWSURFACE, gameWidth, gameHeight, f->BitsPerPixel, f->Rmask, f->Gmask, f->Bmask, f->Amask);
}
}
@ -534,6 +474,68 @@ void SurfaceSdlGraphicsManager::initializeOpenGLContext() const {
OpenGLContext.initialize(type);
}
SurfaceSdlGraphicsManager::OpenGLPixelFormat::OpenGLPixelFormat(uint screenBytesPerPixel, uint red, uint blue, uint green, uint alpha, int samples) :
bytesPerPixel(screenBytesPerPixel),
redSize(red),
blueSize(blue),
greenSize(green),
alphaSize(alpha),
multisampleSamples(samples) {
}
void SurfaceSdlGraphicsManager::createScreenOpenGL(uint effectiveWidth, uint effectiveHeight, GameRenderTarget gameRenderTarget) {
// Build a list of OpenGL pixel formats usable by ResidualVM
Common::Array<OpenGLPixelFormat> pixelFormats;
if (_antialiasing > 0 && gameRenderTarget == kScreen) {
// Don't enable screen level multisampling when rendering to a framebuffer
pixelFormats.push_back(OpenGLPixelFormat(32, 8, 8, 8, 8, _antialiasing));
pixelFormats.push_back(OpenGLPixelFormat(16, 5, 5, 5, 1, _antialiasing));
pixelFormats.push_back(OpenGLPixelFormat(16, 5, 6, 5, 0, _antialiasing));
}
pixelFormats.push_back(OpenGLPixelFormat(32, 8, 8, 8, 8, 0));
pixelFormats.push_back(OpenGLPixelFormat(16, 5, 5, 5, 1, 0));
pixelFormats.push_back(OpenGLPixelFormat(16, 5, 6, 5, 0, 0));
uint32 sdlflags = SDL_OPENGL;
if (_fullscreen)
sdlflags |= SDL_FULLSCREEN;
// Unfortunatly, SDL does not provide a list of valid pixel formats
// for the current OpenGL implementation and hardware.
// SDL may not be able to create a screen with the preferred pixel format.
// Try all the pixel formats in the list until SDL returns a valid screen.
Common::Array<OpenGLPixelFormat>::const_iterator it = pixelFormats.begin();
for (; it != pixelFormats.end(); it++) {
SDL_GL_SetAttribute(SDL_GL_RED_SIZE, it->redSize);
SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, it->greenSize);
SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, it->blueSize);
SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, it->alphaSize);
SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24);
SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 8);
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, it->multisampleSamples > 0);
SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, it->multisampleSamples);
_screen = SDL_SetVideoMode(effectiveWidth, effectiveHeight, it->bytesPerPixel, sdlflags);
if (_screen) {
break;
}
}
// Display a warning if the effective pixel format is not the preferred one
if (it != pixelFormats.begin() && it != pixelFormats.end()) {
bool wantsAA = pixelFormats.front().multisampleSamples > 0;
bool gotAA = it->multisampleSamples > 0;
warning("Couldn't create a %d-bit visual%s, using to %d-bit%s instead",
pixelFormats.front().bytesPerPixel,
wantsAA && !gotAA ? " with AA" : "",
it->bytesPerPixel,
wantsAA && !gotAA ? " without AA" : "");
}
}
#define BITMAP_TEXTURE_SIZE 256
void SurfaceSdlGraphicsManager::updateOverlayTextures() {
@ -613,6 +615,17 @@ void SurfaceSdlGraphicsManager::drawSideTexturesOpenGL() {
}
}
OpenGL::FrameBuffer *SurfaceSdlGraphicsManager::createFramebuffer(uint width, uint height) {
#ifndef USE_GLES2
if (_antialiasing && OpenGLContext.framebufferObjectMultisampleSupported) {
return new OpenGL::MultiSampleFrameBuffer(width, height, _antialiasing);
} else
#endif
{
return new OpenGL::FrameBuffer(width, height);
}
}
#endif
void SurfaceSdlGraphicsManager::drawSideTextures() {
@ -1027,23 +1040,6 @@ void SurfaceSdlGraphicsManager::displayMessageOnOSD(const char *msg) {
}
#endif
#ifdef USE_OPENGL
void SurfaceSdlGraphicsManager::setAntialiasing(bool enable) {
// Antialiasing works without setting MULTISAMPLEBUFFERS, but as SDL's official
// tests set both values, this seems to be the standard way to do it. It could
// just be that in current OpenGL implementations setting SDL_GL_MULTISAMPLESAMPLES
// implicitly sets SDL_GL_MULTISAMPLEBUFFERS as well.
if (_antialiasing && enable) {
SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, 1);
SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, _antialiasing);
} else {
SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, 0);
SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, 0);
}
}
#endif
bool SurfaceSdlGraphicsManager::notifyEvent(const Common::Event &event) {
//ResidualVM specific:
switch ((int)event.type) {

View File

@ -138,6 +138,30 @@ public:
virtual void notifyMousePos(Common::Point mouse);
protected:
/**
* Places where the game can be drawn
*/
enum GameRenderTarget {
kScreen, /** The game is drawn directly on the screen */
kSubScreen, /** The game is drawn to a surface, which is centered on the screen */
kFramebuffer /** The game is drawn to a framebuffer, which is scaled to fit the screen */
};
/** Select the best draw target according to the specified parameters */
GameRenderTarget selectGameRenderTarget(bool fullscreen, bool accel3d,
bool engineSupportsArbitraryResolutions,
bool framebufferSupported,
bool lockAspectRatio);
/** Compute the size and position of the game rectangle in the screen */
Math::Rect2d computeGameRect(GameRenderTarget gameRenderTarget, uint gameWidth, uint gameHeight,
uint effectiveWidth, uint effectiveHeight);
/** Checks if the render target supports drawing at arbitrary resolutions */
bool canUsePreferredResolution(GameRenderTarget gameRenderTarget, bool engineSupportsArbitraryResolutions);
/** Obtain the user configured fullscreen resolution, or default to the desktop resolution */
Common::Rect getPreferredFullscreenResolution();
#if SDL_VERSION_ATLEAST(2, 0, 0)
SDL_Renderer *_renderer;
@ -169,9 +193,27 @@ protected:
Math::Rect2d _gameRect;
#ifdef USE_OPENGL
struct OpenGLPixelFormat {
uint bytesPerPixel;
uint redSize;
uint blueSize;
uint greenSize;
uint alphaSize;
int multisampleSamples;
OpenGLPixelFormat(uint screenBytesPerPixel, uint red, uint blue, uint green, uint alpha, int samples);
};
/**
* Initialize an OpenGL window matching as closely as possible the required properties
*
* When unable to create a context with anti-aliasing this tries without.
* When unable to create a context with the desired pixel depth this tries lower values.
*/
void createScreenOpenGL(uint effectiveWidth, uint effectiveHeight, GameRenderTarget gameRenderTarget);
// Antialiasing
int _antialiasing;
void setAntialiasing(bool enable);
// Overlay
Common::Array<OpenGL::Texture *> _overlayTextures;
@ -184,6 +226,7 @@ protected:
void drawSideTexturesOpenGL();
OpenGL::FrameBuffer *_frameBuffer;
OpenGL::FrameBuffer *createFramebuffer(uint width, uint height);
OpenGL::SurfaceRenderer *_surfaceRenderer;
@ -200,31 +243,6 @@ protected:
void drawSideTextures();
bool detectFramebufferSupport();
/**
* Places where the game can be drawn
*/
enum GameRenderTarget {
kScreen, /** The game is drawn directly on the screen */
kSubScreen, /** The game is drawn to a surface, which is centered on the screen */
kFramebuffer /** The game is drawn to a framebuffer, which is scaled to fit the screen */
};
/** Select the best draw target according to the specified parameters */
GameRenderTarget selectGameRenderTarget(bool fullscreen, bool accel3d,
bool engineSupportsArbitraryResolutions,
bool framebufferSupported,
bool lockAspectRatio);
/** Compute the size and position of the game rectangle in the screen */
Math::Rect2d computeGameRect(GameRenderTarget gameRenderTarget, uint gameWidth, uint gameHeight,
uint effectiveWidth, uint effectiveHeight);
/** Checks if the render target supports drawing at arbitrary resolutions */
bool canUsePreferredResolution(GameRenderTarget gameRenderTarget, bool engineSupportsArbitraryResolutions);
/** Obtain the user configured fullscreen resolution, or default to the desktop resolution */
Common::Rect getPreferredFullscreenResolution();
};
#endif

View File

@ -49,6 +49,8 @@ void Context::reset() {
framebufferObjectSupported = false;
packedDepthStencilSupported = false;
unpackSubImageSupported = false;
framebufferObjectMultisampleSupported = false;
multisampleMaxSamples = -1;
}
void Context::initialize(ContextType contextType) {
@ -67,6 +69,8 @@ void Context::initialize(ContextType contextType) {
bool ARBShadingLanguage100 = false;
bool ARBVertexShader = false;
bool ARBFragmentShader = false;
bool EXTFramebufferMultisample = false;
bool EXTFramebufferBlit = false;
Common::StringTokenizer tokenizer(extString, " ");
while (!tokenizer.empty()) {
@ -88,6 +92,10 @@ void Context::initialize(ContextType contextType) {
packedDepthStencilSupported = true;
} else if (token == "GL_EXT_unpack_subimage") {
unpackSubImageSupported = true;
} else if (token == "GL_EXT_framebuffer_multisample") {
EXTFramebufferMultisample = true;
} else if (token == "GL_EXT_framebuffer_blit") {
EXTFramebufferBlit = true;
}
}
@ -103,11 +111,21 @@ void Context::initialize(ContextType contextType) {
// GLES2 always has FBO support.
framebufferObjectSupported = true;
// ResidualVM does not support multisample FBOs with GLES2 for now
framebufferObjectMultisampleSupported = false;
multisampleMaxSamples = -1;
} else {
shadersSupported = ARBShaderObjects && ARBShadingLanguage100 && ARBVertexShader && ARBFragmentShader && glslVersion >= 120;
// Desktop GL always has unpack sub-image support
unpackSubImageSupported = true;
framebufferObjectMultisampleSupported = EXTFramebufferMultisample && EXTFramebufferBlit;
if (framebufferObjectMultisampleSupported) {
glGetIntegerv(GL_MAX_SAMPLES, (GLint *)&multisampleMaxSamples);
}
}
// Log context type.

View File

@ -71,6 +71,15 @@ public:
/** Whether FBO support is available or not. */
bool framebufferObjectSupported;
/** Whether multisample FBO support is available or not */
bool framebufferObjectMultisampleSupported;
/**
* Contains the maximum number of supported multisample samples
* if multisample FBOs are supported. Contains -1 otherwise.
*/
int multisampleMaxSamples;
/** Whether packing the depth and stencil buffers is possible or not. */
bool packedDepthStencilSupported;

View File

@ -21,6 +21,7 @@
*/
#include "common/textconsole.h"
#include "common/util.h"
#if defined(USE_OPENGL) && !defined(AMIGAOS)
@ -36,7 +37,9 @@
#define GL_STENCIL_ATTACHMENT GL_STENCIL_ATTACHMENT_EXT
#define GL_STENCIL_INDEX8 GL_STENCIL_INDEX8_EXT
#define GL_DEPTH24_STENCIL8 0x88F0
#endif
#define GL_READ_FRAMEBUFFER 0x8CA8
#define GL_DRAW_FRAMEBUFFER 0x8CA9
#endif // defined(GL_ARB_framebuffer_object)
#include "backends/platform/sdl/sdl-sys.h"
#else
#include "graphics/opengl/framebuffer.h"
@ -62,6 +65,11 @@ static PFNGLFRAMEBUFFERTEXTURE2DEXTPROC glFramebufferTexture2D;
static PFNGLGENFRAMEBUFFERSEXTPROC glGenFramebuffers;
static PFNGLGENRENDERBUFFERSEXTPROC glGenRenderbuffers;
static PFNGLRENDERBUFFERSTORAGEEXTPROC glRenderbufferStorage;
typedef void (* PFNGLRENDERBUFFERSTORAGEMULTISAMPLEEXTPROC) (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height);
static PFNGLRENDERBUFFERSTORAGEMULTISAMPLEEXTPROC glRenderbufferStorageMultisample;
typedef void (* PFNGLBLITFRAMEBUFFEREXTPROC) (GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter);
static PFNGLBLITFRAMEBUFFEREXTPROC glBlitFramebuffer;
static void grabFramebufferObjectPointers() {
if (framebuffer_object_functions)
@ -75,6 +83,8 @@ static void grabFramebufferObjectPointers() {
// We're casting from an object pointer to a function pointer, the
// sizes need to be the same for this to work.
assert(sizeof(u.obj_ptr) == sizeof(u.func_ptr));
u.obj_ptr = SDL_GL_GetProcAddress("glBlitFramebuffer");
glBlitFramebuffer = (PFNGLBLITFRAMEBUFFEREXTPROC)u.func_ptr;
u.obj_ptr = SDL_GL_GetProcAddress("glBindFramebuffer");
glBindFramebuffer = (PFNGLBINDFRAMEBUFFEREXTPROC)u.func_ptr;
u.obj_ptr = SDL_GL_GetProcAddress("glBindRenderbuffer");
@ -95,8 +105,10 @@ static void grabFramebufferObjectPointers() {
glGenRenderbuffers = (PFNGLGENRENDERBUFFERSEXTPROC)u.func_ptr;
u.obj_ptr = SDL_GL_GetProcAddress("glRenderbufferStorage");
glRenderbufferStorage = (PFNGLRENDERBUFFERSTORAGEEXTPROC)u.func_ptr;
u.obj_ptr = SDL_GL_GetProcAddress("glRenderbufferStorageMultisample");
glRenderbufferStorageMultisample = (PFNGLRENDERBUFFERSTORAGEMULTISAMPLEEXTPROC)u.func_ptr;
}
#endif // defined(SDL_BACKEND) && !defined(USE_GLES2)
#endif // defined(SDL_BACKEND) && !defined(USE_GLEW) && !defined(USE_GLES2)
@ -172,6 +184,71 @@ void FrameBuffer::detach() {
glBindFramebuffer(GL_FRAMEBUFFER, 0);
}
#if !defined(USE_GLES2) && !defined(AMIGAOS)
MultiSampleFrameBuffer::MultiSampleFrameBuffer(uint width, uint height, int samples)
: FrameBuffer(width,height) {
if (!OpenGLContext.framebufferObjectMultisampleSupported) {
error("The current OpenGL context does not support multisample framebuffer objects!");
}
if (samples > OpenGLContext.multisampleMaxSamples) {
warning("Requested anti-aliasing with '%d' samples, but the current OpenGL context supports '%d' samples at most",
samples, OpenGLContext.multisampleMaxSamples);
}
_msSamples = MIN(samples, OpenGLContext.multisampleMaxSamples);
init();
}
MultiSampleFrameBuffer::~MultiSampleFrameBuffer() {
glDeleteRenderbuffers(1, &_msColorId);
glDeleteRenderbuffers(1, &_msDepthId);
glBindFramebuffer(GL_FRAMEBUFFER, 0);
glDeleteFramebuffers(1, &_msFrameBufferId);
}
void MultiSampleFrameBuffer::init() {
glGenFramebuffers(1, &_msFrameBufferId);
glBindFramebuffer(GL_FRAMEBUFFER, _msFrameBufferId);
glGenRenderbuffers(1, &_msColorId);
glBindRenderbuffer(GL_RENDERBUFFER, _msColorId);
glRenderbufferStorageMultisample(GL_RENDERBUFFER, _msSamples, GL_RGBA8, getTexWidth(), getTexHeight());
glGenRenderbuffers(1, &_msDepthId);
glBindRenderbuffer(GL_RENDERBUFFER, _msDepthId);
glRenderbufferStorageMultisample(GL_RENDERBUFFER, _msSamples, GL_DEPTH24_STENCIL8, getTexWidth(), getTexHeight());
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, _msColorId);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, _msDepthId);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, _msDepthId);
GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
if (status != GL_FRAMEBUFFER_COMPLETE)
error("Framebuffer is not complete! status: %d", status);
glBindFramebuffer(GL_FRAMEBUFFER, 0);
}
void MultiSampleFrameBuffer::attach() {
glBindFramebuffer(GL_READ_FRAMEBUFFER, getFrameBufferName());
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, _msFrameBufferId);
glViewport(0,0, getWidth(), getHeight());
glClearColor(0, 0, 0, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
}
void MultiSampleFrameBuffer::detach() {
glBindFramebuffer(GL_READ_FRAMEBUFFER, _msFrameBufferId);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, getFrameBufferName());
glBlitFramebuffer(0, 0, getWidth(), getHeight(), 0, 0, getWidth(), getHeight(), GL_COLOR_BUFFER_BIT, GL_NEAREST);
glBindFramebuffer(GL_FRAMEBUFFER, 0);
}
#endif // !defined(USE_GLES2) && !defined(AMIGAOS)
} // End of namespace OpenGL
#endif

View File

@ -40,16 +40,37 @@ public:
#else
virtual ~FrameBuffer();
void attach();
void detach();
virtual void attach();
virtual void detach();
#endif
protected:
GLuint getFrameBufferName() const { return _frameBuffer; }
private:
void init();
GLuint _renderBuffers[2];
GLuint _frameBuffer;
};
#if !defined(USE_GLES2) && !defined(AMIGAOS)
class MultiSampleFrameBuffer : public FrameBuffer {
public:
MultiSampleFrameBuffer(uint width, uint height, int samples);
virtual ~MultiSampleFrameBuffer();
virtual void attach();
virtual void detach();
private:
void init();
GLuint _msFrameBufferId;
GLuint _msColorId;
GLuint _msDepthId;
GLuint _msSamples;
};
#endif
} // End of namespace OpenGL
#endif

View File

@ -46,6 +46,11 @@
#define GL_UNPACK_ROW_LENGTH 0x0CF2
#endif
#if !defined(GL_MAX_SAMPLES)
// The Android SDK does not declare GL_MAX_SAMPLES
#define GL_MAX_SAMPLES 0x8D57
#endif
#elif defined(USE_GLEW)
#include <GL/glew.h>
#elif defined(SDL_BACKEND) && defined(USE_OPENGL)