Skip to content

Commit fef75c7

Browse files
committed
Merge branch 'performance-fixes' into develop
Conflicts: cocos2d/CCSprite.m
2 parents 78746d5 + b077bef commit fef75c7

File tree

10 files changed

+484
-364
lines changed

10 files changed

+484
-364
lines changed

cocos2d-ios.xcodeproj/project.pbxproj

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -297,6 +297,7 @@
297297
D39FA9C818C1BC6B00441627 /* CCShader_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = D39FA9C718C1BC6B00441627 /* CCShader_Private.h */; };
298298
D3A2E7D2181E12750033614C /* CCPhysicsShape.h in Headers */ = {isa = PBXBuildFile; fileRef = D3A2E7D0181E12750033614C /* CCPhysicsShape.h */; };
299299
D3A2E7D3181E12750033614C /* CCPhysicsShape.m in Sources */ = {isa = PBXBuildFile; fileRef = D3A2E7D1181E12750033614C /* CCPhysicsShape.m */; };
300+
D3B2010D19805F4500D92915 /* CCNoARC.m in Sources */ = {isa = PBXBuildFile; fileRef = D3B2010C19805F4500D92915 /* CCNoARC.m */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; };
300301
E01E6D8C121F130E001A484F /* CCLabelBMFont.h in Headers */ = {isa = PBXBuildFile; fileRef = E01E6D8A121F130E001A484F /* CCLabelBMFont.h */; };
301302
E01E6D8D121F130E001A484F /* CCLabelBMFont.m in Sources */ = {isa = PBXBuildFile; fileRef = E01E6D8B121F130E001A484F /* CCLabelBMFont.m */; };
302303
E02BB6D6126CA93A006E46A2 /* CCAnimationCache.h in Headers */ = {isa = PBXBuildFile; fileRef = E02BB6D4126CA93A006E46A2 /* CCAnimationCache.h */; };
@@ -636,6 +637,7 @@
636637
D39FA9C718C1BC6B00441627 /* CCShader_Private.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CCShader_Private.h; sourceTree = "<group>"; };
637638
D3A2E7D0181E12750033614C /* CCPhysicsShape.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CCPhysicsShape.h; sourceTree = "<group>"; };
638639
D3A2E7D1181E12750033614C /* CCPhysicsShape.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CCPhysicsShape.m; sourceTree = "<group>"; };
640+
D3B2010C19805F4500D92915 /* CCNoARC.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CCNoARC.m; sourceTree = "<group>"; };
639641
E01E6D8A121F130E001A484F /* CCLabelBMFont.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; path = CCLabelBMFont.h; sourceTree = "<group>"; };
640642
E01E6D8B121F130E001A484F /* CCLabelBMFont.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; lineEnding = 0; path = CCLabelBMFont.m; sourceTree = "<group>"; };
641643
E02BB6D4126CA93A006E46A2 /* CCAnimationCache.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CCAnimationCache.h; sourceTree = "<group>"; };
@@ -787,6 +789,7 @@
787789
D38058181889AD6000822437 /* CCRenderer.h */,
788790
D309054F18AC23110081BF11 /* CCRenderer_private.h */,
789791
D38058191889AD6000822437 /* CCRenderer.m */,
792+
D3B2010C19805F4500D92915 /* CCNoARC.m */,
790793
);
791794
path = cocos2d;
792795
sourceTree = "<group>";
@@ -1689,6 +1692,7 @@
16891692
A6DC4E0A18055DCC00C280A6 /* CCTransition.m in Sources */,
16901693
9DE9042A192D630000AEB37A /* CCEffectRenderer.m in Sources */,
16911694
B77060021831A07B0043CC67 /* NSMutableDictionary+WeakReferences.m in Sources */,
1695+
D3B2010D19805F4500D92915 /* CCNoARC.m in Sources */,
16921696
A6A0734617C788EB004343C8 /* CCResponderManager.m in Sources */,
16931697
A6A0734B17C78EF3004343C8 /* CCResponder.m in Sources */,
16941698
B78AE46317E7AF1C0028BE0B /* CCButton.m in Sources */,

