Skip to content

Commit 8f4d8c1

Browse files
committed
Fixed a bug with render state caching and added unit tests for it.
1 parent 09ee27d commit 8f4d8c1

File tree

4 files changed

+88
-6
lines changed

4 files changed

+88
-6
lines changed

UnitTests/CCRendererTests.m

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,4 +82,22 @@ -(void)testBlendModeDefaults
8282
}
8383
}
8484

85+
-(void)testRenderStateCacheFlush
86+
{
87+
__weak CCRenderState *renderState = nil;
88+
89+
@autoreleasepool {
90+
CCBlendMode *mode = [CCBlendMode alphaMode];
91+
CCShader *shader = [CCShader positionColorShader];
92+
CCTexture *texture = [CCTexture textureWithFile:@"Images/grossini_dance_01.png"];
93+
94+
renderState = [CCRenderState renderStateWithBlendMode:mode shader:shader mainTexture:texture];
95+
XCTAssertNotNil(renderState, @"Render state was not created.");
96+
}
97+
98+
[CCRENDERSTATE_CACHE flush];
99+
100+
XCTAssertNil(renderState, @"Render state was not released.");
101+
}
102+
85103
@end

UnitTests/CCTextureTests.m

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
#import <XCTest/XCTest.h>
2+
#import "cocos2d.h"
3+
4+
#import "CCTextureCache.h"
5+
6+
@interface CCTextureTests : XCTestCase
7+
@end
8+
9+
@implementation CCTextureTests
10+
11+
-(void)testTextureCache
12+
{
13+
__weak CCTexture *textures[4];
14+
__weak CCRenderState *renderStates[3];
15+
16+
@autoreleasepool {
17+
// Load some cached textures
18+
for(int i=0; i<4; i++){
19+
NSString *name = [NSString stringWithFormat:@"Images/grossini_dance_0%d.png", i + 1];
20+
textures[i] = [CCTexture textureWithFile:name];
21+
}
22+
23+
// Make sure the textures were loaded.
24+
for(int i=0; i<4; i++){
25+
XCTAssertNotNil(textures[i], @"Texture %d not loaded.", i);
26+
}
27+
28+
// Create render states for the textures.
29+
CCBlendMode *blend = [CCBlendMode premultipliedAlphaMode];
30+
CCShader *shader = [CCShader positionColorShader];
31+
32+
// A cached render state..
33+
renderStates[0] = [CCRenderState renderStateWithBlendMode:blend shader:shader mainTexture:textures[0]];
34+
// An uncached, immutable render state.
35+
NSDictionary *uniforms1 = @{@"SomeTexture": textures[1]};
36+
renderStates[1] = [CCRenderState renderStateWithBlendMode:blend shader:shader shaderUniforms:uniforms1 copyUniforms:YES];
37+
// An uncached, mutable render state.
38+
NSMutableDictionary *uniforms2 = [NSMutableDictionary dictionaryWithObject:textures[2] forKey:@"SomeTexture"];
39+
renderStates[2] = [CCRenderState renderStateWithBlendMode:blend shader:shader shaderUniforms:uniforms2 copyUniforms:NO];
40+
// Leave textures[3] unused.
41+
42+
// Make sure the render states were loaded
43+
for(int i=0; i<3; i++){
44+
XCTAssertNotNil(renderStates[i], @"Render state %d not loaded.", i);
45+
}
46+
}
47+
48+
// Flush the texture cache
49+
[[CCTextureCache sharedTextureCache] removeUnusedTextures];
50+
51+
// Make sure the textures were unloaded.
52+
for(int i=0; i<4; i++){
53+
XCTAssertNil(textures[i], @"Texture %d still loaded.", i);
54+
}
55+
}
56+
57+
@end

