//------------------------------------------------------------------------------
// Lamp : Open source game middleware
// Copyright (C) 2004  Junpei Ohtani ( Email : junpee@users.sourceforge.jp )
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
//------------------------------------------------------------------------------

/** @file
 * スプライトピクチャRGBA8実装
 * @author Junpee
 */

#include "LampBasic.h"
#include "Graphics2D/Sprite/SpritePictureRGBA8.h"
#include "Graphics/Renderer/RenderingDevice.h"
#include "Core/Codec/LinearMinificationFilter/LinearMinificationFilter.h"

namespace Lamp{

//------------------------------------------------------------------------------
// 生成、破棄
//------------------------------------------------------------------------------
// コンストラクタ
SpritePictureRGBA8::SpritePictureRGBA8() : image_(NULL){
}
//------------------------------------------------------------------------------
// デストラクタ
SpritePictureRGBA8::~SpritePictureRGBA8(){
	SafeArrayDelete(image_);
}
//------------------------------------------------------------------------------
// サイズ
//------------------------------------------------------------------------------
// サイズの設定
void SpritePictureRGBA8::setSize(const DimensionI& size){
	SpritePicture::setSize(size);
	SafeArrayDelete(image_);
	image_ = new Color4c[size.width * size.height];
}
//------------------------------------------------------------------------------
// Direct3Dテクスチャ
//------------------------------------------------------------------------------
// D3Dテクスチャのコンパイル
bool SpritePictureRGBA8::compileD3DTexture(){
	Assert(image_ != NULL);
	Direct3DTexture* d3dTexture;
	const DimensionI& size = getSize();
	d3dTexture = RenderingDevice::getInstance()->createTexture(
		D3DFMT_A8R8G8B8, size.width, size.height);
	setD3DTexture(d3dTexture);
	// 書き込み
	if(!compileMipmap(image_, size, 0)){ return false; }
	return true;
}
//------------------------------------------------------------------------------
// イメージのコンパイル
bool SpritePictureRGBA8::compileImage(
	const Color4c* image, const DimensionI& size, int mipmapLevel){
	RenderingDevice* device = RenderingDevice::getInstance();
	D3DLOCKED_RECT lockedRect =
		device->lockTexture(getD3DTexture(), mipmapLevel);
	u_char* lineAddr = (u_char*)lockedRect.pBits;
	for(int i = 0; i < size.height; i++){
		u_int* writeAddr = (u_int*)lineAddr;
		int offset = i * size.width;
		for(int j = 0; j < size.width; j++){
			(*writeAddr) = image[offset + j].getARGB();
			writeAddr++;
		}
		lineAddr += lockedRect.Pitch;
	}
	device->unlockTexture(getD3DTexture(), mipmapLevel);
	return true;
}
//------------------------------------------------------------------------------
// ミップマップのコンパイル
bool SpritePictureRGBA8::compileMipmap(
	const Color4c* image, const DimensionI& size, int mipmapLevel){
	// イメージのコンパイル
	if(!compileImage(image, size, mipmapLevel)){ return false; }
	// ミップマップ再帰チェック
	mipmapLevel++;
	if((size.width == 1) && (size.height == 1)){
		Assert(getD3DTexture()->GetLevelCount() == mipmapLevel);
		return true;
	}
	DimensionI nextSize = LinearMinificationFilter::getNextSize(size);
	Color4c* nextImage = new Color4c[nextSize.width * nextSize.height];
	// ブロックフィルタで縮小
	LinearMinificationFilter::filter(image, size, nextImage, nextSize);
	bool nextLevelResult = compileMipmap(nextImage, nextSize, mipmapLevel);
	delete[] nextImage;
	return nextLevelResult;
}
//------------------------------------------------------------------------------
} // End of namespace Lamp
//------------------------------------------------------------------------------