cocos2d/CCNoARC.m

Lines changed: 239 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,239 @@
1+
#import "CCTexture.h"
2+
#import "CCNode_Private.h"
3+
#import "CCSprite_Private.h"
4+
#import "CCRenderer_Private.h"
5+
#import "CCShader_Private.h"
6+
7+
8+
@implementation CCNode(NoARC)
9+
10+
static inline GLKMatrix4
11+
CCNodeTransform(CCNode *node, GLKMatrix4 parentTransform)
12+
{
13+
CGAffineTransform t = [node nodeToParentTransform];
14+
float z = node->_vertexZ;
15+
16+
// Convert to 4x4 column major GLK matrix.
17+
return GLKMatrix4Multiply(parentTransform, GLKMatrix4Make(
18+
t.a, t.b, 0.0f, 0.0f,
19+
t.c, t.d, 0.0f, 0.0f,
20+
0.0f, 0.0f, 1.0f, 0.0f,
21+
t.tx, t.ty, z, 1.0f
22+
));
23+
}
24+
25+
-(GLKMatrix4)transform:(const GLKMatrix4 *)parentTransform
26+
{
27+
return CCNodeTransform(self, *parentTransform);
28+
}
29+
30+
-(void) visit:(CCRenderer *)renderer parentTransform:(const GLKMatrix4 *)parentTransform
31+
{
32+
// quick return if not visible. children won't be drawn.
33+
if (!_visible) return;
34+
35+
[self sortAllChildren];
36+
37+
GLKMatrix4 transform = CCNodeTransform(self, *parentTransform);
38+
BOOL drawn = NO;
39+
40+
for(CCNode *child in _children){
41+
if(!drawn && child.zOrder >= 0){
42+
[self draw:renderer transform:&transform];
43+
drawn = YES;
44+
}
45+
46+
[child visit:renderer parentTransform:&transform];
47+
}
48+
49+
if(!drawn) [self draw:renderer transform:&transform];
50+
51+
// reset for next frame
52+
_orderOfArrival = 0;
53+
}
54+
55+
@end
56+
57+
58+
@implementation CCSprite(NoARC)
59+
60+
static inline void
61+
EnqueueTriangles(CCSprite *self, CCRenderer *renderer, const GLKMatrix4 *transform)
62+
{
63+
CCRenderState *state = self->_renderState ?: self.renderState;
64+
CCRenderBuffer buffer = [renderer enqueueTriangles:2 andVertexes:4 withState:state globalSortOrder:0];
65+
66+
CCRenderBufferSetVertex(buffer, 0, CCVertexApplyTransform(self->_verts.bl, transform));
67+
CCRenderBufferSetVertex(buffer, 1, CCVertexApplyTransform(self->_verts.br, transform));
68+
CCRenderBufferSetVertex(buffer, 2, CCVertexApplyTransform(self->_verts.tr, transform));
69+
CCRenderBufferSetVertex(buffer, 3, CCVertexApplyTransform(self->_verts.tl, transform));
70+
71+
CCRenderBufferSetTriangle(buffer, 0, 0, 1, 2);
72+
CCRenderBufferSetTriangle(buffer, 1, 0, 2, 3);
73+
}
74+
75+
-(void)draw:(CCRenderer *)renderer transform:(const GLKMatrix4 *)transform;
76+
{
77+
if(!CCRenderCheckVisbility(transform, _vertexCenter, _vertexExtents)) return;
78+
79+
if (_effect)
80+
{
81+
_effectRenderer.contentSize = self.contentSize;
82+
if ([self.effect prepareForRendering] == CCEffectPrepareSuccess)
83+
{
84+
// Preparing an effect for rendering can modify its uniforms
85+
// dictionary which means we need to reinitialize our copy of the
86+
// uniforms.
87+
[self updateShaderUniformsFromEffect];
88+
}
89+
[_effectRenderer drawSprite:self withEffect:self.effect uniforms:_shaderUniforms renderer:renderer transform:transform];
90+
}
91+
else
92+
{
93+
EnqueueTriangles(self, renderer, transform);
94+
}
95+
96+
#if CC_SPRITE_DEBUG_DRAW
97+
const GLKVector2 zero = {{0, 0}};
98+
const GLKVector4 white = {{1, 1, 1, 1}};
99+
100+
CCRenderBuffer debug = [renderer enqueueLines:4 andVertexes:4 withState:[CCRenderState debugColor] globalSortOrder:0];
101+
CCRenderBufferSetVertex(debug, 0, (CCVertex){GLKMatrix4MultiplyVector4(*transform, _verts.bl.position), zero, zero, white});
102+
CCRenderBufferSetVertex(debug, 1, (CCVertex){GLKMatrix4MultiplyVector4(*transform, _verts.br.position), zero, zero, white});
103+
CCRenderBufferSetVertex(debug, 2, (CCVertex){GLKMatrix4MultiplyVector4(*transform, _verts.tr.position), zero, zero, white});
104+
CCRenderBufferSetVertex(debug, 3, (CCVertex){GLKMatrix4MultiplyVector4(*transform, _verts.tl.position), zero, zero, white});
105+
106+
CCRenderBufferSetLine(debug, 0, 0, 1);
107+
CCRenderBufferSetLine(debug, 1, 1, 2);
108+
CCRenderBufferSetLine(debug, 2, 2, 3);
109+
CCRenderBufferSetLine(debug, 3, 3, 0);
110+
#endif
111+
}
112+
113+
-(void)enqueueTriangles:(CCRenderer *)renderer transform:(const GLKMatrix4 *)transform
114+
{
115+
EnqueueTriangles(self, renderer, transform);
116+
}
117+
118+
@end
119+
120+
121+
@implementation CCRenderer(NoARC)
122+
123+
-(CCRenderBuffer)enqueueTriangles:(NSUInteger)triangleCount andVertexes:(NSUInteger)vertexCount withState:(CCRenderState *)renderState globalSortOrder:(NSInteger)globalSortOrder;
124+
{
125+
// Need to record the first vertex or element index before pushing more vertexes.
126+
size_t firstVertex = _vertexBuffer.count;
127+
size_t firstElement = _elementBuffer.count;
128+
129+
size_t elementCount = 3*triangleCount;
130+
CCVertex *vertexes = CCGraphicsBufferPushElements(&_vertexBuffer, vertexCount, self);
131+
GLushort *elements = CCGraphicsBufferPushElements(&_elementBuffer, elementCount, self);
132+
133+
CCRenderCommandDraw *previous = _lastDrawCommand;
134+
if(previous && previous->_renderState == renderState && previous->_globalSortOrder == globalSortOrder){
135+
// Batch with the previous command.
136+
[previous batchElements:(GLsizei)elementCount];
137+
} else {
138+
// Start a new command.
139+
CCRenderCommandDraw *command = [[CCRenderCommandDraw alloc] initWithMode:GL_TRIANGLES renderState:renderState first:(GLint)firstElement elements:(GLsizei)elementCount globalSortOrder:globalSortOrder];
140+
[_queue addObject:command];
141+
[command release];
142+
143+
_lastDrawCommand = command;
144+
}
145+
146+
return (CCRenderBuffer){vertexes, elements, firstVertex};
147+
}
148+
149+
-(CCRenderBuffer)enqueueLines:(NSUInteger)lineCount andVertexes:(NSUInteger)vertexCount withState:(CCRenderState *)renderState globalSortOrder:(NSInteger)globalSortOrder;
150+
{
151+
// Need to record the first vertex or element index before pushing more vertexes.
152+
size_t firstVertex = _vertexBuffer.count;
153+
size_t firstElement = _elementBuffer.count;
154+
155+
size_t elementCount = 2*lineCount;
156+
CCVertex *vertexes = CCGraphicsBufferPushElements(&_vertexBuffer, vertexCount, self);
157+
GLushort *elements = CCGraphicsBufferPushElements(&_elementBuffer, elementCount, self);
158+
159+
CCRenderCommandDraw *command = [[CCRenderCommandDraw alloc] initWithMode:GL_LINES renderState:renderState first:(GLint)firstElement elements:(GLsizei)elementCount globalSortOrder:globalSortOrder];
160+
[_queue addObject:command];
161+
[command release];
162+
163+
// Line drawing commands are currently intended for debugging and cannot be batched.
164+
_lastDrawCommand = nil;
165+
166+
return(CCRenderBuffer){vertexes, elements, firstVertex};
167+
}
168+
169+
@end
170+
171+
172+
@implementation CCRenderer(NoARCPrivate)
173+
174+
-(void)setRenderState:(CCRenderState *)renderState
175+
{
176+
[self bindVAO:YES];
177+
if(renderState == _renderState) return;
178+
179+
glPushGroupMarkerEXT(0, "CCRenderer: Render State");
180+
181+
// Set the blending state.
182+
NSDictionary *blendOptions = renderState->_blendMode->_options;
183+
if(blendOptions != _blendOptions){
184+
glInsertEventMarkerEXT(0, "Blending mode");
185+
186+
if(blendOptions == CCBLEND_DISABLED_OPTIONS){
187+
if(_blendOptions != CCBLEND_DISABLED_OPTIONS) glDisable(GL_BLEND);
188+
} else {
189+
if(_blendOptions == nil || _blendOptions == CCBLEND_DISABLED_OPTIONS) glEnable(GL_BLEND);
190+
191+
glBlendFuncSeparate(
192+
[blendOptions[CCBlendFuncSrcColor] unsignedIntValue],
193+
[blendOptions[CCBlendFuncDstColor] unsignedIntValue],
194+
[blendOptions[CCBlendFuncSrcAlpha] unsignedIntValue],
195+
[blendOptions[CCBlendFuncDstAlpha] unsignedIntValue]
196+
);
197+
198+
glBlendEquationSeparate(
199+
[blendOptions[CCBlendEquationColor] unsignedIntValue],
200+
[blendOptions[CCBlendEquationAlpha] unsignedIntValue]
201+
);
202+
}
203+
204+
_blendOptions = blendOptions;
205+
}
206+
207+
// Bind the shader.
208+
CCShader *shader = renderState->_shader;
209+
if(shader != _shader){
210+
glInsertEventMarkerEXT(0, "Shader");
211+
212+
glUseProgram(shader->_program);
213+
214+
_shader = shader;
215+
_shaderUniforms = nil;
216+
}
217+
218+
// Set the shader's uniform state.
219+
NSDictionary *shaderUniforms = renderState->_shaderUniforms;
220+
NSDictionary *globalShaderUniforms = _globalShaderUniforms;
221+
if(shaderUniforms != _shaderUniforms){
222+
glInsertEventMarkerEXT(0, "Uniforms");
223+
224+
NSDictionary *setters = shader->_uniformSetters;
225+
for(NSString *uniformName in setters){
226+
CCUniformSetter setter = setters[uniformName];
227+
setter(self, shaderUniforms, globalShaderUniforms);
228+
}
229+
_shaderUniforms = shaderUniforms;
230+
}
231+
232+
CC_CHECK_GL_ERROR_DEBUG();
233+
glPopGroupMarkerEXT();
234+
235+
_renderState = renderState;
236+
return;
237+
}
238+
239+
@end

