mirror of
https://github.com/libretro/scummvm.git
synced 2025-02-19 10:41:55 +00:00
Merge pull request #1250 from bgK/wip-multisampling
Multisampling for framebuffers
This commit is contained in:
commit
fe4aac9ada
@ -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) {
|
||||
|
@ -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
|
||||
|
@ -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.
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
Loading…
x
Reference in New Issue
Block a user