//******************************************************************************
//
// OGL Utility / OGLTexture
//
// テクスチャクラス
//
// Copyright (C) 2010-2022 WADA Masashi. All Rights Reserved.
//
//******************************************************************************

#import "YNBaseLib.h"
#import "OGLTexture.h"


//##############################################################################
// テクスチャクラス
//##############################################################################
//******************************************************************************
// コンストラクタ
//******************************************************************************
OGLTexture::OGLTexture(void)
{
	m_Texture = nil;
	m_Width = 0;
	m_Height = 0;
}

//******************************************************************************
// デストラクタ
//******************************************************************************
OGLTexture::~OGLTexture(void)
{
	Release();
}

//******************************************************************************
// 任意画像サイズ有効化：初期値 false
//******************************************************************************
void OGLTexture::EnableRectanbleExt(
		bool isEnable
	)
{
	return;
}

//******************************************************************************
// 画像ファイル読み込み
//******************************************************************************
int OGLTexture::LoadImageFile(
		OGLDevice* pOGLDevice,
		NSString* pImageFilePath
	)
{
	int result = 0;
	NSImageRep* pImage = nil;
	
	//画像ファイル読み込み
	pImage = [NSBitmapImageRep imageRepWithContentsOfFile:pImageFilePath];
	if (pImage == nil) {
		result = YN_SET_ERR(@"Bitmap file open error.", 0, 0);
		goto EXIT;
	}
	if (![pImage isKindOfClass:[NSBitmapImageRep class]]) {
		result = YN_SET_ERR(@"Bitmap file open error.", 0, 0);
		goto EXIT;
	}
	
	//ビットマップからテクスチャ作成
	result = LoadBitmap(pOGLDevice, (NSBitmapImageRep*)pImage);
	if (result != 0) goto EXIT;
	
EXIT:;
	//TODO: pBitmapImageはautoreleaseされている？
	return result;
}

//******************************************************************************
// ビットマップ読み込み
//******************************************************************************
int OGLTexture::LoadBitmap(
		OGLDevice* pOGLDevice,
		NSBitmapImageRep* pBitmapImage
	)
{
	int result = 0;
	NSError* pError = nil;
	MTKTextureLoader* pTextureLoader = nil;
	NSDictionary* pTextureLoaderOptions = nil;
	
	if (pBitmapImage == nil) {
		result = YN_SET_ERR(@"Program error.", 0, 0);
		goto EXIT;
	}
	
	Release();
	
	m_Width = (OGLsizei)[pBitmapImage pixelsWide];
	m_Height = (OGLsizei)[pBitmapImage pixelsHigh];
	
	//テクスチャ最大サイズを超えていないことを確認
	if ((m_Width > OGL_MAX_TEXTURE_SIZE) || (m_Height > OGL_MAX_TEXTURE_SIZE)) {
		result = YN_SET_ERR(@"Bitmap size is too large.", m_Width, m_Height);
		goto EXIT;
	}
	
	//テクスチャローダー生成
	pTextureLoader = [[MTKTextureLoader alloc] initWithDevice:pOGLDevice->GetMetalDevice()];
	if (pTextureLoader == nil) {
		result = YN_SET_ERR(@"Metal API error.", 0, 0);
		goto EXIT;
	}
	
	//テクスチャローダーオプション作成
	pTextureLoaderOptions = @{
		//テクスチャ使用目的：シェーダー読み取り
		MTKTextureLoaderOptionTextureUsage: @(MTLTextureUsageShaderRead),
		
		//メモリ配置とアクセス権：GPUのみアクセス可能
		MTKTextureLoaderOptionTextureStorageMode: @(MTLStorageModePrivate),
		
		//原点指定：左上 -- 未指定の場合は画像は反転されない
		//MTKTextureLoaderOptionOrigin: MTKTextureLoaderOriginTopLeft,
		
		//SRGB：無効（テクスチャが暗くなる問題を回避）
		MTKTextureLoaderOptionSRGB: @(NO)
	};
	
	//テクスチャローダーオプションに関するメモ
	//  OS X 10.11(El Capitan)では、テクスチャローダーで読み込んだ画像が上下反転してしまう。
	//  macOS 10.12(Sierra)からは、テクスチャローダーオプションに MTKTextureLoaderOptionOrigin が追加されたことに伴い、
	//  MTKTextureLoaderOptionOrigin を省略した場合に画像が上下反転されなくなった。
	//  OS X 10.11(El Capitan)はMIDITrailのサポート対象外とするため、対策しない。
	
	//テクスチャ読み込み
	m_Texture = [pTextureLoader newTextureWithCGImage:(pBitmapImage.CGImage)
										  options:pTextureLoaderOptions
											error:&pError];
	if (pError != nil) {
		NSLog(@"Error creating texture %@", pError.localizedDescription);
		result = YN_SET_ERR(@"Metal API error.", 0, 0);
		goto EXIT;
	}
	
EXIT:;
	[pTextureLoader release];
	return result;
}

//******************************************************************************
// 破棄
//******************************************************************************
void OGLTexture::Release()
{
	if (m_Texture != nil) {
		[m_Texture release];
		m_Texture = nil;
	}
	m_Width = 0;
	m_Height = 0;
	
	return;
}

//******************************************************************************
// テクスチャサイズ取得：幅
//******************************************************************************
OGLsizei OGLTexture::GetWidth()
{
	return m_Width;
}

//******************************************************************************
// テクスチャサイズ取得：高さ
//******************************************************************************
OGLsizei OGLTexture::GetHeight()
{
	return m_Height;
}

//******************************************************************************
// テクスチャ描画開始処理
//******************************************************************************
void OGLTexture::BindTexture(
		OGLDevice* pOGLDevice,
		NSUInteger textureIndex
	)
{
	id <MTLRenderCommandEncoder> commandEncoder = nil;
	
	if (m_Texture != nil) {
		//エンコーダにテクスチャ登録
		m_TextureIndex = textureIndex;
		commandEncoder = pOGLDevice->GetCurrentCommandEncoder();
		[commandEncoder setFragmentTexture:m_Texture
								   atIndex:m_TextureIndex];
	}
	
	return;
}

//******************************************************************************
// テクスチャ描画終了処理
//******************************************************************************
void OGLTexture::UnbindTexture(OGLDevice* pDevice)
{
	id <MTLRenderCommandEncoder> commandEncoder = nil;
	
	//テクスチャ無効化
	commandEncoder = pDevice->GetCurrentCommandEncoder();
	[commandEncoder setFragmentTexture:nil
							   atIndex:m_TextureIndex];
	
	return;
}