cocos2d/CCNode.h

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -553,9 +553,6 @@ A common user pattern in building a Cocos2d game is to subclass CCNode, add it t
553553
/// @name Accessing Transformations and Matrices
554554
/// -----------------------------------------------------------------------
555555

556-
/** Returns the 4x4 drawing transformation for this node. Really only useful when overriding visit:parentTransform: */
557-
-(GLKMatrix4)transform:(const GLKMatrix4 *)parentTransform;
558-
559556
/** Returns the matrix that transform the node's (local) space coordinates into the parent's space coordinates.
560557
The matrix is in Pixels.
561558
*/
@@ -630,9 +627,6 @@ A common user pattern in building a Cocos2d game is to subclass CCNode, add it t
630627
/** Calls visit:parentTransform using the current renderer and projection. */
631628
-(void) visit;
632629

633-
/** Recursive method that visit its children and draw them. */
634-
-(void) visit:(CCRenderer *)renderer parentTransform:(const GLKMatrix4 *)parentTransform;
635-
636630
/** Sets and returns the color (tint), alpha is ignored when setting. */
637631
@property (nonatomic,strong) CCColor* color;
638632

@@ -699,3 +693,14 @@ A common user pattern in building a Cocos2d game is to subclass CCNode, add it t
699693

700694
@end
701695

