Skip to content

Commit fd20cd4

Browse files
committed
Extracting framebuffer objects into their own class. CCRenderers are bound to a single FBO. Implementation for effects and render textures not finished.
1 parent a0852a5 commit fd20cd4

File tree

9 files changed

+210
-208
lines changed

9 files changed

+210
-208
lines changed

cocos2d-ios.xcodeproj/project.pbxproj

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1906,15 +1906,15 @@
19061906
D34CAD6519C3A7A5009BED7A /* CCRendererBasicTypes.h */,
19071907
D34CAD6A19C3AA10009BED7A /* CCRendererBasicTypes_Private.h */,
19081908
D34CAD6819C3A7B3009BED7A /* CCRendererBasicTypes.m */,
1909-
D38058181889AD6000822437 /* CCRenderer.h */,
1910-
D309054F18AC23110081BF11 /* CCRenderer_Private.h */,
1911-
D38058191889AD6000822437 /* CCRenderer.m */,
1912-
D36DFA2719996EC500DEC135 /* CCRendererGLSupport.m */,
19131909
E0BC7D9B1342CE7B001B4DCC /* CCShader.h */,
19141910
D39FA9C718C1BC6B00441627 /* CCShader_Private.h */,
19151911
E0BC7D9C1342CE7B001B4DCC /* CCShader.m */,
19161912
D34CAD5F19C3A0B5009BED7A /* NSValue+CCRenderer.h */,
19171913
D34CAD6219C3A0FD009BED7A /* NSValue+CCRenderer.m */,
1914+
D38058181889AD6000822437 /* CCRenderer.h */,
1915+
D309054F18AC23110081BF11 /* CCRenderer_Private.h */,
1916+
D38058191889AD6000822437 /* CCRenderer.m */,
1917+
D36DFA2719996EC500DEC135 /* CCRendererGLSupport.m */,
19181918
);
19191919
name = Rendering;
19201920
sourceTree = "<group>";

cocos2d/CCDirector.m

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,9 @@ -(void) calculateDeltaTime;
9696
-(void) calculateMPF;
9797
@end
9898

99-
@implementation CCDirector
99+
@implementation CCDirector {
100+
CCFrameBufferObject *_framebuffer;
101+
}
100102

101103
@synthesize animationInterval = _animationInterval;
102104
@synthesize runningScene = _runningScene;
@@ -200,6 +202,8 @@ - (id) init
200202

201203
_rendererPool = [NSMutableArray array];
202204
_globalShaderUniforms = [NSMutableDictionary dictionary];
205+
206+
_framebuffer = [[CCFrameBufferObject alloc] init];
203207
}
204208

