\r
#else\r
\r
+// Note that the expression is still evaluated, since we declared this as an inlined function, rather than a macro.\r
slInline void Assert(bool expression) {}\r
slInline void AssertMsg(bool expression, char* msg, ...) {}\r
\r
\r
#define IS_POWER_OF_TWO(x) ( ((x) & -(x)) == (x) )\r
\r
-#pragma warning(disable:4146) // =(\r
+//#pragma warning(disable:4146) // =(\r
#define ALIGN_UP(x, ALIGNMENT) ( ((x) + (ALIGNMENT) - 1) & -(ALIGNMENT) )\r
#define ALIGN_DOWN(x, ALIGNMENT) ( (x) & -(ALIGNMENT) )\r
\r
* This is a wrapper class around all OpenGL API calls in iOS. This completely abstracts
* away all mixes between the OS-specific calls in Objective-C and the C-style inteface of
* OpenGL.
+ *
+ * Since iPhone/iPad will be single/dual cores for the near-term future, we'll basically
+ * only allow a single rendering context to exist at any given point in time. Therefore,
+ * we should never need to set context other than during startup or shutdown.
*****************************************************************************************/
-#include "Foundation/Common/GlobalInclude.h"
-
#include <OpenGLES/ES1/gl.h>
#include <OpenGLES/ES1/glext.h>
#include <OpenGLES/ES2/gl.h>
#include <OpenGLES/ES2/glext.h>
+#include "Foundation/Common/GlobalInclude.h"
+
//----------------------------------------------------------------------------------------
// Some forward declarations
@class EAGLContext;
class OpenGLServices
{
public:
- bool init();
+ enum
+ {
+ kMaxTextureSize = 512 * 512 * 4,
+ };
+
+ OpenGLServices();
+
+ bool init( EAGLContext* mainContext );
+ void destroy();
+
+ bool initScratchMem();
+ void destroyScratchMem();
bool setRenderTarget( RenderTarget& renderTarget );
+ bool present( RenderTarget& renderTarget );
+
+ TextureHandle loadPNGTexture( const char* fileName );
+ void destroyTexture( TextureHandle texture );
private:
- EAGLContext* mGLContext;
+ EAGLContext* mGLContext;
+ void* mScratchMem;
+
+ void setContext( EAGLContext* newContext );
};
+#import <QuartzCore/QuartzCore.h>
+#import <CoreGraphics/CoreGraphics.h>
+
#include "OpenGLServices.h"
#include "RenderTarget.h"
-#import <QuartzCore/QuartzCore.h>
+//----------------------------------------------------------------------------------------
+OpenGLServices::OpenGLServices() : mGLContext(NULL), mScratchMem(NULL)
+{
+}
+
+//----------------------------------------------------------------------------------------
+bool OpenGLServices::init( EAGLContext* mainContext )
+{
+ if ( mGLContext )
+ {
+ return false;
+ }
+
+ mGLContext = [mainContext retain];
+ Assert( [EAGLContext setCurrentContext:mGLContext] );
+
+ initScratchMem();
+
+ // Enable some common states.
+ glEnable( GL_TEXTURE_2D );
+
+ glEnable( GL_BLEND );
+
+ // We will premultiply alpha into the color channels of all textures (so no alpha animation).
+ // This is basically the A over B alpha scheme.
+ glBlendFunc( GL_ONE, GL_ONE_MINUS_SRC_ALPHA );
+
+ glEnable( GL_DEPTH_TEST );
+
+ return true;
+}
+
+//----------------------------------------------------------------------------------------
+void OpenGLServices::destroy()
+{
+ if ( !mGLContext )
+ {
+ return;
+ }
+
+ destroyScratchMem();
+ [mGLContext release];
+ [EAGLContext setCurrentContext:nil];
+}
+
+//----------------------------------------------------------------------------------------
+bool OpenGLServices::initScratchMem()
+{
+ if (!mScratchMem)
+ {
+ mScratchMem = malloc( kMaxTextureSize );
+ return mScratchMem != NULL;
+ }
+ return true;
+}
+
+//----------------------------------------------------------------------------------------
+void OpenGLServices::destroyScratchMem()
+{
+ if (mScratchMem)
+ {
+ free( mScratchMem );
+ mScratchMem = NULL;
+ }
+}
//----------------------------------------------------------------------------------------
bool OpenGLServices::setRenderTarget( RenderTarget& renderTarget )
{
-#if defined(DEBUG)
if (!renderTarget.getFramebuffer() || !glIsFramebuffer( renderTarget.getFramebuffer() ))
{
return false;
}
-#endif
glBindFramebuffer( GL_FRAMEBUFFER, renderTarget.getFramebuffer() );
return true;
}
+
+//----------------------------------------------------------------------------------------
+bool OpenGLServices::present( RenderTarget& renderTarget )
+{
+ GLuint colorBuffer = renderTarget.getColorBuffer();
+ if (!colorBuffer || !glIsRenderbuffer( colorBuffer ))
+ {
+ return false;
+ }
+
+ glBindRenderbuffer( GL_RENDERBUFFER, colorBuffer );
+ return [renderTarget.getContext() presentRenderbuffer:GL_RENDERBUFFER];
+}
+
+//----------------------------------------------------------------------------------------
+TextureHandle OpenGLServices::loadPNGTexture( const char* fileName )
+{
+ GLuint textureHandle;
+ glGenTextures( 1, &textureHandle );
+ if (!textureHandle)
+ {
+ return textureHandle;
+ }
+
+ glBindTexture( GL_TEXTURE_2D, textureHandle );
+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR );
+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE );
+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE );
+
+ // http://iphonedevelopment.blogspot.com/2009/05/opengl-es-from-ground-up-part-6_25.html
+ NSString* nsFileName = [NSString stringWithUTF8String:fileName];
+ NSString* nsPath = [[NSBundle mainBundle] pathForResource:nsFileName ofType:@"png"];
+ NSData* fileData = [[NSData alloc] initWithContentsOfFile:nsPath];
+ UIImage* image = [[UIImage alloc] initWithData:fileData];
+ AssertMessage( image != nil, "Image failed to load!\n" );
+
+ GLuint width = CGImageGetWidth( image.CGImage );
+ GLuint height = CGImageGetHeight( image.CGImage );
+ CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
+ Assert( width * height * 4 <= kMaxTextureSize );
+ CGContextRef context = CGBitmapContextCreate( mScratchMem, width, height, 8, 4 * width, colorSpace, kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big );
+ CGColorSpaceRelease( colorSpace );
+ CGContextClearRect( context, CGRectMake( 0, 0, width, height ) );
+ CGContextTranslateCTM( context, 0, 0 );
+ CGContextDrawImage( context, CGRectMake( 0, 0, width, height ), image.CGImage );
+
+ glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, mScratchMem );
+ glGenerateMipmap( GL_TEXTURE_2D );
+
+ CGContextRelease(context);
+ [image release];
+ [fileData release];
+
+ return textureHandle;
+}
+
+//----------------------------------------------------------------------------------------
+void OpenGLServices::destroyTexture( TextureHandle texture )
+{
+ glDeleteTextures( 1, &texture );
+}
+
+//----------------------------------------------------------------------------------------
+void OpenGLServices::setContext( EAGLContext* newContext )
+{
+ if (mGLContext != newContext)
+ {
+ mGLContext = newContext;
+ [EAGLContext setCurrentContext:newContext];
+ }
+}
#pragma once
-#include "Foundation/Common/GlobalInclude.h"
-
#include <OpenGLES/ES1/gl.h>
#include <OpenGLES/ES1/glext.h>
#include <OpenGLES/ES2/gl.h>
#include <OpenGLES/ES2/glext.h>
+#include "Foundation/Common/GlobalInclude.h"
+
@class EAGLContext;
@class CAEAGLLayer;
bool init( RenderTargetInitParams& params );
void destroy();
- uint32_t getWidth() { return mRenderBufferWidth; }
- uint32_t getHeight() { return mRenderBufferHeight; }
- GLuint getFramebuffer() { return mFramebuffer; }
+ EAGLContext* getContext() const { return mContext; }
+ uint32_t getWidth() const { return mRenderBufferWidth; }
+ uint32_t getHeight() const { return mRenderBufferHeight; }
+ GLuint getFramebuffer() const { return mFramebuffer; }
+ GLuint getColorBuffer() const { return mColorBuffer; }
protected:
EAGLContext* mContext;
-//
-// EAGLView.h
-// Littlest
-//
-// Created by Doris Chen on 12/4/10.
-// Copyright 2010 __MyCompanyName__. All rights reserved.
-//
+#pragma once
#import <UIKit/UIKit.h>
@interface EAGLView : UIView
{
@private
- EAGLContext *context;
+ EAGLContext* context;
// The pixel dimensions of the CAEAGLLayer.
GLint framebufferWidth;
GLuint defaultFramebuffer, colorRenderbuffer;
}
-@property (nonatomic, retain) EAGLContext *context;
+@property (nonatomic, retain) EAGLContext* context;
- (void)setFramebuffer;
- (BOOL)presentFramebuffer;
-//
-// EAGLView.m
-// Littlest
-//
-// Created by Doris Chen on 12/4/10.
-// Copyright 2010 __MyCompanyName__. All rights reserved.
-//
-
#import <QuartzCore/QuartzCore.h>
#import "EAGLView.h"
// You must implement this method
+ (Class)layerClass
{
- return [CAEAGLLayer class];
+ return [CAEAGLLayer class];
}
//-----------------------------------------------------------------------------------------------------------
//The EAGL view is stored in the nib file. When it's unarchived it's sent -initWithCoder:.
- (id)initWithCoder:(NSCoder*)coder
{
- self = [super initWithCoder:coder];
+ self = [super initWithCoder:coder];
if (self)
- {
- CAEAGLLayer *eaglLayer = (CAEAGLLayer *)self.layer;
-
- eaglLayer.opaque = TRUE;
- eaglLayer.drawableProperties = [NSDictionary dictionaryWithObjectsAndKeys:
- [NSNumber numberWithBool:FALSE], kEAGLDrawablePropertyRetainedBacking,
- kEAGLColorFormatRGBA8, kEAGLDrawablePropertyColorFormat,
- nil];
- }
-
- return self;
+ {
+ CAEAGLLayer *eaglLayer = (CAEAGLLayer *)self.layer;
+
+ eaglLayer.opaque = TRUE;
+ eaglLayer.drawableProperties = [NSDictionary dictionaryWithObjectsAndKeys:
+ [NSNumber numberWithBool:FALSE], kEAGLDrawablePropertyRetainedBacking,
+ kEAGLColorFormatRGBA8, kEAGLDrawablePropertyColorFormat,
+ nil];
+ }
+
+ return self;
}
//-----------------------------------------------------------------------------------------------------------
- (void)dealloc
{
- [self deleteFramebuffer];
- [context release];
-
- [super dealloc];
+ [self deleteFramebuffer];
+ [context release];
+
+ [super dealloc];
}
//-----------------------------------------------------------------------------------------------------------
- (EAGLContext *)context
{
- return context;
+ return context;
}
//-----------------------------------------------------------------------------------------------------------
- (void)setContext:(EAGLContext *)newContext
{
- if (context != newContext)
- {
- [self deleteFramebuffer];
- [context release];
-
- context = [newContext retain];
- }
+ if (context != newContext)
+ {
+ [self deleteFramebuffer];
+ [context release];
+
+ context = [newContext retain];
+ [EAGLContext setCurrentContext:nil];
+ }
}
//-----------------------------------------------------------------------------------------------------------
- (void)createFrameBuffer
{
- if (context && !defaultFramebuffer)
- {
- [EAGLContext setCurrentContext:context];
-
- // Create default framebuffer object.
- glGenFramebuffers(1, &defaultFramebuffer);
- glBindFramebuffer(GL_FRAMEBUFFER, defaultFramebuffer);
-
- // Create color render buffer and allocate backing store.
- glGenRenderbuffers(1, &colorRenderbuffer);
- glBindRenderbuffer(GL_RENDERBUFFER, colorRenderbuffer);
- [context renderbufferStorage:GL_RENDERBUFFER fromDrawable:(CAEAGLLayer *)self.layer];
- glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_WIDTH, &framebufferWidth);
- glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_HEIGHT, &framebufferHeight);
-
- glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, colorRenderbuffer);
-
- if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
- NSLog(@"Failed to make complete framebuffer object %x", glCheckFramebufferStatus(GL_FRAMEBUFFER));
- }
+ if (context && !defaultFramebuffer)
+ {
+ [EAGLContext setCurrentContext:context];
+
+ // Create default framebuffer object.
+ glGenFramebuffers(1, &defaultFramebuffer);
+ glBindFramebuffer(GL_FRAMEBUFFER, defaultFramebuffer);
+
+ // Create color render buffer and allocate backing store.
+ glGenRenderbuffers(1, &colorRenderbuffer);
+ glBindRenderbuffer(GL_RENDERBUFFER, colorRenderbuffer);
+ [context renderbufferStorage:GL_RENDERBUFFER fromDrawable:(CAEAGLLayer *)self.layer];
+ glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_WIDTH, &framebufferWidth);
+ glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_HEIGHT, &framebufferHeight);
+
+ glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, colorRenderbuffer);
+
+ if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
+ NSLog(@"Failed to make complete framebuffer object %x", glCheckFramebufferStatus(GL_FRAMEBUFFER));
+ }
}
//-----------------------------------------------------------------------------------------------------------
- (void)deleteFramebuffer
{
- if (context)
+ if (context)
+ {
+ [EAGLContext setCurrentContext:context];
+
+ if (defaultFramebuffer)
{
- [EAGLContext setCurrentContext:context];
-
- if (defaultFramebuffer)
- {
- glDeleteFramebuffers(1, &defaultFramebuffer);
- defaultFramebuffer = 0;
- }
-
- if (colorRenderbuffer)
- {
- glDeleteRenderbuffers(1, &colorRenderbuffer);
- colorRenderbuffer = 0;
- }
+ glDeleteFramebuffers(1, &defaultFramebuffer);
+ defaultFramebuffer = 0;
}
+
+ if (colorRenderbuffer)
+ {
+ glDeleteRenderbuffers(1, &colorRenderbuffer);
+ colorRenderbuffer = 0;
+ }
+ }
}
//-----------------------------------------------------------------------------------------------------------
- (void)setFramebuffer
{
- if (context)
- {
- [EAGLContext setCurrentContext:context];
-
- if (!defaultFramebuffer)
- [self createFrameBuffer];
-
- glBindFramebuffer(GL_FRAMEBUFFER, defaultFramebuffer);
-
- glViewport(0, 0, framebufferWidth, framebufferHeight);
- }
+ if (context)
+ {
+ [EAGLContext setCurrentContext:context];
+
+ if (!defaultFramebuffer)
+ [self createFrameBuffer];
+
+ glBindFramebuffer(GL_FRAMEBUFFER, defaultFramebuffer);
+
+ glViewport(0, 0, framebufferWidth, framebufferHeight);
+ }
}
//-----------------------------------------------------------------------------------------------------------
- (BOOL)presentFramebuffer
{
- BOOL success = FALSE;
+ BOOL success = FALSE;
+
+ if (context)
+ {
+ [EAGLContext setCurrentContext:context];
- if (context)
- {
- [EAGLContext setCurrentContext:context];
-
- glBindRenderbuffer(GL_RENDERBUFFER, colorRenderbuffer);
-
- success = [context presentRenderbuffer:GL_RENDERBUFFER];
- }
+ glBindRenderbuffer(GL_RENDERBUFFER, colorRenderbuffer);
- return success;
+ success = [context presentRenderbuffer:GL_RENDERBUFFER];
+ }
+
+ return success;
}
//-----------------------------------------------------------------------------------------------------------
- (void)layoutSubviews
{
- // The framebuffer will be re-created at the beginning of the next setFramebuffer method call.
- [self deleteFramebuffer];
+ // The framebuffer will be re-created at the beginning of the next setFramebuffer method call.
+ [self deleteFramebuffer];
}
@end
-//
-// LittlestAppDelegate.h
-// Littlest
-//
-// Created by Doris Chen on 12/4/10.
-// Copyright 2010 __MyCompanyName__. All rights reserved.
-//
+#pragma once
#import <UIKit/UIKit.h>
@class LittlestViewController;
-@interface LittlestAppDelegate : NSObject <UIApplicationDelegate> {
- UIWindow *window;
- LittlestViewController *viewController;
+@interface LittlestAppDelegate : NSObject <UIApplicationDelegate>
+{
+ UIWindow* window;
+ LittlestViewController* viewController;
}
-@property (nonatomic, retain) IBOutlet UIWindow *window;
-@property (nonatomic, retain) IBOutlet LittlestViewController *viewController;
+@property (nonatomic, retain) IBOutlet UIWindow* window;
+@property (nonatomic, retain) IBOutlet LittlestViewController* viewController;
@end
-//
-// LittlestAppDelegate.m
-// Littlest
-//
-// Created by Doris Chen on 12/4/10.
-// Copyright 2010 __MyCompanyName__. All rights reserved.
-//
-
#import "LittlestAppDelegate.h"
#import "LittlestViewController.h"
-//
-// LittlestViewController.h
-// Littlest
-//
-// Created by Doris Chen on 12/4/10.
-// Copyright 2010 __MyCompanyName__. All rights reserved.
-//
+#pragma once
#import <UIKit/UIKit.h>
-//
-// LittlestViewController.m
-// Littlest
-//
-// Created by Doris Chen on 12/4/10.
-// Copyright 2010 __MyCompanyName__. All rights reserved.
-//
-
#import <QuartzCore/QuartzCore.h>
#import "LittlestViewController.h"
4B90648612B426FE00655D84 /* Standard.fsh in Resources */ = {isa = PBXBuildFile; fileRef = 4B90648512B426FE00655D84 /* Standard.fsh */; };
4BA0CDCE12BD655200EBB6F0 /* OpenGLServices.mm in Sources */ = {isa = PBXBuildFile; fileRef = 4BA0CDCD12BD655200EBB6F0 /* OpenGLServices.mm */; };
4BA0CDF112BD6FE100EBB6F0 /* RenderTarget.mm in Sources */ = {isa = PBXBuildFile; fileRef = 4BA0CDF012BD6FE100EBB6F0 /* RenderTarget.mm */; };
+ 4BA0CF4C12BEA74F00EBB6F0 /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4BA0CF4B12BEA74F00EBB6F0 /* CoreGraphics.framework */; };
/* End PBXBuildFile section */
/* Begin PBXFileReference section */
4BA0CDCD12BD655200EBB6F0 /* OpenGLServices.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = OpenGLServices.mm; sourceTree = "<group>"; };
4BA0CDEF12BD6EB200EBB6F0 /* RenderTarget.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RenderTarget.h; sourceTree = "<group>"; };
4BA0CDF012BD6FE100EBB6F0 /* RenderTarget.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = RenderTarget.mm; sourceTree = "<group>"; };
+ 4BA0CF4B12BEA74F00EBB6F0 /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; };
8D1107310486CEB800E47090 /* Littlest-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "Littlest-Info.plist"; plistStructureDefinitionIdentifier = "com.apple.xcode.plist.structure-definition.iphone.info-plist"; sourceTree = "<group>"; };
/* End PBXFileReference section */
1DF5F4E00D08C38300B7A737 /* UIKit.framework in Frameworks */,
28FD15000DC6FC520079059D /* OpenGLES.framework in Frameworks */,
28FD15080DC6FC5B0079059D /* QuartzCore.framework in Frameworks */,
+ 4BA0CF4C12BEA74F00EBB6F0 /* CoreGraphics.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
29B97323FDCFA39411CA2CEA /* Frameworks */ = {
isa = PBXGroup;
children = (
+ 4BA0CF4B12BEA74F00EBB6F0 /* CoreGraphics.framework */,
28FD15070DC6FC5B0079059D /* QuartzCore.framework */,
28FD14FF0DC6FC520079059D /* OpenGLES.framework */,
1DF5F4DF0D08C38300B7A737 /* UIKit.framework */,