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 300
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"
69 " float4 pos : SV_POSITION;\n"
70 " float4 col : COLOR;\n"
71 " float2 tex : TEXCOORD;\n"
73 "float4 main( PS_INPUT input ) : SV_Target\n"
75 " return tex2D.Sample( linearSampler, input.tex ) * input.col;\n"
79 const char fontvertshader
[] = {
82 " float4 pos : POSITION;\n"
83 " float4 col : COLOR;\n"
84 " float2 tex : TEXCOORD;\n"
88 " float4 pos : SV_POSITION;\n"
89 " float4 col : COLOR;\n"
90 " float2 tex : TEXCOORD;\n"
92 "PS_INPUT main( VS_INPUT input )\n"
95 " output.pos = input.pos;\n"
96 " output.col = input.col;\n"
97 " output.tex = input.tex;\n"
106 // prepare to create a bitmap
107 unsigned int* pBitmapBits
;
109 ZeroMemory(&bmi
.bmiHeader
, sizeof(BITMAPINFOHEADER
));
110 bmi
.bmiHeader
.biSize
= sizeof(BITMAPINFOHEADER
);
111 bmi
.bmiHeader
.biWidth
= (int)m_dwTexWidth
;
112 bmi
.bmiHeader
.biHeight
= -(int)m_dwTexHeight
;
113 bmi
.bmiHeader
.biPlanes
= 1;
114 bmi
.bmiHeader
.biCompression
= BI_RGB
;
115 bmi
.bmiHeader
.biBitCount
= 32;
117 // create a DC and a bitmap for the font
118 HDC hDC
= CreateCompatibleDC(NULL
);
119 HBITMAP hbmBitmap
= CreateDIBSection(hDC
, &bmi
, DIB_RGB_COLORS
, (void**)&pBitmapBits
, NULL
, 0);
120 SetMapMode(hDC
, MM_TEXT
);
123 int m_dwFontHeight
= 24;
124 int nHeight
= -MulDiv(m_dwFontHeight
, (int)GetDeviceCaps(hDC
, LOGPIXELSY
), 72);
125 int dwBold
= FW_NORMAL
;
126 HFONT hFont
= CreateFont(nHeight
, 0, 0, 0, dwBold
, 0,
127 FALSE
, FALSE
, DEFAULT_CHARSET
, OUT_DEFAULT_PRECIS
,
128 CLIP_DEFAULT_PRECIS
, ANTIALIASED_QUALITY
,
129 VARIABLE_PITCH
, _T("Tahoma"));
130 if (NULL
== hFont
) return E_FAIL
;
132 HGDIOBJ hOldbmBitmap
= SelectObject(hDC
, hbmBitmap
);
133 HGDIOBJ hOldFont
= SelectObject(hDC
, hFont
);
135 // set text properties
136 SetTextColor(hDC
, 0xFFFFFF);
138 SetTextAlign(hDC
, TA_TOP
);
140 // loop through all printable characters and output them to the bitmap
141 // meanwhile, keep track of the corresponding tex coords for each character.
144 for (int c
= 0; c
< 127 - 32; c
++)
148 GetTextExtentPoint32A(hDC
, str
, 1, &size
);
149 if ((int)(x
+size
.cx
+1) > m_dwTexWidth
)
155 ExtTextOutA(hDC
, x
+1, y
+0, ETO_OPAQUE
| ETO_CLIPPED
, NULL
, str
, 1, NULL
);
156 m_fTexCoords
[c
][0] = ((float)(x
+0))/m_dwTexWidth
;
157 m_fTexCoords
[c
][1] = ((float)(y
+0))/m_dwTexHeight
;
158 m_fTexCoords
[c
][2] = ((float)(x
+0+size
.cx
))/m_dwTexWidth
;
159 m_fTexCoords
[c
][3] = ((float)(y
+0+size
.cy
))/m_dwTexHeight
;
161 x
+= size
.cx
+ 3; // 3 to work around annoying ij conflict (part of the j ends up with the i)
164 // create a new texture for the font
165 // possible optimization: store the converted data in a buffer and fill the texture on creation.
166 // That way, we can use a static texture
167 ID3D11Texture2D
* buftex
;
168 D3D11_TEXTURE2D_DESC texdesc
= CD3D11_TEXTURE2D_DESC(DXGI_FORMAT_R8G8B8A8_UNORM
, m_dwTexWidth
, m_dwTexHeight
,
169 1, 1, D3D11_BIND_SHADER_RESOURCE
, D3D11_USAGE_DYNAMIC
,
170 D3D11_CPU_ACCESS_WRITE
);
171 hr
= device
->CreateTexture2D(&texdesc
, NULL
, &buftex
);
174 PanicAlert("Failed to create font texture");
177 D3D::SetDebugObjectName((ID3D11DeviceChild
*)buftex
, "texture of a CD3DFont object");
179 // lock the surface and write the alpha values for the set pixels
180 D3D11_MAPPED_SUBRESOURCE texmap
;
181 hr
= context
->Map(buftex
, 0, D3D11_MAP_WRITE_DISCARD
, 0, &texmap
);
182 if (FAILED(hr
)) PanicAlert("Failed to map a texture at %s %d\n", __FILE__
, __LINE__
);
184 for (y
= 0; y
< m_dwTexHeight
; y
++)
186 u32
* pDst32
= (u32
*)((u8
*)texmap
.pData
+ y
* texmap
.RowPitch
);
187 for (x
= 0; x
< m_dwTexWidth
; x
++)
189 const u8 bAlpha
= (pBitmapBits
[m_dwTexWidth
* y
+ x
] & 0xff);
190 pDst32
[x
] = ((bAlpha
* 255 / 15) << 24) | 0xFFFFFF;
195 context
->Unmap(buftex
, 0);
196 hr
= D3D::device
->CreateShaderResourceView(buftex
, NULL
, &m_pTexture
);
197 if (FAILED(hr
)) PanicAlert("Failed to create shader resource view at %s %d\n", __FILE__
, __LINE__
);
200 SelectObject(hDC
, hOldbmBitmap
);
201 DeleteObject(hbmBitmap
);
203 SelectObject(hDC
, hOldFont
);
206 // setup device objects for drawing
207 m_pshader
= D3D::CompileAndCreatePixelShader(fontpixshader
, sizeof(fontpixshader
));
208 if (m_pshader
== NULL
) PanicAlert("Failed to create pixel shader, %s %d\n", __FILE__
, __LINE__
);
209 D3D::SetDebugObjectName((ID3D11DeviceChild
*)m_pshader
, "pixel shader of a CD3DFont object");
212 D3D::CompileVertexShader(fontvertshader
, sizeof(fontvertshader
), &vsbytecode
);
213 if (vsbytecode
== NULL
) PanicAlert("Failed to compile vertex shader, %s %d\n", __FILE__
, __LINE__
);
214 m_vshader
= D3D::CreateVertexShaderFromByteCode(vsbytecode
);
215 if (m_vshader
== NULL
) PanicAlert("Failed to create vertex shader, %s %d\n", __FILE__
, __LINE__
);
216 D3D::SetDebugObjectName((ID3D11DeviceChild
*)m_vshader
, "vertex shader of a CD3DFont object");
218 const D3D11_INPUT_ELEMENT_DESC desc
[] =
220 { "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT
, 0, 0, D3D11_INPUT_PER_VERTEX_DATA
, 0 },
221 { "COLOR", 0, DXGI_FORMAT_R32G32B32A32_FLOAT
, 0, 12, D3D11_INPUT_PER_VERTEX_DATA
, 0 },
222 { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT
, 0, 28, D3D11_INPUT_PER_VERTEX_DATA
, 0 },
224 hr
= D3D::device
->CreateInputLayout(desc
, 3, vsbytecode
->Data(), vsbytecode
->Size(), &m_InputLayout
);
225 if (FAILED(hr
)) PanicAlert("Failed to create input layout, %s %d\n", __FILE__
, __LINE__
);
226 vsbytecode
->Release();
228 D3D11_BLEND_DESC blenddesc
;
229 blenddesc
.AlphaToCoverageEnable
= FALSE
;
230 blenddesc
.IndependentBlendEnable
= FALSE
;
231 blenddesc
.RenderTarget
[0].BlendEnable
= TRUE
;
232 blenddesc
.RenderTarget
[0].RenderTargetWriteMask
= D3D11_COLOR_WRITE_ENABLE_ALL
;
233 blenddesc
.RenderTarget
[0].SrcBlend
= D3D11_BLEND_SRC_ALPHA
;
234 blenddesc
.RenderTarget
[0].DestBlend
= D3D11_BLEND_INV_SRC_ALPHA
;
235 blenddesc
.RenderTarget
[0].BlendOp
= D3D11_BLEND_OP_ADD
;
236 blenddesc
.RenderTarget
[0].SrcBlendAlpha
= D3D11_BLEND_SRC_ALPHA
;
237 blenddesc
.RenderTarget
[0].DestBlendAlpha
= D3D11_BLEND_INV_SRC_ALPHA
;
238 blenddesc
.RenderTarget
[0].BlendOpAlpha
= D3D11_BLEND_OP_ADD
;
239 hr
= D3D::device
->CreateBlendState(&blenddesc
, &m_blendstate
);
240 CHECK(hr
==S_OK
, "Create font blend state");
241 D3D::SetDebugObjectName((ID3D11DeviceChild
*)m_blendstate
, "blend state of a CD3DFont object");
243 // this might need to be changed when adding multisampling support
244 D3D11_RASTERIZER_DESC rastdesc
= CD3D11_RASTERIZER_DESC(D3D11_FILL_SOLID
, D3D11_CULL_NONE
, false, 0, 0.f
, 0.f
, false, false, false, false);
245 hr
= D3D::device
->CreateRasterizerState(&rastdesc
, &m_raststate
);
246 CHECK(hr
==S_OK
, "Create font rasterizer state");
247 D3D::SetDebugObjectName((ID3D11DeviceChild
*)m_raststate
, "rasterizer state of a CD3DFont object");
249 D3D11_BUFFER_DESC vbdesc
= CD3D11_BUFFER_DESC(MAX_NUM_VERTICES
*sizeof(FONT2DVERTEX
), D3D11_BIND_VERTEX_BUFFER
, D3D11_USAGE_DYNAMIC
, D3D11_CPU_ACCESS_WRITE
);
250 if (FAILED(hr
= device
->CreateBuffer(&vbdesc
, NULL
, &m_pVB
)))
252 PanicAlert("Failed to create font vertex buffer at %s, line %d\n", __FILE__
, __LINE__
);
255 D3D::SetDebugObjectName((ID3D11DeviceChild
*)m_pVB
, "vertex buffer of a CD3DFont object");
259 int CD3DFont::Shutdown()
262 SAFE_RELEASE(m_pTexture
);
263 SAFE_RELEASE(m_InputLayout
);
264 SAFE_RELEASE(m_pshader
);
265 SAFE_RELEASE(m_vshader
);
267 SAFE_RELEASE(m_blendstate
);
268 SAFE_RELEASE(m_raststate
);
273 int CD3DFont::DrawTextScaled(float x
, float y
, float scale
, float spacing
, u32 dwColor
, const char* strText
, bool center
)
275 if (!m_pVB
) return 0;
277 UINT stride
= sizeof(FONT2DVERTEX
);
280 // translate starting positions
281 float sx
= x
/ m_dwTexWidth
- 1;
282 float sy
= 1 - y
/ m_dwTexHeight
;
285 // fill vertex buffer
286 FONT2DVERTEX
* pVertices
;
287 int dwNumTriangles
= 0L;
289 D3D11_MAPPED_SUBRESOURCE vbmap
;
290 HRESULT hr
= context
->Map(m_pVB
, 0, D3D11_MAP_WRITE_DISCARD
, 0, &vbmap
);
291 if (FAILED(hr
)) PanicAlert("Mapping vertex buffer failed, %s %d\n", __FILE__
, __LINE__
);
292 pVertices
= (D3D::FONT2DVERTEX
*)vbmap
.pData
;
294 // if center was requested, set current position as centre
295 // this is currently never used
298 const char *oldText
= strText
;
302 while (c
= *strText
++)
309 mx
+= (m_fTexCoords
[c
][2]-m_fTexCoords
[c
][0])/(m_fTexCoords
[0][3] - m_fTexCoords
[0][1])
311 if (mx
> maxx
) maxx
= mx
;
313 sx
-= scale
*maxx
/(2*m_dwTexWidth
);
316 // we now have a starting point
318 // set general pipeline state
319 D3D::stateman
->PushBlendState(m_blendstate
);
320 D3D::stateman
->PushRasterizerState(m_raststate
);
321 D3D::stateman
->Apply();
323 D3D::context
->PSSetShader(m_pshader
, NULL
, 0);
324 D3D::context
->VSSetShader(m_vshader
, NULL
, 0);
326 D3D::context
->IASetInputLayout(m_InputLayout
);
327 D3D::context
->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST
);
328 D3D::context
->PSSetShaderResources(0, 1, &m_pTexture
);
329 while (c
= *strText
++)
334 sy
-= scale
/ m_dwTexHeight
;
339 float tx1
= m_fTexCoords
[c
][0];
340 float ty1
= m_fTexCoords
[c
][1];
341 float tx2
= m_fTexCoords
[c
][2];
342 float ty2
= m_fTexCoords
[c
][3];
344 float w
= (tx2
-tx1
)/2;
345 float h
= (ty1
-ty2
)/2;
348 v
[0] = InitFont2DVertex( sx
, h
+sy
, dwColor
, tx1
, ty2
);
349 v
[1] = InitFont2DVertex( sx
, sy
, dwColor
, tx1
, ty1
);
350 v
[2] = InitFont2DVertex(w
+sx
, h
+sy
, dwColor
, tx2
, ty2
);
351 v
[3] = InitFont2DVertex(w
+sx
, sy
, dwColor
, tx2
, ty1
);
355 memcpy(pVertices
, v
, 6*sizeof(FONT2DVERTEX
));
360 if (dwNumTriangles
* 3 > (MAX_NUM_VERTICES
- 6))
362 context
->Unmap(m_pVB
, 0);
364 D3D::context
->IASetVertexBuffers(0, 1, &m_pVB
, &stride
, &bufoffset
);
365 D3D::context
->Draw(3 * dwNumTriangles
, 0);
368 D3D11_MAPPED_SUBRESOURCE vbmap
;
369 HRESULT hr
= context
->Map(m_pVB
, 0, D3D11_MAP_WRITE_DISCARD
, 0, &vbmap
);
370 if (FAILED(hr
)) PanicAlert("Mapping vertex buffer failed, %s %d\n", __FILE__
, __LINE__
);
371 pVertices
= (D3D::FONT2DVERTEX
*)vbmap
.pData
;
373 sx
+= w
+ spacing
*scale
/m_dwTexWidth
;
376 // Unlock and render the vertex buffer
377 context
->Unmap(m_pVB
, 0);
378 if (dwNumTriangles
> 0)
380 D3D::context
->IASetVertexBuffers(0, 1, &m_pVB
, &stride
, &bufoffset
);
381 D3D::context
->Draw(3 * dwNumTriangles
, 0);
383 D3D::stateman
->PopBlendState();
384 D3D::stateman
->PopRasterizerState();
388 ID3D11Buffer
* CreateQuadVertexBuffer(unsigned int size
, void* data
)
391 D3D11_BUFFER_DESC vbdesc
;
392 vbdesc
.BindFlags
= D3D11_BIND_VERTEX_BUFFER
;
393 vbdesc
.ByteWidth
= size
;
394 vbdesc
.CPUAccessFlags
= D3D11_CPU_ACCESS_WRITE
;
395 vbdesc
.MiscFlags
= 0;
396 vbdesc
.Usage
= D3D11_USAGE_DYNAMIC
;
399 D3D11_SUBRESOURCE_DATA bufdata
;
400 bufdata
.pSysMem
= data
;
401 if (FAILED(device
->CreateBuffer(&vbdesc
, &bufdata
, &vb
))) return NULL
;
403 else if (FAILED(device
->CreateBuffer(&vbdesc
, NULL
, &vb
))) return NULL
;
408 ID3D11SamplerState
* stqsamplerstate
= NULL
;
409 ID3D11SamplerState
* stsqsamplerstate
= NULL
;
410 ID3D11Buffer
* stqvb
= NULL
;
411 ID3D11Buffer
* stsqvb
= NULL
;
412 ID3D11Buffer
* clearvb
= NULL
;
414 typedef struct { float x
,y
,z
,u
,v
; } STQVertex
;
415 typedef struct { float x
,y
,z
,u
,v
; } STSQVertex
;
416 typedef struct { float x
,y
,z
; u32 col
;} ClearVertex
;
420 float border
[4] = { 0.f
, 0.f
, 0.f
, 0.f
};
421 D3D11_SAMPLER_DESC samDesc
= CD3D11_SAMPLER_DESC(D3D11_FILTER_MIN_MAG_MIP_POINT
, D3D11_TEXTURE_ADDRESS_CLAMP
, D3D11_TEXTURE_ADDRESS_CLAMP
, D3D11_TEXTURE_ADDRESS_CLAMP
, 0.f
, 16, D3D11_COMPARISON_ALWAYS
, border
, -D3D11_FLOAT32_MAX
, D3D11_FLOAT32_MAX
);
422 HRESULT hr
= D3D::device
->CreateSamplerState(&samDesc
, &stqsamplerstate
);
423 if (FAILED(hr
)) PanicAlert("Failed to create sampler state at %s %d\n", __FILE__
, __LINE__
);
424 else SetDebugObjectName((ID3D11DeviceChild
*)stqsamplerstate
, "sampler state of drawShadedTexQuad");
426 stqvb
= CreateQuadVertexBuffer(4*sizeof(STQVertex
), NULL
);
427 CHECK(stqvb
!=NULL
, "Create vertex buffer of drawShadedTexQuad");
428 SetDebugObjectName((ID3D11DeviceChild
*)stqvb
, "vertex buffer of drawShadedTexQuad");
430 stsqvb
= CreateQuadVertexBuffer(4*sizeof(STSQVertex
), NULL
);
431 CHECK(stsqvb
!=NULL
, "Create vertex buffer of drawShadedTexSubQuad");
432 SetDebugObjectName((ID3D11DeviceChild
*)stsqvb
, "vertex buffer of drawShadedTexSubQuad");
434 clearvb
= CreateQuadVertexBuffer(4*sizeof(ClearVertex
), NULL
);
435 CHECK(clearvb
!=NULL
, "Create vertex buffer of drawClearQuad");
436 SetDebugObjectName((ID3D11DeviceChild
*)clearvb
, "vertex buffer of drawClearQuad");
438 samDesc
= CD3D11_SAMPLER_DESC(D3D11_FILTER_MIN_MAG_MIP_POINT
, D3D11_TEXTURE_ADDRESS_CLAMP
, D3D11_TEXTURE_ADDRESS_CLAMP
, D3D11_TEXTURE_ADDRESS_CLAMP
, 0.f
, 16, D3D11_COMPARISON_ALWAYS
, border
, -D3D11_FLOAT32_MAX
, D3D11_FLOAT32_MAX
);
439 hr
= D3D::device
->CreateSamplerState(&samDesc
, &stsqsamplerstate
);
440 if (FAILED(hr
)) PanicAlert("Failed to create sampler state at %s %d\n", __FILE__
, __LINE__
);
441 else SetDebugObjectName((ID3D11DeviceChild
*)stsqsamplerstate
, "sampler state of drawShadedTexSubQuad");
446 SAFE_RELEASE(stqsamplerstate
);
447 SAFE_RELEASE(stsqsamplerstate
);
449 SAFE_RELEASE(stsqvb
);
450 SAFE_RELEASE(clearvb
);
453 void drawShadedTexQuad(ID3D11ShaderResourceView
* texture
,
454 const D3D11_RECT
* rSource
,
457 ID3D11PixelShader
* PShader
,
458 ID3D11VertexShader
* Vshader
,
459 ID3D11InputLayout
* layout
)
461 float sw
= 1.0f
/(float) SourceWidth
;
462 float sh
= 1.0f
/(float) SourceHeight
;
463 float u1
= ((float)rSource
->left
) * sw
;
464 float u2
= ((float)rSource
->right
) * sw
;
465 float v1
=((float)rSource
->top
) * sh
;
466 float v2
=((float)rSource
->bottom
) * sh
;
468 static float lastu1
= 0.f
, lastv1
= 0.f
, lastu2
= 0.f
, lastv2
= 0.f
;
470 STQVertex coords
[4] = {
471 {-1.0f
, 1.0f
, 0.0f
, u1
, v1
},
472 { 1.0f
, 1.0f
, 0.0f
, u2
, v1
},
473 {-1.0f
,-1.0f
, 0.0f
, u1
, v2
},
474 { 1.0f
,-1.0f
, 0.0f
, u2
, v2
},
477 // only upload the data to VRAM if it changed
478 if (lastu1
!= u1
|| lastv1
!= v1
|| lastu2
!= u2
|| lastv2
!= v2
)
480 D3D11_MAPPED_SUBRESOURCE map
;
481 D3D::context
->Map(stqvb
, 0, D3D11_MAP_WRITE_DISCARD
, 0, &map
);
482 memcpy(map
.pData
, coords
, sizeof(coords
));
483 D3D::context
->Unmap(stqvb
, 0);
485 UINT stride
= sizeof(STQVertex
);
488 D3D::context
->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP
);
489 D3D::context
->IASetInputLayout(layout
);
490 D3D::context
->IASetVertexBuffers(0, 1, &stqvb
, &stride
, &offset
);
491 D3D::context
->PSSetSamplers(0, 1, &stqsamplerstate
);
492 D3D::context
->PSSetShader(PShader
, NULL
, 0);
493 D3D::context
->PSSetShaderResources(0, 1, &texture
);
494 D3D::context
->VSSetShader(Vshader
, NULL
, 0);
495 D3D::stateman
->Apply();
496 D3D::context
->Draw(4, 0);
498 ID3D11ShaderResourceView
* texres
= NULL
;
499 context
->PSSetShaderResources(0, 1, &texres
); // immediately unbind the texture
507 void drawShadedTexSubQuad(ID3D11ShaderResourceView
* texture
,
508 const MathUtil::Rectangle
<float>* rSource
,
511 const MathUtil::Rectangle
<float>* rDest
,
512 ID3D11PixelShader
* PShader
,
513 ID3D11VertexShader
* Vshader
,
514 ID3D11InputLayout
* layout
)
516 float sw
= 1.0f
/(float) SourceWidth
;
517 float sh
= 1.0f
/(float) SourceHeight
;
518 float u1
= (rSource
->left
) * sw
;
519 float u2
= (rSource
->right
) * sw
;
520 float v1
= (rSource
->top
) * sh
;
521 float v2
= (rSource
->bottom
) * sh
;
523 static MathUtil::Rectangle
<float> lastrdest
= {0.f
};
524 static float lastu1
= 0.f
, lastv1
= 0.f
, lastu2
= 0.f
, lastv2
= 0.f
;
526 STSQVertex coords
[4] = {
527 { rDest
->left
, rDest
->bottom
, 0.0f
, u1
, v1
},
528 { rDest
->right
, rDest
->bottom
, 0.0f
, u2
, v1
},
529 { rDest
->left
, rDest
->top
, 0.0f
, u1
, v2
},
530 { rDest
->right
, rDest
->top
, 0.0f
, u2
, v2
},
533 // only upload the data to VRAM if it changed
534 if (memcmp(rDest
, &lastrdest
, sizeof(lastrdest
)) != 0 || lastu1
!= u1
|| lastv1
!= v1
|| lastu2
!= u2
|| lastv2
!= v2
)
536 D3D11_MAPPED_SUBRESOURCE map
;
537 D3D::context
->Map(stsqvb
, 0, D3D11_MAP_WRITE_DISCARD
, 0, &map
);
538 memcpy(map
.pData
, coords
, sizeof(coords
));
539 D3D::context
->Unmap(stsqvb
, 0);
541 UINT stride
= sizeof(STSQVertex
);
544 context
->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP
);
545 context
->IASetVertexBuffers(0, 1, &stsqvb
, &stride
, &offset
);
546 context
->IASetInputLayout(layout
);
547 context
->PSSetShaderResources(0, 1, &texture
);
548 context
->PSSetSamplers(0, 1, &stsqsamplerstate
);
549 context
->PSSetShader(PShader
, NULL
, 0);
550 context
->VSSetShader(Vshader
, NULL
, 0);
554 ID3D11ShaderResourceView
* texres
= NULL
;
555 context
->PSSetShaderResources(0, 1, &texres
); // immediately unbind the texture
561 lastrdest
.left
= rDest
->left
;
562 lastrdest
.right
= rDest
->right
;
563 lastrdest
.top
= rDest
->top
;
564 lastrdest
.bottom
= rDest
->bottom
;
567 // TODO: Check whether we're passing Color in the right order (should be RGBA)
568 void drawClearQuad(u32 Color
, float z
, ID3D11PixelShader
* PShader
, ID3D11VertexShader
* Vshader
, ID3D11InputLayout
* layout
)
570 static u32 lastcol
= 0;
571 static float lastz
= -15325.376f
; // random value
573 if (lastcol
!= Color
|| lastz
!= z
)
575 ClearVertex coords
[4] = {
576 {-1.0f
, 1.0f
, z
, Color
},
577 { 1.0f
, 1.0f
, z
, Color
},
578 {-1.0f
, -1.0f
, z
, Color
},
579 { 1.0f
, -1.0f
, z
, Color
},
582 D3D11_MAPPED_SUBRESOURCE map
;
583 context
->Map(clearvb
, 0, D3D11_MAP_WRITE_DISCARD
, 0, &map
);
584 memcpy(map
.pData
, coords
, sizeof(coords
));
585 context
->Unmap(clearvb
, 0);
587 context
->VSSetShader(Vshader
, NULL
, 0);
588 context
->PSSetShader(PShader
, NULL
, 0);
589 context
->IASetInputLayout(layout
);
591 UINT stride
= sizeof(ClearVertex
);
593 context
->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP
);
594 context
->IASetVertexBuffers(0, 1, &clearvb
, &stride
, &offset
);