1 // Copyright (C) 2003 Dolphin Project.
3 // This program is free software: you can redistribute it and/or modify
4 // it under the terms of the GNU General Public License as published by
5 // the Free Software Foundation, version 2.0.
7 // This program is distributed in the hope that it will be useful,
8 // but WITHOUT ANY WARRANTY; without even the implied warranty of
9 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 // GNU General Public License 2.0 for more details.
12 // A copy of the GPL 2.0 should have been included with the program.
13 // If not, see http://www.gnu.org/licenses/
15 // Official SVN repository and contact information can be found at
16 // http://code.google.com/p/dolphin-emu/
20 #include "D3DTexture.h"
25 // buffers for storing the data for DEFAULT textures
27 unsigned int texbufsize
= 0;
29 // TODO: Remove this class and properly clean up texbuf!
34 SAFE_DELETE_ARRAY(texbuf
);
39 void ReplaceTexture2D(ID3D11Texture2D
* pTexture
, const u8
* buffer
, unsigned int width
, unsigned int height
, unsigned int pitch
, DXGI_FORMAT fmt
, PC_TexFormat pcfmt
, unsigned int level
, D3D11_USAGE usage
)
42 unsigned int destPitch
;
45 if (usage
== D3D11_USAGE_DYNAMIC
|| usage
== D3D11_USAGE_STAGING
)
47 if (usage
== D3D11_USAGE_DYNAMIC
&& level
!= 0) PanicAlert("Dynamic textures don't support mipmaps, but given level is not 0 at %s %d\n", __FILE__
, __LINE__
);
48 D3D11_MAPPED_SUBRESOURCE map
;
49 D3D::context
->Map(pTexture
, 0, D3D11_MAP_WRITE_DISCARD
, 0, &map
);
50 outptr
= (u8
*)map
.pData
;
51 destPitch
= map
.RowPitch
;
53 else if (usage
== D3D11_USAGE_DEFAULT
&& pcfmt
!= PC_TEX_FMT_BGRA32
)
55 if (texbufsize
< 4*width
*height
)
57 SAFE_DELETE_ARRAY(texbuf
);
58 texbuf
= new u8
[4*width
*height
];
59 texbufsize
= 4*width
*height
;
62 destPitch
= width
* 4;
64 else if (usage
== D3D11_USAGE_DEFAULT
&& pcfmt
== PC_TEX_FMT_BGRA32
)
66 // BGRA32 textures can be uploaded directly to VRAM in this case
67 D3D11_BOX dest_region
= CD3D11_BOX(0, 0, 0, width
, height
, 1);
68 D3D::context
->UpdateSubresource(pTexture
, level
, &dest_region
, buffer
, 4*pitch
, 4*pitch
*height
);
73 PanicAlert("ReplaceTexture2D called on an immutable texture!\n");
77 // TODO: Merge the conversions done here to VideoDecoder
81 case PC_TEX_FMT_IA4_AS_IA8
:
82 for (unsigned int y
= 0; y
< height
; y
++)
84 u16
* in
= (u16
*)buffer
+ y
* pitch
;
85 u32
* pBits
= (u32
*)(outptr
+ y
* destPitch
);
86 for (unsigned int x
= 0; x
< width
; x
++)
88 const u8 I
= (*in
& 0xFF);
89 const u8 A
= (*in
& 0xFF00) >> 8;
90 *pBits
++ = (A
<< 24) | (I
<< 16) | (I
<< 8) | I
;
96 case PC_TEX_FMT_I4_AS_I8
:
97 for (unsigned int y
= 0; y
< height
; y
++)
99 const u8
* in
= buffer
+ y
* pitch
;
100 u32
* pBits
= (u32
*)(outptr
+ y
* destPitch
);
101 for(unsigned int i
= 0; i
< width
; i
++)
102 memset( pBits
++, *in
++, 4 );
105 case PC_TEX_FMT_BGRA32
:
106 for (unsigned int y
= 0; y
< height
; y
++)
107 memcpy( outptr
+ y
* destPitch
, (u32
*)buffer
+ y
* pitch
, destPitch
);
110 case PC_TEX_FMT_RGB565
:
111 for (unsigned int y
= 0; y
< height
; y
++)
113 u16
* in
= (u16
*)buffer
+ y
* pitch
;
114 u32
* pBits
= (u32
*)(outptr
+ y
* destPitch
);
115 for (unsigned int x
= 0; x
< width
; x
++)
117 // we can't simply shift here, since e.g. 11111 must map to 11111111 and not 11111000
118 const u16 col
= *in
++;
119 *(pBits
++) = 0xFF000000 | // alpha
120 ((((col
&0xF800) << 5) * 255 / 31) & 0xFF0000) | // red
121 ((((col
& 0x7e0) << 3) * 255 / 63) & 0xFF00) | // green
122 (( (col
& 0x1f) * 255 / 31)); // blue
127 PanicAlert("Unknown tex fmt %d\n", pcfmt
);
130 if (usage
== D3D11_USAGE_DYNAMIC
)
132 // TODO: UpdateSubresource might be faster than mapping
133 D3D::context
->Unmap(pTexture
, 0);
135 else if (usage
== D3D11_USAGE_DEFAULT
)
137 D3D11_BOX dest_region
= CD3D11_BOX(0, 0, 0, width
, height
, 1);
138 D3D::context
->UpdateSubresource(pTexture
, level
, &dest_region
, outptr
, destPitch
, 4*width
*height
);
144 D3DTexture2D
* D3DTexture2D::Create(unsigned int width
, unsigned int height
, D3D11_BIND_FLAG bind
, D3D11_USAGE usage
, DXGI_FORMAT fmt
, unsigned int levels
)
146 ID3D11Texture2D
* pTexture
= NULL
;
149 D3D11_CPU_ACCESS_FLAG cpuflags
;
150 if (usage
== D3D11_USAGE_STAGING
) cpuflags
= (D3D11_CPU_ACCESS_FLAG
)((int)D3D11_CPU_ACCESS_WRITE
|(int)D3D11_CPU_ACCESS_READ
);
151 else if (usage
== D3D11_USAGE_DYNAMIC
) cpuflags
= D3D11_CPU_ACCESS_WRITE
;
152 else cpuflags
= (D3D11_CPU_ACCESS_FLAG
)0;
153 D3D11_TEXTURE2D_DESC texdesc
= CD3D11_TEXTURE2D_DESC(fmt
, width
, height
, 1, levels
, bind
, usage
, cpuflags
);
154 hr
= D3D::device
->CreateTexture2D(&texdesc
, NULL
, &pTexture
);
157 PanicAlert("Failed to create texture at %s, line %d: hr=%#x\n", __FILE__
, __LINE__
, hr
);
161 D3DTexture2D
* ret
= new D3DTexture2D(pTexture
, bind
);
166 void D3DTexture2D::AddRef()
171 UINT
D3DTexture2D::Release()
182 ID3D11Texture2D
* &D3DTexture2D::GetTex() { return tex
; }
183 ID3D11ShaderResourceView
* &D3DTexture2D::GetSRV() { return srv
; }
184 ID3D11RenderTargetView
* &D3DTexture2D::GetRTV() { return rtv
; }
185 ID3D11DepthStencilView
* &D3DTexture2D::GetDSV() { return dsv
; }
187 D3DTexture2D::D3DTexture2D(ID3D11Texture2D
* texptr
, D3D11_BIND_FLAG bind
,
188 DXGI_FORMAT srv_format
, DXGI_FORMAT dsv_format
, DXGI_FORMAT rtv_format
)
189 : ref(1), tex(texptr
), srv(NULL
), rtv(NULL
), dsv(NULL
)
191 D3D11_SHADER_RESOURCE_VIEW_DESC srv_desc
= CD3D11_SHADER_RESOURCE_VIEW_DESC(D3D11_SRV_DIMENSION_TEXTURE2D
, srv_format
);
192 D3D11_DEPTH_STENCIL_VIEW_DESC dsv_desc
= CD3D11_DEPTH_STENCIL_VIEW_DESC(D3D11_DSV_DIMENSION_TEXTURE2D
, dsv_format
);
193 D3D11_RENDER_TARGET_VIEW_DESC rtv_desc
= CD3D11_RENDER_TARGET_VIEW_DESC(D3D11_RTV_DIMENSION_TEXTURE2D
, rtv_format
);
194 if (bind
& D3D11_BIND_SHADER_RESOURCE
) D3D::device
->CreateShaderResourceView(tex
, &srv_desc
, &srv
);
195 if (bind
& D3D11_BIND_RENDER_TARGET
) D3D::device
->CreateRenderTargetView(tex
, &rtv_desc
, &rtv
);
196 if (bind
& D3D11_BIND_DEPTH_STENCIL
) D3D::device
->CreateDepthStencilView(tex
, &dsv_desc
, &dsv
);
200 D3DTexture2D::~D3DTexture2D()
202 if (srv
) srv
->Release();
203 if (rtv
) rtv
->Release();
204 if (dsv
) dsv
->Release();