cocos2d-tests-ios.xcodeproj/project.pbxproj

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@
7070
B7EE6A28181B075E00B983FE /* CCSliderTest.m in Sources */ = {isa = PBXBuildFile; fileRef = B7EE6A27181B075E00B983FE /* CCSliderTest.m */; };
7171
D29698121926DF7500BBB097 /* CCEffectPongTest.m in Sources */ = {isa = PBXBuildFile; fileRef = D29698111926DF7500BBB097 /* CCEffectPongTest.m */; };
7272
D2B4894C1917EE6700C3443A /* CCEffectsTest.m in Sources */ = {isa = PBXBuildFile; fileRef = D2B4894B1917EE6700C3443A /* CCEffectsTest.m */; };
73+
D32FDE8619B645CA0078CC16 /* CCTextureTests.m in Sources */ = {isa = PBXBuildFile; fileRef = D32FDE8519B645CA0078CC16 /* CCTextureTests.m */; };
7374
D3395F1A187F83E600F22C74 /* CCMemoryTests.m in Sources */ = {isa = PBXBuildFile; fileRef = D3395F19187F83E600F22C74 /* CCMemoryTests.m */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; };
7475
D340E10E185660BE006E605C /* CCPhysicsTest.m in Sources */ = {isa = PBXBuildFile; fileRef = D340E10C185660BE006E605C /* CCPhysicsTest.m */; };
7576
D340E10F185660BE006E605C /* TilemapTest.m in Sources */ = {isa = PBXBuildFile; fileRef = D340E10D185660BE006E605C /* TilemapTest.m */; };
@@ -194,6 +195,7 @@
194195
B7EE6A27181B075E00B983FE /* CCSliderTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = CCSliderTest.m; path = "cocos2d-ui-tests/tests/CCSliderTest.m"; sourceTree = SOURCE_ROOT; };
195196
D29698111926DF7500BBB097 /* CCEffectPongTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = CCEffectPongTest.m; path = "cocos2d-ui-tests/tests/CCEffectPongTest.m"; sourceTree = SOURCE_ROOT; };
196197
D2B4894B1917EE6700C3443A /* CCEffectsTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = CCEffectsTest.m; path = "cocos2d-ui-tests/tests/CCEffectsTest.m"; sourceTree = SOURCE_ROOT; };
198+
D32FDE8519B645CA0078CC16 /* CCTextureTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CCTextureTests.m; sourceTree = "<group>"; };
197199
D3395F19187F83E600F22C74 /* CCMemoryTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CCMemoryTests.m; sourceTree = "<group>"; };
198200
D340E10C185660BE006E605C /* CCPhysicsTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = CCPhysicsTest.m; path = "cocos2d-ui-tests/tests/CCPhysicsTest.m"; sourceTree = SOURCE_ROOT; };
199201
D340E10D185660BE006E605C /* TilemapTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TilemapTest.m; path = "cocos2d-ui-tests/tests/TilemapTest.m"; sourceTree = SOURCE_ROOT; };
@@ -262,6 +264,7 @@
262264
D3395F19187F83E600F22C74 /* CCMemoryTests.m */,
263265
D34CD3C418ABF4AA00D8E537 /* CCRendererTests.m */,
264266
92324E2918EB635500D78D3F /* CCReaderTest.m */,
267+
D32FDE8519B645CA0078CC16 /* CCTextureTests.m */,
265268
755569EC1856361100ED1B0F /* Supporting Files */,
266269
);
267270
path = UnitTests;
@@ -636,6 +639,7 @@
636639
buildActionMask = 2147483647;
637640
files = (
638641
92324E2A18EB635500D78D3F /* CCReaderTest.m in Sources */,
642+
D32FDE8619B645CA0078CC16 /* CCTextureTests.m in Sources */,
639643
75556A161856370A00ED1B0F /* CCFileUtilTests.m in Sources */,
640644
92FE241118F5F06F00647961 /* CCAnimationTest.m in Sources */,
641645
75556A171856370A00ED1B0F /* CCNodeTests.m in Sources */,

cocos2d/CCRenderer.m

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -288,16 +288,18 @@ +(void)initialize
288288

289289
-(instancetype)initWithBlendMode:(CCBlendMode *)blendMode shader:(CCShader *)shader shaderUniforms:(NSDictionary *)shaderUniforms
290290
{
291-
return [self initWithBlendMode:blendMode shader:shader shaderUniforms:shaderUniforms copyUniforms:NO];
291+
return [self initWithBlendMode:blendMode shader:shader mainTexture:nil shaderUniforms:shaderUniforms copyUniforms:NO];
292292
}
293293

294-
-(instancetype)initWithBlendMode:(CCBlendMode *)blendMode shader:(CCShader *)shader shaderUniforms:(NSDictionary *)shaderUniforms copyUniforms:(BOOL)copyUniforms
294+
-(instancetype)initWithBlendMode:(CCBlendMode *)blendMode shader:(CCShader *)shader mainTexture:(CCTexture *)mainTexture shaderUniforms:(NSDictionary *)shaderUniforms copyUniforms:(BOOL)copyUniforms
295295
{
296296
if((self = [super init])){
297297
_blendMode = blendMode;
298298
_shader = shader;
299299
_shaderUniforms = (copyUniforms ? [shaderUniforms copy] : shaderUniforms);
300300

301+
_mainTexture = mainTexture;
302+
301303
// The renderstate as a whole is immutable if the uniforms are copied.
302304
_immutable = copyUniforms;
303305
}
@@ -312,23 +314,24 @@ +(instancetype)renderStateWithBlendMode:(CCBlendMode *)blendMode shader:(CCShade
312314
mainTexture = [CCTexture none];
313315
}
314316

315-
CCRenderState *renderState = [[self alloc] initWithBlendMode:blendMode shader:shader shaderUniforms:@{CCShaderUniformMainTexture: mainTexture} copyUniforms:YES];
316-
renderState->_mainTexture = mainTexture;
317+
// The uniforms are immutable, but don't mark them to be copied.
318+
// This forces the cache to create a unique public object for the shared/key values.
319+
CCRenderState *renderState = [[self alloc] initWithBlendMode:blendMode shader:shader mainTexture:mainTexture shaderUniforms:@{CCShaderUniformMainTexture: mainTexture} copyUniforms:NO];
317320

318321
return [CCRENDERSTATE_CACHE objectForKey:renderState];
319322
}
320323

321324
+(instancetype)renderStateWithBlendMode:(CCBlendMode *)blendMode shader:(CCShader *)shader shaderUniforms:(NSDictionary *)shaderUniforms copyUniforms:(BOOL)copyUniforms
322325
{
323-
return [[self alloc] initWithBlendMode:blendMode shader:shader shaderUniforms:shaderUniforms copyUniforms:copyUniforms];
326+
return [[self alloc] initWithBlendMode:blendMode shader:shader mainTexture:nil shaderUniforms:shaderUniforms copyUniforms:copyUniforms];
324327
}
325328

326329
-(id)copyWithZone:(NSZone *)zone
327330
{
328331
if(_immutable){
329332
return self;
330333
} else {
331-
return [[CCRenderState allocWithZone:zone] initWithBlendMode:_blendMode shader:_shader shaderUniforms:_shaderUniforms copyUniforms:YES];
334+
return [[CCRenderState allocWithZone:zone] initWithBlendMode:_blendMode shader:_shader mainTexture:_mainTexture shaderUniforms:_shaderUniforms copyUniforms:YES];
332335
}
333336
}
334337

0 commit comments

Comments
 (0)