205209
return self;
@@ -237,8 +241,11 @@ - (void) drawScene
237241
if(CCRenderDispatchBeginFrame()){
238242
GLKMatrix4 projection = self.projectionMatrix;
239243

244+
// Synchronize the framebuffer with the view.
245+
[_framebuffer syncWithView:self.view];
246+
240247
CCRenderer *renderer = [self rendererFromPool];
241-
[renderer prepareWithProjection:&projection viewSize:self.viewSize contentScale:self.contentScaleFactor];
248+
[renderer prepareWithProjection:&projection framebuffer:_framebuffer];
242249
[CCRenderer bindRenderer:renderer];
243250

244251
[renderer enqueueClear:(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT) color:_runningScene.colorRGBA.glkVector4 depth:1.0f stencil:0 globalSortOrder:NSIntegerMin];

cocos2d/CCRenderTexture.m

Lines changed: 13 additions & 183 deletions
Original file line numberDiff line numberDiff line change
@@ -83,31 +83,6 @@ - (CGAffineTransform)nodeToWorldTransform
8383
@end
8484

8585

86-
@interface CCRenderTextureFBO : NSObject
87-
88-
@property (nonatomic, readonly) GLuint FBO;
89-
@property (nonatomic, readonly) GLuint depthRenderBuffer;
90-
@property (nonatomic, readonly) GLuint stencilRenderBuffer;
91-
92-
@end
93-
94-
95-
@implementation CCRenderTextureFBO
96-
97-
- (id)initWithFBO:(GLuint)fbo depthRenderBuffer:(GLuint)depthBuffer stencilRenderBuffer:(GLuint)stencilRenderBuffer
98-
{
99-
if((self = [super init]))
100-
{
101-
_FBO = fbo;
102-
_depthRenderBuffer = depthBuffer;
103-
_stencilRenderBuffer = stencilRenderBuffer;
104-
}
105-
return self;
106-
}
107-
108-
@end
109-
110-
11186
@implementation CCRenderTexture
11287

11388
+(id)renderTextureWithWidth:(int)w height:(int)h pixelFormat:(CCTexturePixelFormat) format depthStencilFormat:(GLuint)depthStencilFormat
@@ -139,7 +114,6 @@ - (id)initWithWidth:(int)w height:(int)h pixelFormat:(CCTexturePixelFormat)forma
139114
-(id)initWithWidth:(int)width height:(int)height pixelFormat:(CCTexturePixelFormat) format depthStencilFormat:(GLuint)depthStencilFormat
140115
{
141116
if((self = [super init])){
142-
143117
NSAssert(format != CCTexturePixelFormat_A8, @"only RGB and RGBA formats are valid for a render texture");
144118

145119
CCDirector *director = [CCDirector sharedDirector];
@@ -149,20 +123,21 @@ -(id)initWithWidth:(int)width height:(int)height pixelFormat:(CCTexturePixelForm
149123
CCLOGWARN(@"cocos2d: WARNING. CCRenderTexture is running on its own thread. Make sure that an OpenGL context is being used on this thread!");
150124

151125
_contentScale = [CCDirector sharedDirector].contentScaleFactor;
152-
[self setContentSize:CGSizeMake(width, height)];
126+
[self setContentSize:CGSizeMake(width, height)];
153127
_pixelFormat = format;
154128
_depthStencilFormat = depthStencilFormat;
155129

156130
// Flip the projection matrix on the y-axis since Cocos2D uses upside down textures.
157131
_projection = GLKMatrix4MakeOrtho(0.0f, width, 0.0f, height, -1024.0f, 1024.0f);
158132

159-
CCRenderTextureSprite *rtSprite = [CCRenderTextureSprite spriteWithTexture:[CCTexture none]];
160-
rtSprite.renderTexture = self;
161-
_sprite = rtSprite;
133+
CCRenderTextureSprite *rtSprite = [CCRenderTextureSprite spriteWithTexture:[CCTexture none]];
134+
rtSprite.renderTexture = self;
135+
_sprite = rtSprite;
162136

163137
// Diabled by default.
164138
_autoDraw = NO;
165139
}
140+
166141
return self;
167142
}
168143

@@ -182,8 +157,6 @@ -(void)createTextureAndFboWithPixelSize:(CGSize)pixelSize
182157
{
183158
CCGL_DEBUG_PUSH_GROUP_MARKER("CCRenderTexture: Create");
184159

185-
glGetIntegerv(GL_FRAMEBUFFER_BINDING, &_oldFBO);
186-
187160
// textures must be power of two
188161
NSUInteger powW;
189162
NSUInteger powH;
@@ -197,120 +170,21 @@ -(void)createTextureAndFboWithPixelSize:(CGSize)pixelSize
197170
}
198171

199172
void *data = calloc(powW*powH, 4);
200-
201173
CCTexture *texture = [[CCTexture alloc] initWithData:data pixelFormat:_pixelFormat pixelsWide:powW pixelsHigh:powH contentSizeInPixels:pixelSize contentScale:_contentScale];
202174
self.texture = texture;
203175
free(data);
204176

205177
// Render textures are nearest filtered for legacy reasons.
206178
self.texture.antialiased = NO;
207179

208-
CCRenderDispatch(NO, ^{
209-
CCGL_DEBUG_PUSH_GROUP_MARKER("CCRenderTexture: Create");
210-
211-
glGetIntegerv(GL_FRAMEBUFFER_BINDING, &_oldFBO);
212-
213-
GLint oldRBO;
214-
glGetIntegerv(GL_RENDERBUFFER_BINDING, &oldRBO);
215-
216-
// generate FBO
217-
GLuint fbo;
218-
glGenFramebuffers(1, &fbo);
219-
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
220-
221-
// associate texture with FBO
222-
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture.name, 0);
223-
224-
GLuint depthRenderBuffer = 0;
225-
GLuint stencilRenderBuffer = 0;
226-
227-
#if __CC_PLATFORM_ANDROID
228-
229-
// Some android devices *only* support combined depth buffers (like all iOS devices), some android devices do not
230-
// support combined depth buffers, thus we have to create a seperate stencil buffer
231-
if(_depthStencilFormat)
232-
{
233-
//create and attach depth buffer
234-
235-
if(![[CCConfiguration sharedConfiguration] supportsPackedDepthStencil])
236-
{
237-
glGenRenderbuffers(1, &depthRenderBuffer);
238-
glBindRenderbuffer(GL_RENDERBUFFER, depthRenderBuffer);
239-
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, (GLsizei)powW, (GLsizei)powH); //GL_DEPTH_COMPONENT24_OES
240-
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depthRenderBuffer);
241-
242-
// if depth format is the one with stencil part, bind same render buffer as stencil attachment
243-
if(_depthStencilFormat == GL_DEPTH24_STENCIL8)
244-
{
245-
glGenRenderbuffers(1, &stencilRenderBuffer);
246-
glBindRenderbuffer(GL_RENDERBUFFER, stencilRenderBuffer);
247-
glRenderbufferStorage(GL_RENDERBUFFER, GL_STENCIL_INDEX8, (GLsizei)powW, (GLsizei)powH);
248-
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, stencilRenderBuffer);
249-
}
250-
}
251-
else
252-
{
253-
glGenRenderbuffers(1, &depthRenderBuffer);
254-
glBindRenderbuffer(GL_RENDERBUFFER, depthRenderBuffer);
255-
glRenderbufferStorage(GL_RENDERBUFFER, _depthStencilFormat, (GLsizei)powW, (GLsizei)powH);
256-
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depthRenderBuffer);
257-
258-
// if depth format is the one with stencil part, bind same render buffer as stencil attachment
259-
if(_depthStencilFormat == GL_DEPTH24_STENCIL8){
260-
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, depthRenderBuffer);
261-
}
262-
}
263-
}
264-
265-
#else
266-
267-
if(_depthStencilFormat)
268-
{
269-
//create and attach depth buffer
270-
glGenRenderbuffers(1, &depthRenderBuffer);
271-
glBindRenderbuffer(GL_RENDERBUFFER, depthRenderBuffer);
272-
glRenderbufferStorage(GL_RENDERBUFFER, _depthStencilFormat, (GLsizei)powW, (GLsizei)powH);
273-
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depthRenderBuffer);
274-
275-
// associate texture with FBO
276-
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture.name, 0);
277-
278-
if(_depthStencilFormat){
279-
//create and attach depth buffer
280-
glGenRenderbuffers(1, &depthRenderBuffer);
281-
glBindRenderbuffer(GL_RENDERBUFFER, depthRenderBuffer);
282-
glRenderbufferStorage(GL_RENDERBUFFER, _depthStencilFormat, (GLsizei)powW, (GLsizei)powH);
283-
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depthRenderBuffer);
284-
285-
// if depth format is the one with stencil part, bind same render buffer as stencil attachment
286-
if(_depthStencilFormat == GL_DEPTH24_STENCIL8){
287-
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, depthRenderBuffer);
288-
}
289-
}
290-
}
291-
292-
#endif
293-
294-
// check if it worked (probably worth doing :) )
295-
// NSAssert( glCheckFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE, @"Could not attach texture to framebuffer");
296-
297-
_FBO = [[CCRenderTextureFBO alloc] initWithFBO:fbo depthRenderBuffer:depthRenderBuffer stencilRenderBuffer:stencilRenderBuffer];
298-
299-
glBindRenderbuffer(GL_RENDERBUFFER, oldRBO);
300-
glBindFramebuffer(GL_FRAMEBUFFER, _oldFBO);
301-
302-
CCGL_DEBUG_POP_GROUP_MARKER();
303-
CC_CHECK_GL_ERROR_DEBUG();
304-
});
180+
_framebuffer = [[CCFrameBufferObject alloc] initWithTexture:texture depthStencilFormat:_depthStencilFormat];
305181

