2012-05-06 9 views
1

私はcocos2dのバックグラウンドスレッドでテクスチャをレンダリングしようとしていますが、何らかの理由でテクスチャを使用できなくなったときに解放できません。CCRenderTextureが私の記憶を食べる

最初に2つのイメージを非同期に読み込み、次に新しいイメージをレンダリングするバックグラウンドタスクを実行します。私はそれがすべて正常に動作していると言うように、問題は、これらの関数を数回呼び出した後に私のアプリケーションクラッシュです。どのようにクリーンアップをするのか分かりません。利用可能なメモリをログアウトすると、毎回10〜15MBの間で失われていることがわかります(gfx1とgfx2は網膜の全画面の背景です)。

これらのコード行の中に問題がなければなりません。私がそれらを削除するとメモリの問題はもうなくなり、アプリケーションのプロファイリングにはリークはないということです。

テクスチャはNSMutableArrayです。私はインデックス0にテクスチャを持って、新しいものをレンダリングし、位置1に追加します。スプライトを置き換えた後、私はインデックス0で私の(今は古い)テクスチャを削除しようとし、新しいテクスチャはインデックス0になります。この機能は何度も繰り返されます。

だからここにコード

- (void) startBuildingTextureInBackground { 
    [[CCTextureCache sharedTextureCache] addImageAsync:@"gfx1.png" 
               target:self 
               selector:@selector(imageLoaded:)]; 
} 

- (void) imageLoaded: (id) obj { 
    rtxTexture1 = [[CCTextureCache sharedTextureCache] textureForKey:@"gfx1.png"]; 
    [[CCTextureCache sharedTextureCache] addImageAsync:@"gfx2.png" 
               target:self 
               selector:@selector(imageLoaded2:)]; 
} 

- (void) imageLoaded2: (id) obj { 
    rtxTexture2 = [[CCTextureCache sharedTextureCache] textureForKey:@"gfx2.png"]; 
    [self performSelectorInBackground:@selector(buildRtxTexture) withObject:nil]; 
} 

- (void) buildRtxTexture { 
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; 

    EAGLSharegroup *sharegroup = [[[[CCDirector sharedDirector] openGLView] context] sharegroup]; 
    EAGLContext *k_context = [[[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES1 sharegroup:sharegroup] autorelease]; 
    [EAGLContext setCurrentContext:k_context]; 
    [[CCDirector sharedDirector] setGLDefaultValues]; 

    CCSprite* gfx1 = [CCSprite spriteWithTexture:rtxTexture1]; 
    [rendernode addChild:gfx1]; 

    CCSprite* gfx2 = [CCSprite spriteWithTexture:rtxTexture2]; 
    [rendernode addChild:gfx2]; 

    CCRenderTexture* rtx = [CCRenderTexture renderTextureWithWidth:512 
                  height:320 
                 pixelFormat:kTexture2DPixelFormat_RGBA4444]; 

    [rtx beginWithClear:0 g:0 b:0 a:0]; 
    [rendernode visit]; 

    [rtx end]; 

    [rendernode removeChild:gfx1 cleanup:YES]; 
    [rendernode removeChild:gfx2 cleanup:YES]; 

    [[CCTextureCache sharedTextureCache] removeTexture:rtxTexture1]; 
    [[CCTextureCache sharedTextureCache] removeTexture:rtxTexture2]; 

    [EAGLContext setCurrentContext:nil]; 
    [self performSelectorOnMainThread:@selector(textureLoaded:) withObject:rtx.sprite.texture waitUntilDone:YES]; 

    [pool release]; 
} 

- (void) textureLoaded:(CCTexture2D*) newTexture { 
    [textures addObject:newTexture]; 
} 

- (void) replaceTexture { 
    if (rtxSprite != nil) { 
     [spriteDisplay removeChild:rtxSprite cleanup:YES]; 
     [[CCTextureCache sharedTextureCache] removeTexture:[textures objectAtIndex:0]]; 
     [textures removeObjectAtIndex:0]; 
    } 

    rtxSprite = [CCSprite spriteWithTexture:[textures objectAtIndex:0]]; 
    rtxSprite.scaleY = -1; 
    [spriteDisplay addChild: rtxSprite]; 
} 

答えて

0
  1. はあなたのコードをデバッグするようにしてください:ブレークポイントを追加するかのNSLog/CCLOGのCCTexture2D/CCRenderTextureのinit/deallocをメソッドの呼び出しを追跡します。

  2. バックグラウンドスレッドでCCRenderTextureに問題が発生する可能性があります。テクスチャを操作するためにCCRenderTextureを使用しようとすると、結果は予期しないものでした(黒いテクスチャまたはクラッシュ)。これは、メインループでOpenGL関数を呼び出し、OpenGLがステートマシンであるためです。回避策は、メインスレッド(performSelectorOnMainThread)のCCRenderTextureでメソッドを呼び出すことでした。

0

[pool release]を呼び出す前に、コンテキストをnilに設定すると問題が解決されます。

関連する問題