696+
697+
@interface CCNode(NoARC)
698+
699+
/** Returns the 4x4 drawing transformation for this node. Really only useful when overriding visit:parentTransform: */
700+
-(GLKMatrix4)transform:(const GLKMatrix4 *)parentTransform;
701+
702+
/** Recursive method that visit its children and draw them. */
703+
-(void) visit:(CCRenderer *)renderer parentTransform:(const GLKMatrix4 *)parentTransform;
704+
705+
@end
706+

cocos2d/CCNode.m

Lines changed: 6 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -909,31 +909,8 @@ - (void) sortAllChildren
909909

910910
-(void)draw:(__unsafe_unretained CCRenderer *)renderer transform:(const GLKMatrix4 *)transform {}
911911

912-
-(void) visit:(__unsafe_unretained CCRenderer *)renderer parentTransform:(const GLKMatrix4 *)parentTransform
913-
{
914-
// quick return if not visible. children won't be drawn.
915-
if (!_visible)
916-
return;
917-
918-
[self sortAllChildren];
919-
920-
GLKMatrix4 transform = NodeTransform(self, *parentTransform);
921-
BOOL drawn = NO;
922-
923-
for(CCNode *child in _children){
924-
if(!drawn && child.zOrder >= 0){
925-
[self draw:renderer transform:&transform];
926-
drawn = YES;
927-
}
928-
929-
[child visit:renderer parentTransform:&transform];
930-
}
931-
932-
if(!drawn) [self draw:renderer transform:&transform];
933-
934-
// reset for next frame
935-
_orderOfArrival = 0;
936-
}
912+
// Defined in CCNoARC.m
913+
// -(void) visit:(__unsafe_unretained CCRenderer *)renderer parentTransform:(const GLKMatrix4 *)parentTransform
937914