306182
// XXX Thayer says: I think this is incorrect for any situations where the content
307183
// size type isn't (points, points). The call to setTextureRect below eventually arrives
308184
// at some code that assumes the supplied size is in points so, if the size is not in points,
309185
// things break.
310-
CGRect rect = CGRectMake(0, 0, _contentSize.width, _contentSize.height);
311-
312186
[self assignSpriteTexture];
313-
[_sprite setTextureRect:rect];
187+
[_sprite setTextureRect:CGRectMake(0, 0, _contentSize.width, _contentSize.height)];
314188
}
315189

316190
-(void)assignSpriteTexture
@@ -329,25 +203,7 @@ -(void)setContentScale:(float)contentScale
329203

330204
-(void)destroy
331205
{
332-
GLuint fbo = _FBO.FBO;
333-
GLuint depthRenderBuffer = _FBO.depthRenderBuffer;
334-
GLuint stencilRenderBuffer = _FBO.stencilRenderBuffer;
335-
336-
CCRenderDispatch(YES, ^{
337-
glDeleteFramebuffers(1, &fbo);
338-
339-
if (depthRenderBuffer)
340-
{
341-
glDeleteRenderbuffers(1, &depthRenderBuffer);
342-
}
343-
344-
if (depthRenderBuffer)
345-
{
346-
glDeleteRenderbuffers(1, &stencilRenderBuffer);
347-
}
348-
});
349-
350-
_FBO = nil;
206+
_framebuffer = nil;
351207
self.texture = nil;
352208
}
353209

