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) None = 0, ///< No border / title bar (this flag and all others are mutually exclusive)
Titlebar = 1 << 0, ///< Title bar + fixed border Titlebar = 1 << 0, ///< Title bar + fixed border
Resize = 1 << 1, ///< Titlebar + resizable border + maximize button Resize = 1 << 1, ///< Title bar + resizable border + maximize button
Close = 1 << 2, ///< Titlebar + close button Close = 1 << 2, ///< Title bar + close button
Fullscreen = 1 << 3, ///< Fullscreen mode (this flag and all others are mutually exclusive) Fullscreen = 1 << 3, ///< Fullscreen mode (this flag and all others are mutually exclusive)
Default = Titlebar | Resize | Close ///< Default window style Default = Titlebar | Resize | Close ///< Default window style

View File

@ -35,6 +35,7 @@
SFML_DECLARE_OBJC_CLASS(EAGLContext); SFML_DECLARE_OBJC_CLASS(EAGLContext);
SFML_DECLARE_OBJC_CLASS(SFView);
namespace sf namespace sf
{ {
@ -87,7 +88,18 @@ public:
/// ///
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
~EaglContext(); ~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 /// \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 shared Context to share the new one with (can be NULL)
/// \param window Window to attach the context to (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 bitsPerPixel Pixel depth, in bits per pixel
/// \param settings Creation parameters /// \param settings Creation parameters
/// ///
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
void createContext(EaglContext* shared, void createContext(EaglContext* shared,
const WindowImplUIKit* window, const WindowImplUIKit* window,
Vector2u size,
unsigned int bitsPerPixel, unsigned int bitsPerPixel,
const ContextSettings& settings); const ContextSettings& settings);

View File

@ -62,7 +62,7 @@ m_depthbuffer(0)
{ {
const WindowImplUIKit* window = static_cast<const WindowImplUIKit*>(owner); 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() bool EaglContext::makeCurrent()
{ {
@ -125,17 +176,22 @@ void EaglContext::setVerticalSyncEnabled(bool enabled)
{ {
} }
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
void EaglContext::createContext(EaglContext* shared, void EaglContext::createContext(EaglContext* shared,
const WindowImplUIKit* window, const WindowImplUIKit* window,
Vector2u size,
unsigned int bitsPerPixel, unsigned int bitsPerPixel,
const ContextSettings& settings) const ContextSettings& settings)
{ {
// Save the settings // Save the settings
m_settings = 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 // Create the context
if (shared) if (shared)
m_context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES1 sharegroup:[shared->m_context sharegroup]]; 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) // Create the framebuffer (this is the only allowed drawable on iOS)
glGenFramebuffersOES(1, &m_framebuffer); glGenFramebuffersOES(1, &m_framebuffer);
glBindFramebufferOES(GL_FRAMEBUFFER_OES, m_framebuffer);
// Create the color buffer // Create the render buffers
glGenRenderbuffersOES(1, &m_colorbuffer); recreateRenderBuffers(window->getGlView());
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 a depth buffer if requested // Attach the context to the GL view for future updates
if (settings.depthBits > 0) window->getGlView().context = this;
{
// 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;
} }
} // namespace priv } // namespace priv

View File

@ -28,6 +28,7 @@
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
// Headers // Headers
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
#include <SFML/Window/iOS/EaglContext.hpp>
#include <UIKit/UIKit.h> #include <UIKit/UIKit.h>
@ -38,6 +39,21 @@
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
@interface SFView : UIView<UIKeyInput> @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 @end
#endif // SFML_SFVIEW_HPP #endif // SFML_SFVIEW_HPP

View File

@ -34,6 +34,8 @@
@implementation SFView @implementation SFView
@synthesize context;
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
-(BOOL)canBecomeFirstResponder -(BOOL)canBecomeFirstResponder
@ -111,6 +113,15 @@
} }
////////////////////////////////////////////////////////////
- (void)layoutSubviews
{
// update the attached context's buffers
if (self.context)
self.context->recreateRenderBuffers(self);
}
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
+(Class)layerClass +(Class)layerClass
{ {
@ -124,33 +135,22 @@
self = [super initWithFrame:frame]; self = [super initWithFrame:frame];
if (self) if (self)
{ {
if (![self initialize]) self.context = NULL;
{
[self release]; // Configure the EAGL layer
self = nil; 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; 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 @end

View File

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