Fixed render buffers not correctly resized on orientation changes

This commit is contained in:
Laurent Gomila 2013-08-24 17:27:23 +02:00 committed by Jonathan De Wachter
parent e5ee38fc26
commit d50f94ca97
6 changed files with 119 additions and 68 deletions

View File

@ -39,8 +39,8 @@ namespace Style
{
None = 0, ///< No border / title bar (this flag and all others are mutually exclusive)
Titlebar = 1 << 0, ///< Title bar + fixed border
Resize = 1 << 1, ///< Titlebar + resizable border + maximize button
Close = 1 << 2, ///< Titlebar + close button
Resize = 1 << 1, ///< Title bar + resizable border + maximize button
Close = 1 << 2, ///< Title bar + close button
Fullscreen = 1 << 3, ///< Fullscreen mode (this flag and all others are mutually exclusive)
Default = Titlebar | Resize | Close ///< Default window style

View File

@ -35,6 +35,7 @@
SFML_DECLARE_OBJC_CLASS(EAGLContext);
SFML_DECLARE_OBJC_CLASS(SFView);
namespace sf
{
@ -87,7 +88,18 @@ public:
///
////////////////////////////////////////////////////////////
~EaglContext();
////////////////////////////////////////////////////////////
/// \brief Recreate the render buffers of the context
///
/// This function must be called whenever the containing view
/// changes (typically after an orientation change)
///
/// \param glView : Container of the context
///
////////////////////////////////////////////////////////////
void recreateRenderBuffers(SFView* glView);
////////////////////////////////////////////////////////////
/// \brief Display what has been rendered to the context so far
///
@ -125,14 +137,12 @@ private:
///
/// \param shared Context to share the new one with (can be NULL)
/// \param window Window to attach the context to (can be NULL)
/// \param size Size of the context's drawable
/// \param bitsPerPixel Pixel depth, in bits per pixel
/// \param settings Creation parameters
///
////////////////////////////////////////////////////////////
void createContext(EaglContext* shared,
const WindowImplUIKit* window,
Vector2u size,
unsigned int bitsPerPixel,
const ContextSettings& settings);

View File

@ -62,7 +62,7 @@ m_depthbuffer(0)
{
const WindowImplUIKit* window = static_cast<const WindowImplUIKit*>(owner);
createContext(shared, window, window->getSize(), bitsPerPixel, settings);
createContext(shared, window, bitsPerPixel, settings);
}
@ -105,6 +105,57 @@ EaglContext::~EaglContext()
}
////////////////////////////////////////////////////////////
void EaglContext::recreateRenderBuffers(SFView* glView)
{
// Activate the context
EAGLContext* previousContext = [EAGLContext currentContext];
[EAGLContext setCurrentContext:m_context];
// Bind the frame buffer
glBindFramebufferOES(GL_FRAMEBUFFER_OES, m_framebuffer);
// Destroy previous render-buffers
if (m_colorbuffer)
glDeleteRenderbuffersOES(1, &m_colorbuffer);
if (m_depthbuffer)
glDeleteRenderbuffersOES(1, &m_depthbuffer);
// Create the color buffer
glGenRenderbuffersOES(1, &m_colorbuffer);
glBindRenderbufferOES(GL_RENDERBUFFER_OES, m_colorbuffer);
if (glView)
[m_context renderbufferStorage:GL_RENDERBUFFER_OES fromDrawable:glView.layer];
glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_COLOR_ATTACHMENT0_OES, GL_RENDERBUFFER_OES, m_colorbuffer);
// Create a depth buffer if requested
if (m_settings.depthBits > 0)
{
// Find the best internal format
GLenum format = m_settings.depthBits > 16 ? GL_DEPTH_COMPONENT24_OES : GL_DEPTH_COMPONENT16_OES;
// Get the size of the color-buffer (which fits the current size of the GL view)
GLint width, height;
glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES, GL_RENDERBUFFER_WIDTH_OES, &width);
glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES, GL_RENDERBUFFER_HEIGHT_OES, &height);
// Create the depth buffer
glGenRenderbuffersOES(1, &m_depthbuffer);
glBindRenderbufferOES(GL_RENDERBUFFER_OES, m_depthbuffer);
glRenderbufferStorageOES(GL_RENDERBUFFER_OES, format, width, height);
glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_DEPTH_ATTACHMENT_OES, GL_RENDERBUFFER_OES, m_depthbuffer);
}
// Make sure that everything's ok
GLenum status = glCheckFramebufferStatusOES(GL_FRAMEBUFFER_OES);
if (status != GL_FRAMEBUFFER_COMPLETE_OES)
err() << "Failed to create a valid frame buffer (error code: " << status << ")" << std::endl;
// Restore the previous context
[EAGLContext setCurrentContext:previousContext];
}
////////////////////////////////////////////////////////////
bool EaglContext::makeCurrent()
{
@ -125,17 +176,22 @@ void EaglContext::setVerticalSyncEnabled(bool enabled)
{
}
////////////////////////////////////////////////////////////
void EaglContext::createContext(EaglContext* shared,
const WindowImplUIKit* window,
Vector2u size,
unsigned int bitsPerPixel,
const ContextSettings& settings)
{
// Save the settings
m_settings = settings;
// Adjust the depth buffer format to those available
if (m_settings.depthBits > 16)
m_settings.depthBits = 24;
else if (m_settings.depthBits > 0)
m_settings.depthBits = 16;
// Create the context
if (shared)
m_context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES1 sharegroup:[shared->m_context sharegroup]];
@ -147,42 +203,12 @@ void EaglContext::createContext(EaglContext* shared,
// Create the framebuffer (this is the only allowed drawable on iOS)
glGenFramebuffersOES(1, &m_framebuffer);
glBindFramebufferOES(GL_FRAMEBUFFER_OES, m_framebuffer);
// Create the color buffer
glGenRenderbuffersOES(1, &m_colorbuffer);
glBindRenderbufferOES(GL_RENDERBUFFER_OES, m_colorbuffer);
if (window)
[m_context renderbufferStorage:GL_RENDERBUFFER_OES fromDrawable:window->getGlView().layer];
glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_COLOR_ATTACHMENT0_OES, GL_RENDERBUFFER_OES, m_colorbuffer);
// Create the render buffers
recreateRenderBuffers(window->getGlView());
// Create a depth buffer if requested
if (settings.depthBits > 0)
{
// Find the best internal format
GLenum format;
if (settings.depthBits > 16)
{
format = GL_DEPTH_COMPONENT24_OES;
m_settings.depthBits = 24;
}
else
{
format = GL_DEPTH_COMPONENT16_OES;
m_settings.depthBits = 16;
}
// Create the depth buffer
glGenRenderbuffersOES(1, &m_depthbuffer);
glBindRenderbufferOES(GL_RENDERBUFFER_OES, m_depthbuffer);
glRenderbufferStorageOES(GL_RENDERBUFFER_OES, GL_DEPTH_COMPONENT16_OES, size.x, size.y);
glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_DEPTH_ATTACHMENT_OES, GL_RENDERBUFFER_OES, m_depthbuffer);
}
// Make sure that everything's ok
GLenum status = glCheckFramebufferStatusOES(GL_FRAMEBUFFER_OES);
if (status != GL_FRAMEBUFFER_COMPLETE_OES)
err() << "Failed to create a valid frame buffer (error code: " << status << ")" << std::endl;
// Attach the context to the GL view for future updates
window->getGlView().context = this;
}
} // namespace priv