938915
-(void)visit
939916
{
@@ -946,25 +923,8 @@ -(void)visit
946923

947924
#pragma mark CCNode - Transformations
948925

949-
static inline GLKMatrix4
950-
NodeTransform(__unsafe_unretained CCNode *node, GLKMatrix4 parentTransform)
951-
{
952-
CGAffineTransform t = [node nodeToParentTransform];
953-
float z = node->_vertexZ;
954-
955-
// Convert to 4x4 column major GLK matrix.
956-
return GLKMatrix4Multiply(parentTransform, GLKMatrix4Make(
957-
t.a, t.b, 0.0f, 0.0f,
958-
t.c, t.d, 0.0f, 0.0f,
959-
0.0f, 0.0f, 1.0f, 0.0f,
960-
t.tx, t.ty, z, 1.0f
961-
));
962-
}
963-
964-
-(GLKMatrix4)transform:(const GLKMatrix4 *)parentTransform
965-
{
966-
return NodeTransform(self, *parentTransform);
967-
}
926+
// Implemented in CCNoARC.m
927+
//-(GLKMatrix4)transform:(const GLKMatrix4 *)parentTransform
968928

969929
#pragma mark CCPhysics support.
970930

@@ -1446,7 +1406,8 @@ -(void)setPositionInPoints:(CGPoint)positionInPoints
14461406

14471407
- (CGAffineTransform)nodeToParentTransform
14481408
{
1449-
CCPhysicsBody *physicsBody = GetBodyIfRunning(self);
1409+
// The body ivar cannot be changed while this method is running and it's ARC retain/release is 70% of the profile samples for this method.
1410+
__unsafe_unretained CCPhysicsBody *physicsBody = GetBodyIfRunning(self);
14501411
if(physicsBody){
14511412

14521413
CGAffineTransform rigidTransform;

0 commit comments

Comments
 (0)