描画キャッシュ(2)
OO的にキャッシュするのであれば、こんな感じだろうか。
class CacheObject{ public: virtual ~CacheObject(){} virtual void Draw() = 0; virtual int GetPriority() = 0; }; class DrawCache{ public: DrawCache() : _count( 0 ){} void Draw( CacheObject* obj ){ if( obj == null ) return; if( _count < OBJ_MAX ){ _cache[ _count ] = obj; _count++; } } // プライオリティに基づいてソート void sort(); void Flush(){ sort(); for( int i = 0 ; i < _count ; i++ ){ _cache[ i ]->Draw(); } _count = 0; } private: enum{ OBJ_MAX = 100 , }; CacheObject* _cache[ OBJ_MAX ]; int _count; };
class DrawImageCacheObject : public CacheObject{ public: DrawImageCacheObject( Image dst , int dx , int dy , Image src , int priority ){ _dst = dst; _dx = dx; _dy = dy; _src = src; _priority = priority; } virtual void Draw(){ Graphics::DrawImage( _dst , _dx , _dy , _src ); } virtual int GetPriority(){ return _priority; } private: Image _dst; int _dx; int _dy; Image _src; int _priority; }; class FillRectCacheObject : public CacheObject{ public: FillRectCacheObject( Image dst , int dx , int dy , int dw , int dh , uint32 color , int priority ){ _dst = dst; _dx = dx; _dy = dy; _dw = dw; _dh = dh; _color = color; _priority = priority; } virtual void Draw(){ Graphics::FillRect( _dst , _dx , _dy , _dw , _dh , _color ); } virtual int GetPriority(){ return _priority; } private: Image _dst; int _dx; int _dy; int _dw; int _dh; uint32 _color; int _priority; };
CacheObject インターフェースクラスを作り、その下に実際の描画処理を入れることによって、ユーザ側でキャッシュオブジェクトを拡張することが出来るようになる。
また、DrawCache クラスはオブジェクトへのポインタしか持たないので、メモリも最低限しか取らない。
ただ、描画をキャッシュするときにポインタを渡しているので、ユーザ側でキャッシュオブジェクトが存在していることを保証しなければならない。
これをスマートポインタにして、
DrawCache cache;
cache.Draw(
smart_ptr< CacheObject >(
new DrawImageCacheObject( dst , dx , dy , src , priority )
)
);
こうやってキャッシュする方法も考えられるけど、これだとキャッシュするたびに new しているので、(BREW は)new で null を返す可能性があるし、動的なメモリの確保は速度的にも気になる。
結局メンバとかにキャッシュオブジェクトを置いて、そのポインタ(またはスマートポインタ)を渡すことになるんだろうけど、その場合は DrawCache を wrap したクラスでキャッシュオブジェクトを生成して、そのキャッシュオブジェクトを使用して DrawCache に委譲するクラスを作ると思う。
class DrawCacheImpl{ public: DrawCacheImpl() : _drawImageCount( 0 ) , _fillRectCount( 0 ) , _myDrawCount( 0 ){} void DrawImage( Image dst , int dx , int dy , Image src , int priority ){ if( _drawImageCount < MAX_DRAWIMAGE ){ _drawImageCache[ _drawImageCount ].Set( dst , dx , dy , src , priority ); _drawCache.Draw( &_drawImageCache[ _drawImageCount ] ); _drawImageCount++; } } void FillRect( Image dst , int dx , int dy , int dw , int dy , uint32 color , int priority ){ if( _fillRectCount < MAX_FILLRECT ){ _fillRectCache[ _fillRectCount ].Set( dst , dx , dy , dw , dy , color , priority ); _drawCache.Draw( &_fillRectCache[ _fillRectCount ] ); _fillRectCount++; } } // このプロジェクトでしか使用しない描画オブジェクト void MyDraw( Image dst , int dx , int dy ){ if( _myDrawCount < MAX_MYDRAW ){ _myDrawCache[ _myDrawCount ].Set( dst , dx , dy ); _drawCache.Draw( &_myDrawCache[ _myDrawCount ] ); _myDrawCount++; } } void Flush(){ _drawCache.Flush(); _drawImageCount = 0; _fillRectCount = 0; _myDrawCount = 0; } private: enum{ MAX_DRAWIMAGE = 100 , MAX_FILLRECT = 50 , MAX_MYDRAW = 10 , }; DrawImageCacheObject _drawImageCache[ MAX_DRAWIMAGE ]; int _drawImageCount; FillRectCacheObject _fillRectCache[ MAX_FILLRECT ]; int _fillRectCount; MyDrawCacheObject _myDrawCache[ MAX_MYDRAW ]; int _myDrawCount; DrawCache _drawCache; };
こんな感じだろうか。
ただ、そんな面倒なことを毎回やりたくないので、出来ればライブラリ側にキャッシュオブジェクトを置いてやりたい。
で、ここでどうしたらいいかわからなくなる。
……どうするかなぁ(;´Д`)