@@ -366,39 +222,20 @@ -(CCTexture *)texture
366222
return super.texture;
367223
}
368224

369-
-(GLuint)fbo
370-
{
371-
if (super.texture == nil)
372-
{
373-
[self create];
374-
}
375-
376-
return _FBO.FBO;
377-
}
378-
379225
-(CCRenderer *)begin
380226
{
381227
CCTexture *texture = self.texture;
228+
if(texture == nil){
229+
[self create];
230+
texture = self.texture;
231+
}
382232

383233
CCRenderer *renderer = [[CCDirector sharedDirector] rendererFromPool];
384-
[renderer prepareWithProjection:&_projection viewSize:texture.contentSize contentScale:texture.contentScale];
234+
[renderer prepareWithProjection:&_projection framebuffer:_framebuffer];
385235

386236
_previousRenderer = [CCRenderer currentRenderer];
387237
[CCRenderer bindRenderer:renderer];
388238

389-
CGSize pixelSize = texture.contentSizeInPixels;
390-
GLuint fbo = [self fbo];
391-
392-
[renderer pushGroup];
393-
394-
[renderer enqueueBlock:^{
395-
glGetFloatv(GL_VIEWPORT, _oldViewport.v);
396-
glViewport(0, 0, pixelSize.width, pixelSize.height );
397-
398-
glGetIntegerv(GL_FRAMEBUFFER_BINDING, &_oldFBO);
399-
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
400-
} globalSortOrder:NSIntegerMin debugLabel:@"CCRenderTexture: Bind FBO" threadSafe:NO];
401-
402239
return renderer;
403240
}
404241

@@ -427,13 +264,6 @@ -(void)end
427264
{
428265
CCRenderer *renderer = [CCRenderer currentRenderer];
429266

430-
[renderer enqueueBlock:^{
431-
glBindFramebuffer(GL_FRAMEBUFFER, _oldFBO);
432-
glViewport(_oldViewport.v[0], _oldViewport.v[1], _oldViewport.v[2], _oldViewport.v[3]);
433-
} globalSortOrder:NSIntegerMax debugLabel:@"CCRenderTexture: Restore FBO" threadSafe:NO];
434-
435-
[renderer popGroupWithDebugLabel:@"CCRenderTexture begin/end" globalSortOrder:0];
436-
437267
__unsafe_unretained CCDirector *director = [CCDirector sharedDirector];
438268
CCRenderDispatch(renderer.threadsafe, ^{
439269
[director addFrameCompletionHandler:^{

cocos2d/CCRenderTexture_Private.h

Lines changed: 2 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -8,41 +8,32 @@
88

99
#import "CCRenderTexture.h"
1010

11-
@class CCRenderTextureFBO;
11+
@class CCFrameBufferObject;
1212

1313
@interface CCRenderTexture() {
1414

1515
@protected
1616
GLenum _pixelFormat;
1717
GLuint _depthStencilFormat;
1818

19-
#warning TODO remove me.
20-
CCRenderer *_renderer;
2119
// Reference to the previous render to be restored by end.
2220
CCRenderer *_previousRenderer;
2321

2422
GLKVector4 _clearColor;
2523

26-
GLKVector4 _oldViewport;
27-
GLint _oldFBO;
28-
NSDictionary *_oldGlobalUniforms;
29-
30-
3124
float _contentScale;
3225
GLKMatrix4 _projection;
3326

3427
CCSprite* _sprite;
3528

36-
CCRenderTextureFBO *_FBO;
29+
CCFrameBufferObject *_framebuffer;
3730

3831
BOOL _contentSizeChanged;
3932
}
4033

4134
-(void)createTextureAndFboWithPixelSize:(CGSize)pixelSize;
4235
-(void)destroy;
4336

44-
-(GLuint)fbo;
45-
4637
-(void)assignSpriteTexture;
4738

4839
@end

0 commit comments

Comments
 (0)