deviceの管理


DirectXで描画をする時はDeviceが必要なわけだが,どうにもこれがめんどくさい.

struct directx {
  LPDIRECT3DDEVICE9 device() const;
  // ...
};

struct texture {
  bool create(LPDIRECT3DDEVICE9 device, const std::string& file_path);
  // ...
};


なんて実装にすると,テクスチャを作る時がめんどう.

directx x;
texture tex;

tex.create(x.device(), "foo/bar.bmp");


こんなデバイスをどこにでも持っていかなきゃならない実装は嫌(めんどい)ので,裏に隠す.
private継承でis-implementation-in-terms-ofを実現(言ってみたかっただけ.
# それ以前に用語として合ってるのか・・・.


class directx {
  static LPDIRECT3DDEVICE9 device_;
protected:
  static LPDIRECT3DDEVICE9 device(){ return device_; }
  // ...
};

LPDIRECT3DDEVICE9 directx::device_ = NULL;


struct texture : private directx {
  bool create(const std::string& file_path){
    LPDIRECT3DDEVICE9 dev = directx::device();
    // ...
  }
  // ...
};


texture tex;
tex.create("baz/qux.bmp");


今までこうしてたんだけど,directxクラスの静的メンバ関数にいきなりアクセスされたりする(*1)とまずいので覆う.

あとcom_ptr<>を使ってみる.

以下の例はログの設定とか.


//TODO: directxクラスのローカルクラスへ
class directx_impl {
  LPDIRECT3DDEVICE9 device_;
  log_manager log_;
public:
  LPDIRECT3DDEVICE9 device() const{ return device_; }
  void log_level(int lv){ log_.level(lv); }
  // ...
};


class directx {
  static directx_impl& impl(){
    static directx_impl impl_;
    return impl_;
  }
protected:
  static com_ptr<IDirect3DDevice9> device(){
    return com_ptr<IDirect3DDevice9>(impl().device());
  }
public:
  static void log_level(int lv){ impl().log_level(lv); }
  // ...
};


struct texture : private directx {
  bool create(const std::string& file_path){
    auto dev = directx::device(); // 何
    // ...
  }
  // ...
};


int main(){

  directx::log_level(3); // ok
  texture tex;
  tex.create("quux/corge.bmp"); // ok

}


こんなんどうかな.
まだ実装してないけど.
これ・・・動くのか?(無責任


directx_impl::~directx_impl()が一回しか呼ばれないから,deviceの解放し忘れのチェックとかできるかも?.
staticなdeviceが一個ならだけど.


# C++0xのautoは知ってるけど,C++03のautoは知らなかったり.


余談だけど,LPDIRECT3DDEVICE9 IDirect3DTexture9::GetDevice()があるので,初期化さえしちゃえばいいんだよね.

LPDIRECT3DTEXTURE9 texture = my_create_texture("grault/garply.bmp");
LPDIRECT3DDEVICE9 device = texture->GetDevice();
device->some_func();
device->Release();