View File

@ -28,6 +28,7 @@
////////////////////////////////////////////////////////////
// Headers
////////////////////////////////////////////////////////////
#include <SFML/Window/iOS/EaglContext.hpp>
#include <UIKit/UIKit.h>
@ -38,6 +39,21 @@
////////////////////////////////////////////////////////////
@interface SFView : UIView<UIKeyInput>
////////////////////////////////////////////////////////////
/// \brief Construct the view with its initial size
///
/// \param frame Dimensions of the view
///
/// \return Id of the view
///
////////////////////////////////////////////////////////////
-(id)initWithFrame:(CGRect)frame;
////////////////////////////////////////////////////////////
// Member data
////////////////////////////////////////////////////////////
@property (nonatomic) sf::priv::EaglContext* context; ///< The attached EAGL context
@end
#endif // SFML_SFVIEW_HPP

View File

@ -34,6 +34,8 @@
@implementation SFView
@synthesize context;
////////////////////////////////////////////////////////////
-(BOOL)canBecomeFirstResponder
@ -111,6 +113,15 @@
}
////////////////////////////////////////////////////////////
- (void)layoutSubviews
{
// update the attached context's buffers
if (self.context)
self.context->recreateRenderBuffers(self);
}
////////////////////////////////////////////////////////////
+(Class)layerClass
{
@ -124,33 +135,22 @@
self = [super initWithFrame:frame];
if (self)
{
if (![self initialize])
{
[self release];
self = nil;
}
self.context = NULL;
// Configure the EAGL layer
CAEAGLLayer* eaglLayer = (CAEAGLLayer*)self.layer;
eaglLayer.opaque = YES;
eaglLayer.drawableProperties = [NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithBool:FALSE], kEAGLDrawablePropertyRetainedBacking,
kEAGLColorFormatRGBA8, kEAGLDrawablePropertyColorFormat,
nil];
// Enable user interactions on the view (touch events)
self.userInteractionEnabled = true;
}
return self;
}
////////////////////////////////////////////////////////////
-(bool)initialize
{
// Configure the EAGL layer
CAEAGLLayer* eaglLayer = (CAEAGLLayer*)self.layer;
eaglLayer.opaque = YES;
eaglLayer.drawableProperties = [NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithBool:FALSE], kEAGLDrawablePropertyRetainedBacking,
kEAGLColorFormatRGBA8, kEAGLDrawablePropertyColorFormat,
nil];
// Enable user interactions on the view (touch events)
self.userInteractionEnabled = true;
return true;
}
@end

View File

@ -68,7 +68,6 @@ WindowImplUIKit::WindowImplUIKit(VideoMode mode,
// Create the view
m_view = [[SFView alloc] initWithFrame:frame];
[m_window addSubview:m_view];
[m_view resignFirstResponder];
// Create the view controller
@ -91,7 +90,7 @@ WindowImplUIKit::~WindowImplUIKit()
////////////////////////////////////////////////////////////
void WindowImplUIKit::processEvents()
{
while (CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0.0001, TRUE) == kCFRunLoopRunHandledSource)
while (CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0.0001, true) == kCFRunLoopRunHandledSource)
;
}