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/
22 #include "D3DTexture.h"
24 #include "PixelShaderCache.h"
25 #include "VertexShaderCache.h"
26 #include "D3DShader.h"
33 #define MAX_NUM_VERTICES 50*6
40 inline FONT2DVERTEX
InitFont2DVertex(float x
, float y
, u32 color
, float tu
, float tv
)
42 FONT2DVERTEX v
; v
.x
=x
; v
.y
=y
; v
.z
=0; v
.tu
= tu
; v
.tv
= tv
;
43 v
.col
[0] = ((float)((color
>> 16) & 0xFF)) / 255.f
;
44 v
.col
[1] = ((float)((color
>> 8) & 0xFF)) / 255.f
;
45 v
.col
[2] = ((float)((color
>> 0) & 0xFF)) / 255.f
;
46 v
.col
[3] = ((float)((color
>> 24) & 0xFF)) / 255.f
;
50 CD3DFont::CD3DFont() : m_dwTexWidth(512), m_dwTexHeight(512)
59 const char fontpixshader
[] = {
61 "SamplerState linearSampler\n"
63 " Filter = MIN_MAG_MIP_LINEAR;\n"
64 " AddressU = D3D11_TEXTURE_ADDRESS_BORDER;\n"
65 " AddressV = D3D11_TEXTURE_ADDRESS_BORDER;\n"
66 " BorderColor = float4(0.f, 0.f, 0.f, 0.f);\n"
70 " float4 pos : SV_POSITION;\n"
71 " float4 col : COLOR;\n"
72 " float2 tex : TEXCOORD;\n"
74 "float4 main( PS_INPUT input ) : SV_Target\n"
76 " return tex2D.Sample( linearSampler, input.tex ) * input.col;\n"
80 const char fontvertshader
[] = {
83 " float4 pos : POSITION;\n"
84 " float4 col : COLOR;\n"
85 " float2 tex : TEXCOORD;\n"
89 " float4 pos : SV_POSITION;\n"
90 " float4 col : COLOR;\n"
91 " float2 tex : TEXCOORD;\n"
93 "PS_INPUT main( VS_INPUT input )\n"
96 " output.pos = input.pos;\n"
97 " output.col = input.col;\n"
98 " output.tex = input.tex;\n"
105 // Create vertex buffer for the letters
108 // Prepare to create a bitmap
109 unsigned int* pBitmapBits
;
111 ZeroMemory(&bmi
.bmiHeader
, sizeof(BITMAPINFOHEADER
));
112 bmi
.bmiHeader
.biSize
= sizeof(BITMAPINFOHEADER
);
113 bmi
.bmiHeader
.biWidth
= (int)m_dwTexWidth
;
114 bmi
.bmiHeader
.biHeight
= -(int)m_dwTexHeight
;
115 bmi
.bmiHeader
.biPlanes
= 1;
116 bmi
.bmiHeader
.biCompression
= BI_RGB
;
117 bmi
.bmiHeader
.biBitCount
= 32;
119 // Create a DC and a bitmap for the font
120 HDC hDC
= CreateCompatibleDC(NULL
);
121 HBITMAP hbmBitmap
= CreateDIBSection(hDC
, &bmi
, DIB_RGB_COLORS
, (void**)&pBitmapBits
, NULL
, 0);
122 SetMapMode(hDC
, MM_TEXT
);
125 HFONT hFont
= CreateFont(24, 0, 0, 0, FW_NORMAL
, FALSE
,
126 FALSE
, FALSE
, DEFAULT_CHARSET
, OUT_DEFAULT_PRECIS
,
127 CLIP_DEFAULT_PRECIS
, PROOF_QUALITY
,
128 VARIABLE_PITCH
, _T("Tahoma"));
129 if (NULL
== hFont
) return E_FAIL
;
131 HGDIOBJ hOldbmBitmap
= SelectObject(hDC
, hbmBitmap
);
132 HGDIOBJ hOldFont
= SelectObject(hDC
, hFont
);
134 // Set text properties
135 SetTextColor(hDC
, 0xFFFFFF);
137 SetTextAlign(hDC
, TA_TOP
);
140 GetTextMetricsW(hDC
, &tm
);
141 m_LineHeight
= tm
.tmHeight
;
143 // Loop through all printable characters and output them to the bitmap
144 // Meanwhile, keep track of the corresponding tex coords for each character.
147 for (int c
= 0; c
< 127 - 32; c
++)
151 GetTextExtentPoint32A(hDC
, str
, 1, &size
);
152 if ((int)(x
+size
.cx
+1) > m_dwTexWidth
)
158 ExtTextOutA(hDC
, x
+1, y
+0, ETO_OPAQUE
| ETO_CLIPPED
, NULL
, str
, 1, NULL
);
159 m_fTexCoords
[c
][0] = ((float)(x
+0))/m_dwTexWidth
;
160 m_fTexCoords
[c
][1] = ((float)(y
+0))/m_dwTexHeight
;
161 m_fTexCoords
[c
][2] = ((float)(x
+0+size
.cx
))/m_dwTexWidth
;
162 m_fTexCoords
[c
][3] = ((float)(y
+0+size
.cy
))/m_dwTexHeight
;
164 x
+= size
.cx
+ 3; // 3 to work around annoying ij conflict (part of the j ends up with the i)
167 // Create a new texture for the font
168 // possible optimization: store the converted data in a buffer and fill the texture on creation.
169 // That way, we can use a static texture
170 ID3D11Texture2D
* buftex
;
171 D3D11_TEXTURE2D_DESC texdesc
= CD3D11_TEXTURE2D_DESC(DXGI_FORMAT_R8G8B8A8_UNORM
, m_dwTexWidth
, m_dwTexHeight
,
172 1, 1, D3D11_BIND_SHADER_RESOURCE
, D3D11_USAGE_DYNAMIC
,
173 D3D11_CPU_ACCESS_WRITE
);
174 hr
= device
->CreateTexture2D(&texdesc
, NULL
, &buftex
);
177 PanicAlert("Failed to create font texture");
180 D3D::SetDebugObjectName((ID3D11DeviceChild
*)buftex
, "texture of a CD3DFont object");
182 // Lock the surface and write the alpha values for the set pixels
183 D3D11_MAPPED_SUBRESOURCE texmap
;
184 hr
= context
->Map(buftex
, 0, D3D11_MAP_WRITE_DISCARD
, 0, &texmap
);
185 if (FAILED(hr
)) PanicAlert("Failed to map a texture at %s %d\n", __FILE__
, __LINE__
);
187 for (y
= 0; y
< m_dwTexHeight
; y
++)
189 u32
* pDst32
= (u32
*)((u8
*)texmap
.pData
+ y
* texmap
.RowPitch
);
190 for (x
= 0; x
< m_dwTexWidth
; x
++)
192 const u8 bAlpha
= (pBitmapBits
[m_dwTexWidth
* y
+ x
] & 0xff);
193 *pDst32
++ = (((bAlpha
<< 4) | bAlpha
) << 24) | 0xFFFFFF;
197 // Done updating texture, so clean up used objects
198 context
->Unmap(buftex
, 0);
199 hr
= D3D::device
->CreateShaderResourceView(buftex
, NULL
, &m_pTexture
);
200 if (FAILED(hr
)) PanicAlert("Failed to create shader resource view at %s %d\n", __FILE__
, __LINE__
);
201 SAFE_RELEASE(buftex
);
203 SelectObject(hDC
, hOldbmBitmap
);
204 DeleteObject(hbmBitmap
);
206 SelectObject(hDC
, hOldFont
);
209 // setup device objects for drawing
210 m_pshader
= D3D::CompileAndCreatePixelShader(fontpixshader
, sizeof(fontpixshader
));
211 if (m_pshader
== NULL
) PanicAlert("Failed to create pixel shader, %s %d\n", __FILE__
, __LINE__
);
212 D3D::SetDebugObjectName((ID3D11DeviceChild
*)m_pshader
, "pixel shader of a CD3DFont object");
215 D3D::CompileVertexShader(fontvertshader
, sizeof(fontvertshader
), &vsbytecode
);
216 if (vsbytecode
== NULL
) PanicAlert("Failed to compile vertex shader, %s %d\n", __FILE__
, __LINE__
);
217 m_vshader
= D3D::CreateVertexShaderFromByteCode(vsbytecode
);
218 if (m_vshader
== NULL
) PanicAlert("Failed to create vertex shader, %s %d\n", __FILE__
, __LINE__
);
219 D3D::SetDebugObjectName((ID3D11DeviceChild
*)m_vshader
, "vertex shader of a CD3DFont object");
221 const D3D11_INPUT_ELEMENT_DESC desc
[] =
223 { "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT
, 0, 0, D3D11_INPUT_PER_VERTEX_DATA
, 0 },
224 { "COLOR", 0, DXGI_FORMAT_R32G32B32A32_FLOAT
, 0, 12, D3D11_INPUT_PER_VERTEX_DATA
, 0 },
225 { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT
, 0, 28, D3D11_INPUT_PER_VERTEX_DATA
, 0 },
227 hr
= D3D::device
->CreateInputLayout(desc
, 3, vsbytecode
->Data(), vsbytecode
->Size(), &m_InputLayout
);
228 if (FAILED(hr
)) PanicAlert("Failed to create input layout, %s %d\n", __FILE__
, __LINE__
);
229 SAFE_RELEASE(vsbytecode
);
231 D3D11_BLEND_DESC blenddesc
;
232 blenddesc
.AlphaToCoverageEnable
= FALSE
;
233 blenddesc
.IndependentBlendEnable
= FALSE
;
234 blenddesc
.RenderTarget
[0].BlendEnable
= TRUE
;
235 blenddesc
.RenderTarget
[0].RenderTargetWriteMask
= D3D11_COLOR_WRITE_ENABLE_ALL
;
236 blenddesc
.RenderTarget
[0].SrcBlend
= D3D11_BLEND_SRC_ALPHA
;
237 blenddesc
.RenderTarget
[0].DestBlend
= D3D11_BLEND_INV_SRC_ALPHA
;
238 blenddesc
.RenderTarget
[0].BlendOp
= D3D11_BLEND_OP_ADD
;
239 blenddesc
.RenderTarget
[0].SrcBlendAlpha
= D3D11_BLEND_SRC_ALPHA
;
240 blenddesc
.RenderTarget
[0].DestBlendAlpha
= D3D11_BLEND_INV_SRC_ALPHA
;
241 blenddesc
.RenderTarget
[0].BlendOpAlpha
= D3D11_BLEND_OP_ADD
;
242 hr
= D3D::device
->CreateBlendState(&blenddesc
, &m_blendstate
);
243 CHECK(hr
==S_OK
, "Create font blend state");
244 D3D::SetDebugObjectName((ID3D11DeviceChild
*)m_blendstate
, "blend state of a CD3DFont object");
246 // this might need to be changed when adding multisampling support
247 D3D11_RASTERIZER_DESC rastdesc
= CD3D11_RASTERIZER_DESC(D3D11_FILL_SOLID
, D3D11_CULL_NONE
, false, 0, 0.f
, 0.f
, false, false, false, false);
248 hr
= D3D::device
->CreateRasterizerState(&rastdesc
, &m_raststate
);
249 CHECK(hr
==S_OK
, "Create font rasterizer state");
250 D3D::SetDebugObjectName((ID3D11DeviceChild
*)m_raststate
, "rasterizer state of a CD3DFont object");
252 D3D11_BUFFER_DESC vbdesc
= CD3D11_BUFFER_DESC(MAX_NUM_VERTICES
*sizeof(FONT2DVERTEX
), D3D11_BIND_VERTEX_BUFFER
, D3D11_USAGE_DYNAMIC
, D3D11_CPU_ACCESS_WRITE
);
253 if (FAILED(hr
= device
->CreateBuffer(&vbdesc
, NULL
, &m_pVB
)))
255 PanicAlert("Failed to create font vertex buffer at %s, line %d\n", __FILE__
, __LINE__
);
258 D3D::SetDebugObjectName((ID3D11DeviceChild
*)m_pVB
, "vertex buffer of a CD3DFont object");
262 int CD3DFont::Shutdown()
265 SAFE_RELEASE(m_pTexture
);
266 SAFE_RELEASE(m_InputLayout
);
267 SAFE_RELEASE(m_pshader
);
268 SAFE_RELEASE(m_vshader
);
270 SAFE_RELEASE(m_blendstate
);
271 SAFE_RELEASE(m_raststate
);
276 int CD3DFont::DrawTextScaled(float x
, float y
, float size
, float spacing
, u32 dwColor
, const char* strText
, bool center
)
281 UINT stride
= sizeof(FONT2DVERTEX
);
284 float scalex
= 1 / (float)D3D::GetBackBufferWidth() * 2.f
;
285 float scaley
= 1 / (float)D3D::GetBackBufferHeight() * 2.f
;
286 float sizeratio
= size
/ (float)m_LineHeight
;
288 // translate starting positions
289 float sx
= x
* scalex
- 1.f
;
290 float sy
= 1.f
- y
* scaley
;
293 // Fill vertex buffer
294 FONT2DVERTEX
* pVertices
;
295 int dwNumTriangles
= 0L;
297 D3D11_MAPPED_SUBRESOURCE vbmap
;
298 HRESULT hr
= context
->Map(m_pVB
, 0, D3D11_MAP_WRITE_DISCARD
, 0, &vbmap
);
299 if (FAILED(hr
)) PanicAlert("Mapping vertex buffer failed, %s %d\n", __FILE__
, __LINE__
);
300 pVertices
= (D3D::FONT2DVERTEX
*)vbmap
.pData
;
302 // if center was requested, set current position as centre
303 // this is currently never used
306 const char *oldText
= strText
;
310 while (c
= *strText
++)
312 if (c
== ('\n')) mx
= 0;
313 if (c
< (' ') ) continue;
315 mx
+= (m_fTexCoords
[c
][2]-m_fTexCoords
[c
][0])/(m_fTexCoords
[0][3] - m_fTexCoords
[0][1]) + spacing
;
316 if (mx
> maxx
) maxx
= mx
;
318 sx
-= scalex
*maxx
*size
;
321 // set general pipeline state
322 D3D::stateman
->PushBlendState(m_blendstate
);
323 D3D::stateman
->PushRasterizerState(m_raststate
);
324 D3D::stateman
->Apply();
326 D3D::context
->PSSetShader(m_pshader
, NULL
, 0);
327 D3D::context
->VSSetShader(m_vshader
, NULL
, 0);
329 D3D::context
->IASetInputLayout(m_InputLayout
);
330 D3D::context
->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST
);
331 D3D::context
->PSSetShaderResources(0, 1, &m_pTexture
);
334 while (c
= *strText
++)
345 float tx1
= m_fTexCoords
[c
][0];
346 float ty1
= m_fTexCoords
[c
][1];
347 float tx2
= m_fTexCoords
[c
][2];
348 float ty2
= m_fTexCoords
[c
][3];
350 float w
= (float)(tx2
-tx1
) * m_dwTexWidth
* scalex
* sizeratio
;
351 float h
= (float)(ty1
-ty2
) * m_dwTexHeight
* scaley
* sizeratio
;
354 v
[0] = InitFont2DVertex(sx
, sy
+h
, dwColor
, tx1
, ty2
);
355 v
[1] = InitFont2DVertex(sx
, sy
, dwColor
, tx1
, ty1
);
356 v
[2] = InitFont2DVertex(sx
+w
, sy
+h
, dwColor
, tx2
, ty2
);
357 v
[3] = InitFont2DVertex(sx
+w
, sy
, dwColor
, tx2
, ty1
);
361 memcpy(pVertices
, v
, 6*sizeof(FONT2DVERTEX
));
366 if (dwNumTriangles
* 3 > (MAX_NUM_VERTICES
- 6))
368 context
->Unmap(m_pVB
, 0);
370 D3D::context
->IASetVertexBuffers(0, 1, &m_pVB
, &stride
, &bufoffset
);
371 D3D::context
->Draw(3 * dwNumTriangles
, 0);
374 D3D11_MAPPED_SUBRESOURCE vbmap
;
375 hr
= context
->Map(m_pVB
, 0, D3D11_MAP_WRITE_DISCARD
, 0, &vbmap
);
376 if (FAILED(hr
)) PanicAlert("Mapping vertex buffer failed, %s %d\n", __FILE__
, __LINE__
);
377 pVertices
= (D3D::FONT2DVERTEX
*)vbmap
.pData
;
379 sx
+= w
+ spacing
* scalex
* size
;
382 // Unlock and render the vertex buffer
383 context
->Unmap(m_pVB
, 0);
384 if (dwNumTriangles
> 0)
386 D3D::context
->IASetVertexBuffers(0, 1, &m_pVB
, &stride
, &bufoffset
);
387 D3D::context
->Draw(3 * dwNumTriangles
, 0);
389 D3D::stateman
->PopBlendState();
390 D3D::stateman
->PopRasterizerState();
394 ID3D11Buffer
* CreateQuadVertexBuffer(unsigned int size
, void* data
, D3D11_USAGE usage
= D3D11_USAGE_DYNAMIC
)
397 D3D11_BUFFER_DESC vbdesc
;
398 vbdesc
.BindFlags
= D3D11_BIND_VERTEX_BUFFER
;
399 vbdesc
.ByteWidth
= size
;
400 vbdesc
.MiscFlags
= 0;
401 vbdesc
.Usage
= usage
;
404 case D3D11_USAGE_DEFAULT
:
405 case D3D11_USAGE_IMMUTABLE
:
406 vbdesc
.CPUAccessFlags
= 0;
409 case D3D11_USAGE_DYNAMIC
:
410 vbdesc
.CPUAccessFlags
= D3D11_CPU_ACCESS_WRITE
;
413 case D3D11_USAGE_STAGING
:
414 vbdesc
.CPUAccessFlags
= D3D11_CPU_ACCESS_WRITE
|D3D11_CPU_ACCESS_READ
;
419 D3D11_SUBRESOURCE_DATA bufdata
;
420 bufdata
.pSysMem
= data
;
421 if (FAILED(device
->CreateBuffer(&vbdesc
, &bufdata
, &vb
))) return NULL
;
423 else if (FAILED(device
->CreateBuffer(&vbdesc
, NULL
, &vb
))) return NULL
;
428 ID3D11SamplerState
* linear_copy_sampler
= NULL
;
429 ID3D11SamplerState
* point_copy_sampler
= NULL
;
430 ID3D11Buffer
* stqvb
= NULL
;
431 ID3D11Buffer
* stsqvb
= NULL
;
432 ID3D11Buffer
* quadvb
= NULL
;
433 ID3D11Buffer
* clearvb
= NULL
;
435 typedef struct { float x
,y
,z
,u
,v
; } STQVertex
;
436 typedef struct { float x
,y
,z
,u
,v
; } STSQVertex
;
437 typedef struct { float x
,y
,z
; u32 col
; } ClearVertex
;
438 typedef struct { float x
,y
,z
; u32 col
; } ColVertex
;
442 float u1
, v1
, u2
, v2
;
447 MathUtil::Rectangle
<float> rdest
;
448 float u1
, v1
, u2
, v2
;
453 float x1
, y1
, x2
, y2
;
465 float border
[4] = { 0.f
, 0.f
, 0.f
, 0.f
};
466 D3D11_SAMPLER_DESC samDesc
= CD3D11_SAMPLER_DESC(D3D11_FILTER_MIN_MAG_MIP_POINT
, D3D11_TEXTURE_ADDRESS_BORDER
, D3D11_TEXTURE_ADDRESS_BORDER
, D3D11_TEXTURE_ADDRESS_BORDER
, 0.f
, 1, D3D11_COMPARISON_ALWAYS
, border
, -D3D11_FLOAT32_MAX
, D3D11_FLOAT32_MAX
);
467 HRESULT hr
= D3D::device
->CreateSamplerState(&samDesc
, &point_copy_sampler
);
468 if (FAILED(hr
)) PanicAlert("Failed to create sampler state at %s %d\n", __FILE__
, __LINE__
);
469 else SetDebugObjectName((ID3D11DeviceChild
*)point_copy_sampler
, "point copy sampler state");
471 samDesc
= CD3D11_SAMPLER_DESC(D3D11_FILTER_MIN_MAG_MIP_LINEAR
, D3D11_TEXTURE_ADDRESS_BORDER
, D3D11_TEXTURE_ADDRESS_BORDER
, D3D11_TEXTURE_ADDRESS_BORDER
, 0.f
, 1, D3D11_COMPARISON_ALWAYS
, border
, -D3D11_FLOAT32_MAX
, D3D11_FLOAT32_MAX
);
472 hr
= D3D::device
->CreateSamplerState(&samDesc
, &linear_copy_sampler
);
473 if (FAILED(hr
)) PanicAlert("Failed to create sampler state at %s %d\n", __FILE__
, __LINE__
);
474 else SetDebugObjectName((ID3D11DeviceChild
*)linear_copy_sampler
, "linear copy sampler state");
476 // cached data used to avoid unnecessarily reloading the vertex buffers
477 memset(&tex_quad_data
, 0, sizeof(tex_quad_data
));
478 memset(&tex_sub_quad_data
, 0, sizeof(tex_sub_quad_data
));
479 memset(&draw_quad_data
, 0, sizeof(draw_quad_data
));
480 memset(&clear_quad_data
, 0, sizeof(clear_quad_data
));
482 STQVertex stqcoords
[4] = {
483 {-1.0f
, 1.0f
, 0.0f
, 0, 0},
484 { 1.0f
, 1.0f
, 0.0f
, 0, 0},
485 {-1.0f
,-1.0f
, 0.0f
, 0, 0},
486 { 1.0f
,-1.0f
, 0.0f
, 0, 0},
489 STSQVertex stsqcoords
[4];
490 memset(stsqcoords
, 0, sizeof(stsqcoords
));
492 ColVertex colcoords
[4];
493 memset(colcoords
, 0, sizeof(colcoords
));
495 ClearVertex cqcoords
[4] = {
498 {-1.0f
, -1.0f
, 0, 0},
499 { 1.0f
, -1.0f
, 0, 0},
502 stqvb
= CreateQuadVertexBuffer(4*sizeof(STQVertex
), stqcoords
);
503 CHECK(stqvb
!=NULL
, "Create vertex buffer of drawShadedTexQuad");
504 SetDebugObjectName((ID3D11DeviceChild
*)stqvb
, "vertex buffer of drawShadedTexQuad");
506 stsqvb
= CreateQuadVertexBuffer(4*sizeof(STSQVertex
), stsqcoords
);
507 CHECK(stsqvb
!=NULL
, "Create vertex buffer of drawShadedTexSubQuad");
508 SetDebugObjectName((ID3D11DeviceChild
*)stsqvb
, "vertex buffer of drawShadedTexSubQuad");
510 quadvb
= CreateQuadVertexBuffer(4*sizeof(ColVertex
), colcoords
);
511 CHECK(quadvb
!=NULL
, "Create vertex buffer of drawColorQuad");
512 SetDebugObjectName((ID3D11DeviceChild
*)quadvb
, "vertex buffer of drawColorQuad");
514 clearvb
= CreateQuadVertexBuffer(4*sizeof(ClearVertex
), cqcoords
);
515 CHECK(clearvb
!=NULL
, "Create vertex buffer of drawClearQuad");
516 SetDebugObjectName((ID3D11DeviceChild
*)clearvb
, "vertex buffer of drawClearQuad");
524 SAFE_RELEASE(point_copy_sampler
);
525 SAFE_RELEASE(linear_copy_sampler
);
527 SAFE_RELEASE(stsqvb
);
528 SAFE_RELEASE(quadvb
);
529 SAFE_RELEASE(clearvb
);
532 void SetPointCopySampler()
534 D3D::context
->PSSetSamplers(0, 1, &point_copy_sampler
);
537 void SetLinearCopySampler()
539 D3D::context
->PSSetSamplers(0, 1, &linear_copy_sampler
);
542 void drawShadedTexQuad(ID3D11ShaderResourceView
* texture
,
543 const D3D11_RECT
* rSource
,
546 ID3D11PixelShader
* PShader
,
547 ID3D11VertexShader
* Vshader
,
548 ID3D11InputLayout
* layout
)
550 float sw
= 1.0f
/(float) SourceWidth
;
551 float sh
= 1.0f
/(float) SourceHeight
;
552 float u1
= ((float)rSource
->left
) * sw
;
553 float u2
= ((float)rSource
->right
) * sw
;
554 float v1
= ((float)rSource
->top
) * sh
;
555 float v2
= ((float)rSource
->bottom
) * sh
;
557 STQVertex coords
[4] = {
558 {-1.0f
, 1.0f
, 0.0f
, u1
, v1
},
559 { 1.0f
, 1.0f
, 0.0f
, u2
, v1
},
560 {-1.0f
,-1.0f
, 0.0f
, u1
, v2
},
561 { 1.0f
,-1.0f
, 0.0f
, u2
, v2
},
564 // only upload the data to VRAM if it changed
565 if (tex_quad_data
.u1
!= u1
|| tex_quad_data
.v1
!= v1
||
566 tex_quad_data
.u2
!= u2
|| tex_quad_data
.v2
!= v2
)
568 D3D11_MAPPED_SUBRESOURCE map
;
569 D3D::context
->Map(stqvb
, 0, D3D11_MAP_WRITE_DISCARD
, 0, &map
);
570 memcpy(map
.pData
, coords
, sizeof(coords
));
571 D3D::context
->Unmap(stqvb
, 0);
572 tex_quad_data
.u1
= u1
;
573 tex_quad_data
.v1
= v1
;
574 tex_quad_data
.u2
= u2
;
575 tex_quad_data
.v2
= v2
;
577 UINT stride
= sizeof(STQVertex
);
580 D3D::context
->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP
);
581 D3D::context
->IASetInputLayout(layout
);
582 D3D::context
->IASetVertexBuffers(0, 1, &stqvb
, &stride
, &offset
);
583 D3D::context
->PSSetShader(PShader
, NULL
, 0);
584 D3D::context
->PSSetShaderResources(0, 1, &texture
);
585 D3D::context
->VSSetShader(Vshader
, NULL
, 0);
586 D3D::stateman
->Apply();
587 D3D::context
->Draw(4, 0);
589 ID3D11ShaderResourceView
* texres
= NULL
;
590 context
->PSSetShaderResources(0, 1, &texres
); // immediately unbind the texture
593 void drawShadedTexSubQuad(ID3D11ShaderResourceView
* texture
,
594 const MathUtil::Rectangle
<float>* rSource
,
597 const MathUtil::Rectangle
<float>* rDest
,
598 ID3D11PixelShader
* PShader
,
599 ID3D11VertexShader
* Vshader
,
600 ID3D11InputLayout
* layout
)
602 float sw
= 1.0f
/(float) SourceWidth
;
603 float sh
= 1.0f
/(float) SourceHeight
;
604 float u1
= (rSource
->left
) * sw
;
605 float u2
= (rSource
->right
) * sw
;
606 float v1
= (rSource
->top
) * sh
;
607 float v2
= (rSource
->bottom
) * sh
;
609 STSQVertex coords
[4] = {
610 { rDest
->left
, rDest
->bottom
, 0.0f
, u1
, v1
},
611 { rDest
->right
, rDest
->bottom
, 0.0f
, u2
, v1
},
612 { rDest
->left
, rDest
->top
, 0.0f
, u1
, v2
},
613 { rDest
->right
, rDest
->top
, 0.0f
, u2
, v2
},
616 // only upload the data to VRAM if it changed
617 if (memcmp(rDest
, &tex_sub_quad_data
.rdest
, sizeof(rDest
)) != 0 ||
618 tex_sub_quad_data
.u1
!= u1
|| tex_sub_quad_data
.v1
!= v1
||
619 tex_sub_quad_data
.u2
!= u2
|| tex_sub_quad_data
.v2
!= v2
)
621 D3D11_MAPPED_SUBRESOURCE map
;
622 D3D::context
->Map(stsqvb
, 0, D3D11_MAP_WRITE_DISCARD
, 0, &map
);
623 memcpy(map
.pData
, coords
, sizeof(coords
));
624 D3D::context
->Unmap(stsqvb
, 0);
625 tex_sub_quad_data
.u1
= u1
;
626 tex_sub_quad_data
.v1
= v1
;
627 tex_sub_quad_data
.u2
= u2
;
628 tex_sub_quad_data
.v2
= v2
;
629 memcpy(&tex_sub_quad_data
.rdest
, &rDest
, sizeof(rDest
));
631 UINT stride
= sizeof(STSQVertex
);
634 context
->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP
);
635 context
->IASetVertexBuffers(0, 1, &stsqvb
, &stride
, &offset
);
636 context
->IASetInputLayout(layout
);
637 context
->PSSetShaderResources(0, 1, &texture
);
638 context
->PSSetShader(PShader
, NULL
, 0);
639 context
->VSSetShader(Vshader
, NULL
, 0);
643 ID3D11ShaderResourceView
* texres
= NULL
;
644 context
->PSSetShaderResources(0, 1, &texres
); // immediately unbind the texture
647 // Fills a certain area of the current render target with the specified color
648 // destination coordinates normalized to (-1;1)
649 void drawColorQuad(u32 Color
, float x1
, float y1
, float x2
, float y2
)
651 if(draw_quad_data
.x1
!= x1
|| draw_quad_data
.y1
!= y1
||
652 draw_quad_data
.x2
!= x2
|| draw_quad_data
.y2
!= y2
||
653 draw_quad_data
.col
!= Color
)
655 ColVertex coords
[4] = {
656 { x1
, y2
, 0.f
, Color
},
657 { x2
, y2
, 0.f
, Color
},
658 { x1
, y1
, 0.f
, Color
},
659 { x2
, y1
, 0.f
, Color
},
662 D3D11_MAPPED_SUBRESOURCE map
;
663 context
->Map(quadvb
, 0, D3D11_MAP_WRITE_DISCARD
, 0, &map
);
664 memcpy(map
.pData
, coords
, sizeof(coords
));
665 context
->Unmap(quadvb
, 0);
667 draw_quad_data
.x1
= x1
;
668 draw_quad_data
.y1
= y1
;
669 draw_quad_data
.x2
= x2
;
670 draw_quad_data
.y2
= y2
;
671 draw_quad_data
.col
= Color
;
674 context
->VSSetShader(VertexShaderCache::GetClearVertexShader(), NULL
, 0);
675 context
->PSSetShader(PixelShaderCache::GetClearProgram(), NULL
, 0);
676 context
->IASetInputLayout(VertexShaderCache::GetClearInputLayout());
678 UINT stride
= sizeof(ColVertex
);
680 context
->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP
);
681 context
->IASetVertexBuffers(0, 1, &quadvb
, &stride
, &offset
);
686 void drawClearQuad(u32 Color
, float z
, ID3D11PixelShader
* PShader
, ID3D11VertexShader
* Vshader
, ID3D11InputLayout
* layout
)
688 if (clear_quad_data
.col
!= Color
|| clear_quad_data
.z
!= z
)
690 ClearVertex coords
[4] = {
691 {-1.0f
, 1.0f
, z
, Color
},
692 { 1.0f
, 1.0f
, z
, Color
},
693 {-1.0f
, -1.0f
, z
, Color
},
694 { 1.0f
, -1.0f
, z
, Color
},
697 D3D11_MAPPED_SUBRESOURCE map
;
698 context
->Map(clearvb
, 0, D3D11_MAP_WRITE_DISCARD
, 0, &map
);
699 memcpy(map
.pData
, coords
, sizeof(coords
));
700 context
->Unmap(clearvb
, 0);
701 clear_quad_data
.col
= Color
;
702 clear_quad_data
.z
= z
;
704 context
->VSSetShader(Vshader
, NULL
, 0);
705 context
->PSSetShader(PShader
, NULL
, 0);
706 context
->IASetInputLayout(layout
);
708 UINT stride
= sizeof(ClearVertex
);
710 context
->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP
);
711 context
->IASetVertexBuffers(0, 1, &clearvb
, &stride
, &offset
);