VirtualBox

source: vbox/trunk/src/VBox/Devices/Graphics/DevVGA-SVGA3d-win-d3d9.cpp@ 82781

Last change on this file since 82781 was 82095, checked in by vboxsync, 4 years ago

Devices/Graphics: renamed VMSVGA3DSURFACE::pMipmapLevels to paMipmapLevels; use a helper to get PVMSVGA3DMIPMAPLEVEL pointer.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 50.0 KB
Line 
1/* $Id: DevVGA-SVGA3d-win-d3d9.cpp 82095 2019-11-22 08:09:37Z vboxsync $ */
2/** @file
3 * DevVMWare - VMWare SVGA device Direct3D 9 backend.
4 */
5
6/*
7 * Copyright (C) 2019 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 */
17
18#define LOG_GROUP LOG_GROUP_DEV_VMSVGA
19#include <VBox/vmm/pdmdev.h>
20
21#include <iprt/assert.h>
22
23#include "DevVGA-SVGA.h"
24#include "DevVGA-SVGA3d-internal.h"
25
26
27typedef enum D3D9TextureType
28{
29 D3D9TextureType_Texture,
30 D3D9TextureType_Bounce,
31 D3D9TextureType_Emulated
32} D3D9TextureType;
33
34IDirect3DTexture9 *D3D9GetTexture(PVMSVGA3DSURFACE pSurface,
35 D3D9TextureType enmType)
36{
37 IDirect3DTexture9 *p;
38 switch (enmType)
39 {
40 default: AssertFailed();
41 RT_FALL_THRU();
42 case D3D9TextureType_Texture: p = pSurface->u.pTexture; break;
43 case D3D9TextureType_Bounce: p = pSurface->bounce.pTexture; break;
44 case D3D9TextureType_Emulated: p = pSurface->emulated.pTexture; break;
45 }
46 return p;
47}
48
49IDirect3DCubeTexture9 *D3D9GetCubeTexture(PVMSVGA3DSURFACE pSurface,
50 D3D9TextureType enmType)
51{
52 IDirect3DCubeTexture9 *p;
53 switch (enmType)
54 {
55 default: AssertFailed();
56 RT_FALL_THRU();
57 case D3D9TextureType_Texture: p = pSurface->u.pCubeTexture; break;
58 case D3D9TextureType_Bounce: p = pSurface->bounce.pCubeTexture; break;
59 case D3D9TextureType_Emulated: p = pSurface->emulated.pCubeTexture; break;
60 }
61 return p;
62}
63
64IDirect3DVolumeTexture9 *D3D9GetVolumeTexture(PVMSVGA3DSURFACE pSurface,
65 D3D9TextureType enmType)
66{
67 IDirect3DVolumeTexture9 *p;
68 switch (enmType)
69 {
70 default: AssertFailed();
71 RT_FALL_THRU();
72 case D3D9TextureType_Texture: p = pSurface->u.pVolumeTexture; break;
73 case D3D9TextureType_Bounce: p = pSurface->bounce.pVolumeTexture; break;
74 case D3D9TextureType_Emulated: p = pSurface->emulated.pVolumeTexture; break;
75 }
76 return p;
77}
78
79HRESULT D3D9GetTextureLevel(PVMSVGA3DSURFACE pSurface,
80 D3D9TextureType enmType,
81 uint32_t uFace,
82 uint32_t uMipmap,
83 IDirect3DSurface9 **ppD3DSurface)
84{
85 HRESULT hr;
86
87 if (pSurface->enmD3DResType == VMSVGA3D_D3DRESTYPE_CUBE_TEXTURE)
88 {
89 Assert(pSurface->cFaces == 6);
90
91 IDirect3DCubeTexture9 *p = D3D9GetCubeTexture(pSurface, enmType);
92 if (p)
93 {
94 D3DCUBEMAP_FACES const FaceType = vmsvga3dCubemapFaceFromIndex(uFace);
95 hr = p->GetCubeMapSurface(FaceType, uMipmap, ppD3DSurface);
96 AssertMsg(hr == D3D_OK, ("GetCubeMapSurface failed with %x\n", hr));
97 }
98 else
99 {
100 AssertFailed();
101 hr = E_INVALIDARG;
102 }
103 }
104 else if (pSurface->enmD3DResType == VMSVGA3D_D3DRESTYPE_TEXTURE)
105 {
106 Assert(pSurface->cFaces == 1);
107 Assert(uFace == 0);
108
109 IDirect3DTexture9 *p = D3D9GetTexture(pSurface, enmType);
110 if (p)
111 {
112 hr = p->GetSurfaceLevel(uMipmap, ppD3DSurface);
113 AssertMsg(hr == D3D_OK, ("GetSurfaceLevel failed with %x\n", hr));
114 }
115 else
116 {
117 AssertFailed();
118 hr = E_INVALIDARG;
119 }
120 }
121 else
122 {
123 AssertMsgFailed(("No surface level for type %d\n", pSurface->enmD3DResType));
124 hr = E_INVALIDARG;
125 }
126
127 return hr;
128}
129
130
131static HRESULT d3dCopyToVertexBuffer(IDirect3DVertexBuffer9 *pVB, const void *pvSrc, int cbSrc)
132{
133 HRESULT hr = D3D_OK;
134 void *pvDst = 0;
135 hr = pVB->Lock(0, 0, &pvDst, 0);
136 if (SUCCEEDED(hr))
137 {
138 memcpy(pvDst, pvSrc, cbSrc);
139 hr = pVB->Unlock();
140 }
141 return hr;
142}
143
144struct Vertex
145{
146 float x, y; /* The vertex position. */
147 float u, v; /* Texture coordinates. */
148};
149
150typedef struct D3D9ConversionParameters
151{
152 DWORD const *paVS; /* Vertex shader code. */
153 DWORD const *paPS; /* Pixel shader code. */
154} D3D9ConversionParameters;
155
156/** Select conversion shaders.
157 * @param d3dfmtFrom Source texture format.
158 * @param d3dfmtTo Target texture format.
159 * @param pResult Where the tore pointers to the shader code.
160 */
161static HRESULT d3d9SelectConversion(D3DFORMAT d3dfmtFrom, D3DFORMAT d3dfmtTo,
162 D3D9ConversionParameters *pResult)
163{
164 /*
165 * The shader code has been obtained from the hex listing file (hexdump.txt) produced by fxc HLSL compiler:
166 * fxc.exe /Op /Tfx_2_0 /Fxhexdump.txt shader.fx
167 *
168 * The vertex shader code is the same for all convestion variants.
169 *
170 * For example here is the complete code for aPSCodeSwapRB:
171
172 uniform extern float4 gTextureInfo; // .xy = (width, height) in pixels, .zw = (1/width, 1/height)
173 uniform extern texture gTexSource;
174 sampler sSource = sampler_state
175 {
176 Texture = <gTexSource>;
177 };
178
179 struct VS_INPUT
180 {
181 float2 Position : POSITION; // In pixels.
182 float2 TexCoord : TEXCOORD0;
183 };
184
185 struct VS_OUTPUT
186 {
187 float4 Position : POSITION; // Normalized.
188 float2 TexCoord : TEXCOORD0;
189 };
190
191 VS_OUTPUT VS(VS_INPUT In)
192 {
193 VS_OUTPUT Output;
194
195 // Position is in pixels, i.e [0; width - 1]. Top, left is 0,0.
196 // Convert to the normalized coords in the -1;1 range
197 float4 Position;
198 Position.x = 2.0f * In.Position.x / (gTextureInfo.x - 1.0f) - 1.0f;
199 Position.y = -2.0f * In.Position.y / (gTextureInfo.y - 1.0f) + 1.0f;
200 Position.z = 0.0f; // Not used.
201 Position.w = 1.0f; // It is a point.
202
203 Output.Position = Position;
204 Output.TexCoord = In.TexCoord;
205
206 return Output;
207 }
208
209 struct PS_OUTPUT
210 {
211 float4 Color : COLOR0;
212 };
213
214 PS_OUTPUT PS(VS_OUTPUT In)
215 {
216 PS_OUTPUT Output;
217
218 float2 texCoord = In.TexCoord;
219
220 float4 texColor = tex2D(sSource, texCoord);
221
222 Output.Color = texColor.bgra; // Swizzle rgba -> bgra
223
224 return Output;
225 }
226
227 technique RenderScene
228 {
229 pass P0
230 {
231 VertexShader = compile vs_2_0 VS();
232 PixelShader = compile ps_2_0 PS();
233 }
234 }
235 */
236
237 static DWORD const aVSCode[] =
238 {
239 0xfffe0200, // vs_2_0
240 0x05000051, 0xa00f0001, 0xbf800000, 0xc0000000, 0x3f800000, 0x00000000, // def c1, -1, -2, 1, 0
241 0x0200001f, 0x80000000, 0x900f0000, // dcl_position v0
242 0x0200001f, 0x80000005, 0x900f0001, // dcl_texcoord v1
243 0x03000002, 0x80010000, 0x90000000, 0x90000000, // add r0.x, v0.x, v0.x
244 0x02000001, 0x80010001, 0xa0000001, // mov r1.x, c1.x
245 0x03000002, 0x80060000, 0x80000001, 0xa0d00000, // add r0.yz, r1.x, c0.xxyw
246 0x02000006, 0x80020000, 0x80550000, // rcp r0.y, r0.y
247 0x02000006, 0x80040000, 0x80aa0000, // rcp r0.z, r0.z
248 0x04000004, 0xc0010000, 0x80000000, 0x80550000, 0xa0000001, // mad oPos.x, r0.x, r0.y, c1.x
249 0x03000005, 0x80010000, 0x90550000, 0xa0550001, // mul r0.x, v0.y, c1.y
250 0x04000004, 0xc0020000, 0x80000000, 0x80aa0000, 0xa0aa0001, // mad oPos.y, r0.x, r0.z, c1.z
251 0x02000001, 0xc00c0000, 0xa0b40001, // mov oPos.zw, c1.xywz
252 0x02000001, 0xe0030000, 0x90e40001, // mov oT0.xy, v1
253 0x0000ffff
254 };
255
256 /*
257 * Swap R and B components. Converts D3DFMT_A8R8G8B8 <-> D3DFMT_A8B8G8R8.
258 */
259 static DWORD const aPSCodeSwapRB[] =
260 {
261 0xffff0200, // ps_2_0
262 0x0200001f, 0x80000000, 0xb0030000, // dcl t0.xy
263 0x0200001f, 0x90000000, 0xa00f0800, // dcl_2d s0
264 0x03000042, 0x800f0000, 0xb0e40000, 0xa0e40800, // texld r0, t0, s0
265 0x02000001, 0x80090001, 0x80d20000, // mov r1.xw, r0.zxyw
266 0x02000001, 0x80040001, 0x80000000, // mov r1.z, r0.x
267 0x02000001, 0x80020001, 0x80550000, // mov r1.y, r0.y
268 0x02000001, 0x800f0800, 0x80e40001, // mov oC0, r1
269 0x0000ffff
270 };
271
272 /* YUY2 to RGB:
273
274 // YUY2 if not defined
275 // #define UYVY
276
277 static const float3x3 yuvCoeffs =
278 {
279 1.164383f, 1.164383f, 1.164383f,
280 0.0f, -0.391762f, 2.017232f,
281 1.596027f, -0.812968f, 0.0f
282 };
283
284 PS_OUTPUT PS(VS_OUTPUT In)
285 {
286 PS_OUTPUT Output;
287
288 // 4 bytes of an YUV macropixel contain 2 pixels in X for the target.
289 // I.e. each YUV texture pixel is sampled twice: for both even and odd target pixels.
290
291 // In.TexCoord are in [0;1] range for the target.
292 float2 texCoord = In.TexCoord;
293
294 // Convert to the target coords in pixels: xPixel = TexCoord.x * Width.
295 float xTargetPixel = texCoord.x * gTextureInfo.x;
296
297 // Source texture is half width, i.e. it contains data in pixels [0; width / 2 - 1].
298 float xSourcePixel = xTargetPixel / 2.0f;
299
300 // Remainder is about 0.25 for even pixels and about 0.75 for odd pixels.
301 float remainder = xSourcePixel - trunc(xSourcePixel);
302
303 // Back to the normalized coords: texCoord.x = xPixel / Width.
304 texCoord.x = xSourcePixel * gTextureInfo.z;
305
306 // Fetch YUV
307 float4 texColor = tex2D(sSource, texCoord);
308
309 // Get YUV components.
310 #ifdef UYVY
311 float u = texColor.b;
312 float y0 = texColor.g;
313 float v = texColor.r;
314 float y1 = texColor.a;
315 #else // YUY2
316 float y0 = texColor.b;
317 float u = texColor.g;
318 float y1 = texColor.r;
319 float v = texColor.a;
320 #endif
321
322 // Get y0 for even x coordinates and y1 for odd ones.
323 float y = remainder < 0.5f ? y0 : y1;
324
325 // Make a vector for easier calculation.
326 float3 yuv = float3(y, u, v);
327
328 // Convert YUV to RGB:
329 // https://docs.microsoft.com/en-us/windows/win32/medfound/recommended-8-bit-yuv-formats-for-video-rendering#converting-8-bit-yuv-to-rgb888
330 //
331 // For 8bit [0;255] when Y = [16;235], U,V = [16;239]:
332 //
333 // C = Y - 16
334 // D = U - 128
335 // E = V - 128
336 //
337 // R = 1.164383 * C + 1.596027 * E
338 // G = 1.164383 * C - 0.391762 * D - 0.812968 * E
339 // B = 1.164383 * C + 2.017232 * D
340 //
341 // For shader values [0;1.0] when Y = [16/255;235/255], U,V = [16/255;239/255]:
342 //
343 // C = Y - 0.0627
344 // D = U - 0.5020
345 // E = V - 0.5020
346 //
347 // R = 1.164383 * C + 1.596027 * E
348 // G = 1.164383 * C - 0.391762 * D - 0.812968 * E
349 // B = 1.164383 * C + 2.017232 * D
350 //
351 yuv -= float3(0.0627f, 0.502f, 0.502f);
352 float3 bgr = mul(yuv, yuvCoeffs);
353
354 // Clamp to [0;1]
355 bgr = saturate(bgr);
356
357 // Return RGBA
358 Output.Color = float4(bgr, 1.0f);
359
360 return Output;
361 }
362 */
363 static DWORD const aPSCodeYUY2toRGB[] =
364 {
365 0xffff0200, // ps_2_0
366 0x05000051, 0xa00f0001, 0x3f000000, 0x00000000, 0x3f800000, 0xbf000000, // def c1, 0.5, 0, 1, -0.5
367 0x05000051, 0xa00f0002, 0xbd8068dc, 0xbf008312, 0xbf008312, 0x00000000, // def c2, -0.0627000034, -0.501999974, -0.501999974, 0
368 0x05000051, 0xa00f0003, 0x3f950a81, 0x00000000, 0x3fcc4a9d, 0x00000000, // def c3, 1.16438305, 0, 1.59602702, 0
369 0x05000051, 0xa00f0004, 0x3f950a81, 0xbec89507, 0xbf501eac, 0x00000000, // def c4, 1.16438305, -0.391761988, -0.812968016, 0
370 0x05000051, 0xa00f0005, 0x3f950a81, 0x40011a54, 0x00000000, 0x00000000, // def c5, 1.16438305, 2.01723194, 0, 0
371 0x0200001f, 0x80000000, 0xb0030000, // dcl t0.xy
372 0x0200001f, 0x90000000, 0xa00f0800, // dcl_2d s0
373 0x03000005, 0x80080000, 0xb0000000, 0xa0000000, // mul r0.w, t0.x, c0.x
374 0x03000005, 0x80010000, 0x80ff0000, 0xa0000001, // mul r0.x, r0.w, c1.x
375 0x02000013, 0x80020000, 0x80000000, // frc r0.y, r0.x
376 0x04000058, 0x80040000, 0x81550000, 0xa0550001, 0xa0aa0001, // cmp r0.z, -r0.y, c1.y, c1.z
377 0x03000002, 0x80020000, 0x80000000, 0x81550000, // add r0.y, r0.x, -r0.y
378 0x03000005, 0x80010001, 0x80000000, 0xa0aa0000, // mul r1.x, r0.x, c0.z
379 0x04000058, 0x80010000, 0x80ff0000, 0xa0550001, 0x80aa0000, // cmp r0.x, r0.w, c1.y, r0.z
380 0x03000002, 0x80010000, 0x80000000, 0x80550000, // add r0.x, r0.x, r0.y
381 0x04000004, 0x80010000, 0x80ff0000, 0xa0000001, 0x81000000, // mad r0.x, r0.w, c1.x, -r0.x
382 0x03000002, 0x80010000, 0x80000000, 0xa0ff0001, // add r0.x, r0.x, c1.w
383 0x02000001, 0x80020001, 0xb0550000, // mov r1.y, t0.y
384 0x03000042, 0x800f0001, 0x80e40001, 0xa0e40800, // texld r1, r1, s0
385 0x04000058, 0x80010001, 0x80000000, 0x80000001, 0x80aa0001, // cmp r1.x, r0.x, r1.x, r1.z
386 0x02000001, 0x80040001, 0x80ff0001, // mov r1.z, r1.w
387 0x03000002, 0x80070000, 0x80e40001, 0xa0e40002, // add r0.xyz, r1, c2
388 0x03000008, 0x80110001, 0x80e40000, 0xa0e40003, // dp3_sat r1.x, r0, c3
389 0x03000008, 0x80120001, 0x80e40000, 0xa0e40004, // dp3_sat r1.y, r0, c4
390 0x0400005a, 0x80140001, 0x80e40000, 0xa0e40005, 0xa0aa0005, // dp2add_sat r1.z, r0, c5, c5.z
391 0x02000001, 0x80080001, 0xa0aa0001, // mov r1.w, c1.z
392 0x02000001, 0x800f0800, 0x80e40001, // mov oC0, r1
393 0x0000ffff
394 };
395
396 /* UYVY to RGB is same as YUY2 above except for the order of yuv components:
397
398 // YUY2 if not defined
399 #define UYVY
400 ...
401 */
402 static DWORD const aPSCodeUYVYtoRGB[] =
403 {
404 0xffff0200, // ps_2_0
405 0x05000051, 0xa00f0001, 0x3f000000, 0x00000000, 0x3f800000, 0xbf000000, // def c1, 0.5, 0, 1, -0.5
406 0x05000051, 0xa00f0002, 0xbd8068dc, 0xbf008312, 0xbf008312, 0x00000000, // def c2, -0.0627000034, -0.501999974, -0.501999974, 0
407 0x05000051, 0xa00f0003, 0x3f950a81, 0x00000000, 0x3fcc4a9d, 0x00000000, // def c3, 1.16438305, 0, 1.59602702, 0
408 0x05000051, 0xa00f0004, 0x3f950a81, 0xbec89507, 0xbf501eac, 0x00000000, // def c4, 1.16438305, -0.391761988, -0.812968016, 0
409 0x05000051, 0xa00f0005, 0x3f950a81, 0x40011a54, 0x00000000, 0x00000000, // def c5, 1.16438305, 2.01723194, 0, 0
410 0x0200001f, 0x80000000, 0xb0030000, // dcl t0.xy
411 0x0200001f, 0x90000000, 0xa00f0800, // dcl_2d s0
412 0x03000005, 0x80080000, 0xb0000000, 0xa0000000, // mul r0.w, t0.x, c0.x
413 0x03000005, 0x80010000, 0x80ff0000, 0xa0000001, // mul r0.x, r0.w, c1.x
414 0x02000013, 0x80020000, 0x80000000, // frc r0.y, r0.x
415 0x04000058, 0x80040000, 0x81550000, 0xa0550001, 0xa0aa0001, // cmp r0.z, -r0.y, c1.y, c1.z
416 0x03000002, 0x80020000, 0x80000000, 0x81550000, // add r0.y, r0.x, -r0.y
417 0x03000005, 0x80010001, 0x80000000, 0xa0aa0000, // mul r1.x, r0.x, c0.z
418 0x04000058, 0x80010000, 0x80ff0000, 0xa0550001, 0x80aa0000, // cmp r0.x, r0.w, c1.y, r0.z
419 0x03000002, 0x80010000, 0x80000000, 0x80550000, // add r0.x, r0.x, r0.y
420 0x04000004, 0x80010000, 0x80ff0000, 0xa0000001, 0x81000000, // mad r0.x, r0.w, c1.x, -r0.x
421 0x03000002, 0x80010000, 0x80000000, 0xa0ff0001, // add r0.x, r0.x, c1.w
422 0x02000001, 0x80020001, 0xb0550000, // mov r1.y, t0.y
423 0x03000042, 0x800f0001, 0x80e40001, 0xa0e40800, // texld r1, r1, s0
424 0x04000058, 0x80010000, 0x80000000, 0x80ff0001, 0x80550001, // cmp r0.x, r0.x, r1.w, r1.y
425 0x02000001, 0x80060000, 0x80c90001, // mov r0.yz, r1.yzxw
426 0x03000002, 0x80070000, 0x80e40000, 0xa0e40002, // add r0.xyz, r0, c2
427 0x03000008, 0x80110001, 0x80e40000, 0xa0e40003, // dp3_sat r1.x, r0, c3
428 0x03000008, 0x80120001, 0x80e40000, 0xa0e40004, // dp3_sat r1.y, r0, c4
429 0x0400005a, 0x80140001, 0x80e40000, 0xa0e40005, 0xa0aa0005, // dp2add_sat r1.z, r0, c5, c5.z
430 0x02000001, 0x80080001, 0xa0aa0001, // mov r1.w, c1.z
431 0x02000001, 0x800f0800, 0x80e40001, // mov oC0, r1
432 0x0000ffff
433 };
434
435 /* RGB to YUY2.
436 * UYVY is not defined.
437
438 static const float3x3 bgrCoeffs =
439 {
440 0.0977f, 0.4375f, -0.0703f,
441 0.5039f, -0.2891f, -0.3672f,
442 0.2578f, -0.1484f, 0.4375f
443 };
444
445 static const float3 yuvShift = { 0.0647f, 0.5039f, 0.5039f };
446
447 PS_OUTPUT PS(VS_OUTPUT In)
448 {
449 PS_OUTPUT Output;
450
451 // 4 bytes of an YUV macropixel contain 2 source pixels in X.
452 // I.e. each YUV texture target pixel is computed from 2 source pixels.
453 // The target texture pixels are located in the [0; width / 2 - 1] range.
454
455 // In.TexCoord are in [0;1] range, applicable both to the source and the target textures.
456 float2 texCoordDst = In.TexCoord;
457
458 // Convert to the target coords in pixels: xPixel = TexCoord.x * Width.
459 float xTargetPixel = texCoordDst.x * gTextureInfo.x;
460
461 float4 bgraOutputPixel;
462 if (xTargetPixel < gTextureInfo.x / 2.0f)
463 {
464 // Target texture is half width, i.e. it contains data in pixels [0; width / 2 - 1].
465 // Compute the source texture coords for the pixels which will be used to compute the target pixel.
466 float2 texCoordSrc = texCoordDst;
467 texCoordSrc.x *= 2.0f;
468
469 // Even pixel. Fetch two BGRA source pixels.
470 float4 texColor0 = tex2D(sSource, texCoordSrc);
471
472 // Advance one pixel (+ 1/Width)
473 texCoordSrc.x += gTextureInfo.z;
474 float4 texColor1 = tex2D(sSource, texCoordSrc);
475
476 // Compute y0, u, y1, v components
477 // https://docs.microsoft.com/en-us/windows/win32/medfound/recommended-8-bit-yuv-formats-for-video-rendering#converting-rgb888-to-yuv-444
478 //
479 // For R,G,B and Y,U,V in [0;255]
480 // Y = ( ( 66 * R + 129 * G + 25 * B + 128) >> 8) + 16
481 // U = ( ( -38 * R - 74 * G + 112 * B + 128) >> 8) + 128
482 // V = ( ( 112 * R - 94 * G - 18 * B + 128) >> 8) + 128
483 //
484 // For r,g,b and y,u,v in [0;1.0]
485 // y = 0.2578 * r + 0.5039 * g + 0.0977 * b + 0.0647
486 // u = -0.1484 * r - 0.2891 * g + 0.4375 * b + 0.5039
487 // v = 0.4375 * r - 0.3672 * g - 0.0703 * b + 0.5039
488
489 float3 yuv0 = mul(texColor0.bgr, bgrCoeffs);
490 yuv0 -= yuvShift;
491
492 float3 yuv1 = mul(texColor1.bgr, bgrCoeffs);
493 yuv1 -= yuvShift;
494
495 float y0 = yuv0.b;
496 float u = (yuv0.g + yuv1.g) / 2.0f;
497 float y1 = yuv1.b;
498 float v = (yuv0.r + yuv1.r) / 2.0f;
499
500 #ifdef UYVY
501 bgraOutputPixel = float4(u, y0, v, y1);
502 #else // YUY2
503 bgraOutputPixel = float4(y0, u, y1, v);
504 #endif
505 }
506 else
507 {
508 // [width / 2; width - 1] pixels are not used. Set to something.
509 bgraOutputPixel = float4(0.0f, 0.0f, 0.0f, 0.0f);
510 }
511
512 // Clamp to [0;1]
513 bgraOutputPixel = saturate(bgraOutputPixel);
514
515 // Return RGBA
516 Output.Color = bgraOutputPixel;
517
518 return Output;
519 }
520 */
521 static DWORD const aPSCodeRGBtoYUY2[] =
522 {
523 0xffff0200, // ps_2_0
524 0x05000051, 0xa00f0001, 0xbd84816f, 0xbf00ff97, 0xbf00ff97, 0x00000000, // def c1, -0.0647, -0.503899992, -0.503899992, 0
525 0x05000051, 0xa00f0002, 0xbe80ff97, 0x00000000, 0xbd04816f, 0x00000000, // def c2, -0.251949996, 0, -0.03235, 0
526 0x05000051, 0xa00f0003, 0x3dc816f0, 0x3f00ff97, 0x3e83fe5d, 0x00000000, // def c3, 0.0976999998, 0.503899992, 0.257800013, 0
527 0x05000051, 0xa00f0004, 0x3ee00000, 0xbe9404ea, 0xbe17f62b, 0x00000000, // def c4, 0.4375, -0.289099991, -0.148399994, 0
528 0x05000051, 0xa00f0005, 0xbd8ff972, 0xbebc01a3, 0x3ee00000, 0x00000000, // def c5, -0.0702999979, -0.367199987, 0.4375, 0
529 0x05000051, 0xa00f0006, 0x3f000000, 0x40000000, 0x3f800000, 0xbf00ff97, // def c6, 0.5, 2, 1, -0.503899992
530 0x05000051, 0xa00f0007, 0x3f000000, 0x3f800000, 0x3f000000, 0x00000000, // def c7, 0.5, 1, 0.5, 0
531 0x0200001f, 0x80000000, 0xb0030000, // dcl t0.xy
532 0x0200001f, 0x90000000, 0xa00f0800, // dcl_2d s0
533 0x03000005, 0x80030000, 0xb0e40000, 0xa0c90006, // mul r0.xy, t0, c6.yzxw
534 0x02000001, 0x80030001, 0xa0e40006, // mov r1.xy, c6
535 0x04000004, 0x80010002, 0xb0000000, 0x80550001, 0xa0aa0000, // mad r2.x, t0.x, r1.y, c0.z
536 0x02000001, 0x80020002, 0xb0550000, // mov r2.y, t0.y
537 0x03000042, 0x800f0000, 0x80e40000, 0xa0e40800, // texld r0, r0, s0
538 0x03000042, 0x800f0002, 0x80e40002, 0xa0e40800, // texld r2, r2, s0
539 0x03000005, 0x80080000, 0x80aa0000, 0xa0000003, // mul r0.w, r0.z, c3.x
540 0x04000004, 0x80080000, 0x80550000, 0xa0550003, 0x80ff0000, // mad r0.w, r0.y, c3.y, r0.w
541 0x04000004, 0x80010003, 0x80000000, 0xa0aa0003, 0x80ff0000, // mad r3.x, r0.x, c3.z, r0.w
542 0x03000005, 0x80080000, 0x80aa0000, 0xa0000004, // mul r0.w, r0.z, c4.x
543 0x04000004, 0x80080000, 0x80550000, 0xa0550004, 0x80ff0000, // mad r0.w, r0.y, c4.y, r0.w
544 0x04000004, 0x80020003, 0x80000000, 0xa0aa0004, 0x80ff0000, // mad r3.y, r0.x, c4.z, r0.w
545 0x03000005, 0x80080002, 0x80aa0000, 0xa0000005, // mul r2.w, r0.z, c5.x
546 0x04000004, 0x80080002, 0x80550000, 0xa0550005, 0x80ff0002, // mad r2.w, r0.y, c5.y, r2.w
547 0x04000004, 0x80040003, 0x80000000, 0xa0aa0005, 0x80ff0002, // mad r3.z, r0.x, c5.z, r2.w
548 0x03000002, 0x80070000, 0x80e40003, 0xa0e40001, // add r0.xyz, r3, c1
549 0x02000001, 0x80080000, 0xa0ff0006, // mov r0.w, c6.w
550 0x03000005, 0x80080002, 0x80aa0002, 0xa0000003, // mul r2.w, r2.z, c3.x
551 0x04000004, 0x80080002, 0x80550002, 0xa0550003, 0x80ff0002, // mad r2.w, r2.y, c3.y, r2.w
552 0x04000004, 0x80040003, 0x80000002, 0xa0aa0003, 0x80ff0002, // mad r3.z, r2.x, c3.z, r2.w
553 0x03000005, 0x80080002, 0x80aa0002, 0xa0000004, // mul r2.w, r2.z, c4.x
554 0x04000004, 0x80080002, 0x80550002, 0xa0550004, 0x80ff0002, // mad r2.w, r2.y, c4.y, r2.w
555 0x04000004, 0x80010003, 0x80000002, 0xa0aa0004, 0x80ff0002, // mad r3.x, r2.x, c4.z, r2.w
556 0x03000005, 0x80080003, 0x80aa0002, 0xa0000005, // mul r3.w, r2.z, c5.x
557 0x04000004, 0x80080003, 0x80550002, 0xa0550005, 0x80ff0003, // mad r3.w, r2.y, c5.y, r3.w
558 0x04000004, 0x80020003, 0x80000002, 0xa0aa0005, 0x80ff0003, // mad r3.y, r2.x, c5.z, r3.w
559 0x03000002, 0x80050002, 0x80c90000, 0x80e40003, // add r2.xz, r0.yzxw, r3
560 0x03000002, 0x80020002, 0x80ff0000, 0x80550003, // add r2.y, r0.w, r3.y
561 0x02000001, 0x80110000, 0x80aa0000, // mov_sat r0.x, r0.z
562 0x02000001, 0x80070003, 0xa0e40007, // mov r3.xyz, c7
563 0x04000004, 0x80160000, 0x80d20002, 0x80d20003, 0xa0d20002, // mad_sat r0.yz, r2.zxyw, r3.zxyw, c2.zxyw
564 0x04000004, 0x80180000, 0x80aa0002, 0x80aa0003, 0xa0aa0002, // mad_sat r0.w, r2.z, r3.z, c2.z
565 0x03000005, 0x80010001, 0x80000001, 0xa0000000, // mul r1.x, r1.x, c0.x
566 0x04000004, 0x80010001, 0xb0000000, 0xa0000000, 0x81000001, // mad r1.x, t0.x, c0.x, -r1.x
567 0x04000058, 0x800f0000, 0x80000001, 0xa0ff0003, 0x80e40000, // cmp r0, r1.x, c3.w, r0
568 0x02000001, 0x800f0800, 0x80e40000, // mov oC0, r0
569 0x0000ffff
570 };
571
572 /* RGB to UYVY is same as YUY2 above except for the order of yuv components.
573 * UYVY is defined.
574 */
575 static DWORD const aPSCodeRGBtoUYVY[] =
576 {
577 0xffff0200, // ps_2_0
578 0x05000051, 0xa00f0001, 0xbd84816f, 0xbf00ff97, 0xbf00ff97, 0x00000000, // def c1, -0.0647, -0.503899992, -0.503899992, 0
579 0x05000051, 0xa00f0002, 0xbe80ff97, 0xbd04816f, 0x00000000, 0x00000000, // def c2, -0.251949996, -0.03235, 0, 0
580 0x05000051, 0xa00f0003, 0x3dc816f0, 0x3f00ff97, 0x3e83fe5d, 0x00000000, // def c3, 0.0976999998, 0.503899992, 0.257800013, 0
581 0x05000051, 0xa00f0004, 0x3ee00000, 0xbe9404ea, 0xbe17f62b, 0x00000000, // def c4, 0.4375, -0.289099991, -0.148399994, 0
582 0x05000051, 0xa00f0005, 0xbd8ff972, 0xbebc01a3, 0x3ee00000, 0x00000000, // def c5, -0.0702999979, -0.367199987, 0.4375, 0
583 0x05000051, 0xa00f0006, 0x3f000000, 0x40000000, 0x3f800000, 0xbf00ff97, // def c6, 0.5, 2, 1, -0.503899992
584 0x05000051, 0xa00f0007, 0x3f000000, 0x3f000000, 0x3f800000, 0x00000000, // def c7, 0.5, 0.5, 1, 0
585 0x0200001f, 0x80000000, 0xb0030000, // dcl t0.xy
586 0x0200001f, 0x90000000, 0xa00f0800, // dcl_2d s0
587 0x03000005, 0x80030000, 0xb0e40000, 0xa0c90006, // mul r0.xy, t0, c6.yzxw
588 0x02000001, 0x80030001, 0xa0e40006, // mov r1.xy, c6
589 0x04000004, 0x80010002, 0xb0000000, 0x80550001, 0xa0aa0000, // mad r2.x, t0.x, r1.y, c0.z
590 0x02000001, 0x80020002, 0xb0550000, // mov r2.y, t0.y
591 0x03000042, 0x800f0000, 0x80e40000, 0xa0e40800, // texld r0, r0, s0
592 0x03000042, 0x800f0002, 0x80e40002, 0xa0e40800, // texld r2, r2, s0
593 0x03000005, 0x80080000, 0x80aa0000, 0xa0000003, // mul r0.w, r0.z, c3.x
594 0x04000004, 0x80080000, 0x80550000, 0xa0550003, 0x80ff0000, // mad r0.w, r0.y, c3.y, r0.w
595 0x04000004, 0x80010003, 0x80000000, 0xa0aa0003, 0x80ff0000, // mad r3.x, r0.x, c3.z, r0.w
596 0x03000005, 0x80080000, 0x80aa0000, 0xa0000004, // mul r0.w, r0.z, c4.x
597 0x04000004, 0x80080000, 0x80550000, 0xa0550004, 0x80ff0000, // mad r0.w, r0.y, c4.y, r0.w
598 0x04000004, 0x80020003, 0x80000000, 0xa0aa0004, 0x80ff0000, // mad r3.y, r0.x, c4.z, r0.w
599 0x03000005, 0x80080002, 0x80aa0000, 0xa0000005, // mul r2.w, r0.z, c5.x
600 0x04000004, 0x80080002, 0x80550000, 0xa0550005, 0x80ff0002, // mad r2.w, r0.y, c5.y, r2.w
601 0x04000004, 0x80040003, 0x80000000, 0xa0aa0005, 0x80ff0002, // mad r3.z, r0.x, c5.z, r2.w
602 0x03000002, 0x80070000, 0x80e40003, 0xa0e40001, // add r0.xyz, r3, c1
603 0x02000001, 0x80080000, 0xa0ff0006, // mov r0.w, c6.w
604 0x03000005, 0x80080002, 0x80aa0002, 0xa0000003, // mul r2.w, r2.z, c3.x
605 0x04000004, 0x80080002, 0x80550002, 0xa0550003, 0x80ff0002, // mad r2.w, r2.y, c3.y, r2.w
606 0x04000004, 0x80020003, 0x80000002, 0xa0aa0003, 0x80ff0002, // mad r3.y, r2.x, c3.z, r2.w
607 0x03000005, 0x80080002, 0x80aa0002, 0xa0000004, // mul r2.w, r2.z, c4.x
608 0x04000004, 0x80080002, 0x80550002, 0xa0550004, 0x80ff0002, // mad r2.w, r2.y, c4.y, r2.w
609 0x04000004, 0x80010003, 0x80000002, 0xa0aa0004, 0x80ff0002, // mad r3.x, r2.x, c4.z, r2.w
610 0x03000005, 0x80080003, 0x80aa0002, 0xa0000005, // mul r3.w, r2.z, c5.x
611 0x04000004, 0x80080003, 0x80550002, 0xa0550005, 0x80ff0003, // mad r3.w, r2.y, c5.y, r3.w
612 0x04000004, 0x80040003, 0x80000002, 0xa0aa0005, 0x80ff0003, // mad r3.z, r2.x, c5.z, r3.w
613 0x03000002, 0x80010002, 0x80550000, 0x80000003, // add r2.x, r0.y, r3.x
614 0x03000002, 0x80020002, 0x80000000, 0x80550003, // add r2.y, r0.x, r3.y
615 0x03000002, 0x80040002, 0x80ff0000, 0x80aa0003, // add r2.z, r0.w, r3.z
616 0x02000001, 0x80120000, 0x80aa0000, // mov_sat r0.y, r0.z
617 0x02000001, 0x80070003, 0xa0e40007, // mov r3.xyz, c7
618 0x04000004, 0x80110000, 0x80000002, 0x80000003, 0xa0000002, // mad_sat r0.x, r2.x, r3.x, c2.x
619 0x04000004, 0x80140000, 0x80550002, 0x80550003, 0xa0550002, // mad_sat r0.z, r2.y, r3.y, c2.y
620 0x04000004, 0x80180000, 0x80aa0002, 0x80aa0003, 0xa0aa0002, // mad_sat r0.w, r2.z, r3.z, c2.z
621 0x03000005, 0x80010001, 0x80000001, 0xa0000000, // mul r1.x, r1.x, c0.x
622 0x04000004, 0x80010001, 0xb0000000, 0xa0000000, 0x81000001, // mad r1.x, t0.x, c0.x, -r1.x
623 0x04000058, 0x800f0000, 0x80000001, 0xa0ff0003, 0x80e40000, // cmp r0, r1.x, c3.w, r0
624 0x02000001, 0x800f0800, 0x80e40000, // mov oC0, r0
625 0x0000ffff
626 };
627
628 switch (d3dfmtFrom)
629 {
630 /*
631 * Emulated to ARGB
632 */
633 case D3DFMT_A8B8G8R8:
634 {
635 if (d3dfmtTo == D3DFMT_A8R8G8B8)
636 {
637 pResult->paVS = aVSCode;
638 pResult->paPS = aPSCodeSwapRB;
639
640 return D3D_OK;
641 }
642 } break;
643 case D3DFMT_UYVY:
644 {
645 if (d3dfmtTo == D3DFMT_A8R8G8B8)
646 {
647 pResult->paVS = aVSCode;
648 pResult->paPS = aPSCodeUYVYtoRGB;
649
650 return D3D_OK;
651 }
652 } break;
653 case D3DFMT_YUY2:
654 {
655 if (d3dfmtTo == D3DFMT_A8R8G8B8)
656 {
657 pResult->paVS = aVSCode;
658 pResult->paPS = aPSCodeYUY2toRGB;
659
660 return D3D_OK;
661 }
662 } break;
663
664 /*
665 * ARGB to emulated.
666 */
667 case D3DFMT_A8R8G8B8:
668 {
669 if (d3dfmtTo == D3DFMT_A8B8G8R8)
670 {
671 pResult->paVS = aVSCode;
672 pResult->paPS = aPSCodeSwapRB;
673
674 return D3D_OK;
675 }
676 else if (d3dfmtTo == D3DFMT_UYVY)
677 {
678 pResult->paVS = aVSCode;
679 pResult->paPS = aPSCodeRGBtoUYVY;
680
681 return D3D_OK;
682 }
683 else if (d3dfmtTo == D3DFMT_YUY2)
684 {
685 pResult->paVS = aVSCode;
686 pResult->paPS = aPSCodeRGBtoYUY2;
687
688 return D3D_OK;
689 }
690 } break;
691
692 default:
693 break;
694 }
695
696 return E_NOTIMPL;
697}
698
699class D3D9Conversion
700{
701 private:
702 IDirect3DDevice9Ex *mpDevice;
703
704 /* State objects. */
705 IDirect3DVertexBuffer9 *mpVB;
706 IDirect3DVertexDeclaration9 *mpVertexDecl;
707 IDirect3DVertexShader9 *mpVS;
708 IDirect3DPixelShader9 *mpPS;
709
710 D3D9ConversionParameters mParameters;
711
712 typedef struct D3DSamplerState
713 {
714 D3DSAMPLERSTATETYPE Type;
715 DWORD Value;
716 } D3DSamplerState;
717
718 /* Saved context. */
719 struct
720 {
721 DWORD dwCull;
722 DWORD dwZEnable;
723 IDirect3DSurface9 *pRT;
724 IDirect3DVertexShader9 *pVS;
725 IDirect3DPixelShader9 *pPS;
726 IDirect3DBaseTexture9 *pTexture;
727 float aVSConstantData[4];
728 float aPSConstantData[4];
729 D3DSamplerState aSamplerState[3];
730 } mSaved;
731
732 void destroyConversion();
733 HRESULT saveContextState();
734 HRESULT restoreContextState(PVMSVGA3DCONTEXT pContext);
735 HRESULT initConversion();
736 HRESULT setConversionState(IDirect3DTexture9 *pSourceTexture,
737 uint32_t cWidth,
738 uint32_t cHeight);
739
740 public:
741 enum Direction
742 {
743 FromEmulated,
744 ToEmulated,
745 };
746
747 D3D9Conversion(IDirect3DDevice9Ex *pDevice);
748 ~D3D9Conversion();
749
750 HRESULT SelectConversion(D3DFORMAT d3dfmtFrom, D3DFORMAT d3dfmtTo);
751 HRESULT ConvertTexture(PVMSVGA3DCONTEXT pContext,
752 PVMSVGA3DSURFACE pSurface,
753 Direction enmDirection);
754};
755
756D3D9Conversion::D3D9Conversion(IDirect3DDevice9Ex *pDevice)
757 :
758 mpDevice(pDevice),
759 mpVB(0),
760 mpVertexDecl(0),
761 mpVS(0),
762 mpPS(0)
763{
764 mParameters.paVS = 0;
765 mParameters.paPS = 0;
766 mSaved.dwCull = D3DCULL_NONE;
767 mSaved.dwZEnable = D3DZB_FALSE;
768 mSaved.pRT = 0;
769 mSaved.pVS = 0;
770 mSaved.pPS = 0;
771 mSaved.pTexture = 0;
772 RT_ZERO(mSaved.aVSConstantData);
773 RT_ZERO(mSaved.aPSConstantData);
774 mSaved.aSamplerState[0].Type = D3DSAMP_MAGFILTER;
775 mSaved.aSamplerState[0].Value = D3DTEXF_POINT;
776 mSaved.aSamplerState[1].Type = D3DSAMP_MINFILTER;
777 mSaved.aSamplerState[1].Value = D3DTEXF_POINT;
778 mSaved.aSamplerState[2].Type = D3DSAMP_MIPFILTER;
779 mSaved.aSamplerState[2].Value = D3DTEXF_NONE;
780}
781
782D3D9Conversion::~D3D9Conversion()
783{
784 destroyConversion();
785}
786
787void D3D9Conversion::destroyConversion()
788{
789 D3D_RELEASE(mpVertexDecl);
790 D3D_RELEASE(mpVB);
791 D3D_RELEASE(mpVS);
792 D3D_RELEASE(mpPS);
793}
794
795HRESULT D3D9Conversion::saveContextState()
796{
797 /*
798 * This is probably faster than
799 * IDirect3DStateBlock9 *mpStateBlock;
800 * mpDevice->CreateStateBlock(D3DSBT_ALL, &mpStateBlock);
801 */
802 HRESULT hr = mpDevice->GetRenderState(D3DRS_CULLMODE, &mSaved.dwCull);
803 AssertReturn(hr == D3D_OK, hr);
804
805 hr = mpDevice->GetRenderState(D3DRS_ZENABLE, &mSaved.dwZEnable);
806 AssertReturn(hr == D3D_OK, hr);
807
808 hr = mpDevice->GetRenderTarget(0, &mSaved.pRT);
809 AssertReturn(hr == D3D_OK, hr);
810
811 hr = mpDevice->GetVertexShader(&mSaved.pVS);
812 AssertReturn(hr == D3D_OK, hr);
813
814 hr = mpDevice->GetPixelShader(&mSaved.pPS);
815 AssertReturn(hr == D3D_OK, hr);
816
817 hr = mpDevice->GetTexture(0, &mSaved.pTexture);
818 AssertReturn(hr == D3D_OK, hr);
819
820 hr = mpDevice->GetVertexShaderConstantF(0, mSaved.aVSConstantData, 1);
821 AssertReturn(hr == D3D_OK, hr);
822
823 hr = mpDevice->GetPixelShaderConstantF(0, mSaved.aPSConstantData, 1);
824 AssertReturn(hr == D3D_OK, hr);
825
826 for (uint32_t i = 0; i < RT_ELEMENTS(mSaved.aSamplerState); ++i)
827 {
828 hr = mpDevice->GetSamplerState(0, mSaved.aSamplerState[i].Type, &mSaved.aSamplerState[i].Value);
829 AssertReturn(hr == D3D_OK, hr);
830 }
831
832 return hr;
833}
834
835HRESULT D3D9Conversion::restoreContextState(PVMSVGA3DCONTEXT pContext)
836{
837 HRESULT hr = mpDevice->SetRenderState(D3DRS_CULLMODE, mSaved.dwCull);
838 Assert(hr == D3D_OK);
839
840 hr = mpDevice->SetRenderState(D3DRS_ZENABLE, mSaved.dwZEnable);
841 Assert(hr == D3D_OK);
842
843 hr = mpDevice->SetRenderTarget(0, mSaved.pRT);
844 D3D_RELEASE(mSaved.pRT); /* GetRenderTarget increases the internal reference count. */
845 Assert(hr == D3D_OK);
846
847 hr = mpDevice->SetVertexDeclaration(pContext->d3dState.pVertexDecl);
848 Assert(hr == D3D_OK);
849
850 hr = mpDevice->SetVertexShader(mSaved.pVS);
851 Assert(hr == D3D_OK);
852
853 hr = mpDevice->SetPixelShader(mSaved.pPS);
854 Assert(hr == D3D_OK);
855
856 hr = mpDevice->SetTexture(0, mSaved.pTexture);
857 D3D_RELEASE(mSaved.pTexture); /* GetTexture increases the internal reference count. */
858 Assert(hr == D3D_OK);
859
860 hr = mpDevice->SetVertexShaderConstantF(0, mSaved.aVSConstantData, 1);
861 Assert(hr == D3D_OK);
862
863 hr = mpDevice->SetPixelShaderConstantF(0, mSaved.aPSConstantData, 1);
864 Assert(hr == D3D_OK);
865
866 for (uint32_t i = 0; i < RT_ELEMENTS(mSaved.aSamplerState); ++i)
867 {
868 hr = mpDevice->SetSamplerState(0, mSaved.aSamplerState[i].Type, mSaved.aSamplerState[i].Value);
869 Assert(hr == D3D_OK);
870 }
871
872 return hr;
873}
874
875HRESULT D3D9Conversion::initConversion()
876{
877 static D3DVERTEXELEMENT9 const aVertexElements[] =
878 {
879 {0, 0, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
880 {0, 8, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
881 D3DDECL_END()
882 };
883
884 HRESULT hr = mpDevice->CreateVertexDeclaration(aVertexElements, &mpVertexDecl);
885 AssertReturn(hr == D3D_OK, hr);
886
887 hr = mpDevice->CreateVertexBuffer(6 * sizeof(Vertex),
888 0, /* D3DUSAGE_* */
889 0, /* FVF */
890 D3DPOOL_DEFAULT,
891 &mpVB,
892 0);
893 AssertReturn(hr == D3D_OK, hr);
894
895 hr = mpDevice->CreateVertexShader(mParameters.paVS, &mpVS);
896 AssertReturn(hr == D3D_OK, hr);
897
898 hr = mpDevice->CreatePixelShader(mParameters.paPS, &mpPS);
899 AssertReturn(hr == D3D_OK, hr);
900
901 return hr;
902}
903
904HRESULT D3D9Conversion::setConversionState(IDirect3DTexture9 *pSourceTexture,
905 uint32_t cWidth,
906 uint32_t cHeight)
907{
908 /* Subtract 0.5 to line up the pixel centers with texels
909 * https://docs.microsoft.com/en-us/windows/win32/direct3d9/directly-mapping-texels-to-pixels
910 */
911 float const xLeft = -0.5f;
912 float const xRight = (cWidth - 1) - 0.5f;
913 float const yTop = -0.5f;
914 float const yBottom = (cHeight - 1) - 0.5f;
915
916 Vertex const aVertices[] =
917 {
918 { xLeft, yTop, 0.0f, 0.0f},
919 { xRight, yTop, 1.0f, 0.0f},
920 { xRight, yBottom, 1.0f, 1.0f},
921
922 { xLeft, yTop, 0.0f, 0.0f},
923 { xRight, yBottom, 1.0f, 1.0f},
924 { xLeft, yBottom, 0.0f, 1.0f},
925 };
926
927 HRESULT hr = d3dCopyToVertexBuffer(mpVB, aVertices, sizeof(aVertices));
928 AssertReturn(hr == D3D_OK, hr);
929
930 /* No need to save the stream source, because vmsvga3dDrawPrimitives always sets it. */
931 hr = mpDevice->SetStreamSource(0, mpVB, 0, sizeof(Vertex));
932 AssertReturn(hr == D3D_OK, hr);
933
934 /* Stored in pContext->d3dState.pVertexDecl. */
935 hr = mpDevice->SetVertexDeclaration(mpVertexDecl);
936 AssertReturn(hr == D3D_OK, hr);
937
938 /* Saved by saveContextState. */
939 hr = mpDevice->SetVertexShader(mpVS);
940 AssertReturn(hr == D3D_OK, hr);
941
942 /* Saved by saveContextState. */
943 hr = mpDevice->SetPixelShader(mpPS);
944 AssertReturn(hr == D3D_OK, hr);
945
946 /* Saved by saveContextState. */
947 hr = mpDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
948 AssertReturn(hr == D3D_OK, hr);
949
950 /* Saved by saveContextState. */
951 hr = mpDevice->SetRenderState(D3DRS_ZENABLE, D3DZB_FALSE);
952 AssertReturn(hr == D3D_OK, hr);
953
954 /* Saved by saveContextState. */
955 hr = mpDevice->SetTexture(0, pSourceTexture);
956 AssertReturn(hr == D3D_OK, hr);
957
958 float aTextureInfo[4];
959 aTextureInfo[0] = (float)cWidth;
960 aTextureInfo[1] = (float)cHeight;
961 aTextureInfo[2] = 1.0f / (float)cWidth; /* Pixel width in texture coords. */
962 aTextureInfo[3] = 1.0f / (float)cHeight; /* Pixel height in texture coords. */
963
964 /* Saved by saveContextState. */
965 hr = mpDevice->SetVertexShaderConstantF(0, aTextureInfo, 1);
966 AssertReturn(hr == D3D_OK, hr);
967
968 /* Saved by saveContextState. */
969 hr = mpDevice->SetPixelShaderConstantF(0, aTextureInfo, 1);
970 AssertReturn(hr == D3D_OK, hr);
971
972 /* Saved by saveContextState. */
973 hr = mpDevice->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_POINT);
974 AssertReturn(hr == D3D_OK, hr);
975 hr = mpDevice->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_POINT);
976 AssertReturn(hr == D3D_OK, hr);
977 hr = mpDevice->SetSamplerState(0, D3DSAMP_MIPFILTER, D3DTEXF_NONE);
978 AssertReturn(hr == D3D_OK, hr);
979
980 return hr;
981}
982
983
984HRESULT D3D9Conversion::SelectConversion(D3DFORMAT d3dfmtFrom, D3DFORMAT d3dfmtTo)
985{
986 /** @todo d3d9SelectConversion should be a member. Move the code here? */
987 HRESULT hr = d3d9SelectConversion(d3dfmtFrom, d3dfmtTo, &mParameters);
988 return hr;
989}
990
991HRESULT D3D9Conversion::ConvertTexture(PVMSVGA3DCONTEXT pContext,
992 PVMSVGA3DSURFACE pSurface,
993 Direction enmDirection)
994{
995 IDirect3DTexture9 *pSourceTexture;
996 IDirect3DTexture9 *pTargetTexture;
997 D3D9TextureType enmTargetType;
998
999 if (enmDirection == FromEmulated)
1000 {
1001 pSourceTexture = pSurface->emulated.pTexture;
1002 pTargetTexture = pSurface->u.pTexture;
1003 enmTargetType = D3D9TextureType_Texture;
1004 }
1005 else if (enmDirection == ToEmulated)
1006 {
1007 pSourceTexture = pSurface->u.pTexture;
1008 pTargetTexture = pSurface->emulated.pTexture;
1009 enmTargetType = D3D9TextureType_Emulated;
1010 }
1011 else
1012 AssertFailedReturn(E_INVALIDARG);
1013
1014 AssertPtrReturn(pSourceTexture, E_INVALIDARG);
1015 AssertPtrReturn(pTargetTexture, E_INVALIDARG);
1016
1017 HRESULT hr = saveContextState();
1018 if (hr == D3D_OK)
1019 {
1020 hr = initConversion();
1021 if (hr == D3D_OK)
1022 {
1023 uint32_t const cWidth = pSurface->paMipmapLevels[0].mipmapSize.width;
1024 uint32_t const cHeight = pSurface->paMipmapLevels[0].mipmapSize.height;
1025
1026 hr = setConversionState(pSourceTexture, cWidth, cHeight);
1027 if (hr == D3D_OK)
1028 {
1029 hr = mpDevice->BeginScene();
1030 Assert(hr == D3D_OK);
1031 if (hr == D3D_OK)
1032 {
1033 for (DWORD iFace = 0; iFace < pSurface->cFaces; ++iFace)
1034 {
1035 DWORD const cMipLevels = pTargetTexture->GetLevelCount();
1036 for (DWORD iMipmap = 0; iMipmap < cMipLevels && hr == D3D_OK; ++iMipmap)
1037 {
1038 IDirect3DSurface9 *pRT = NULL;
1039 hr = D3D9GetTextureLevel(pSurface, enmTargetType, iFace, iMipmap, &pRT);
1040 Assert(hr == D3D_OK);
1041 if (hr == D3D_OK)
1042 {
1043 hr = mpDevice->SetRenderTarget(0, pRT);
1044 Assert(hr == D3D_OK);
1045 if (hr == D3D_OK)
1046 {
1047 hr = mpDevice->DrawPrimitive(D3DPT_TRIANGLELIST, 0, 2);
1048 Assert(hr == D3D_OK);
1049 }
1050
1051 D3D_RELEASE(pRT);
1052 }
1053 }
1054 }
1055
1056 hr = mpDevice->EndScene();
1057 Assert(hr == D3D_OK);
1058 }
1059 }
1060 }
1061
1062 hr = restoreContextState(pContext);
1063 }
1064
1065 destroyConversion();
1066
1067 return hr;
1068}
1069
1070
1071HRESULT D3D9UpdateTexture(PVMSVGA3DCONTEXT pContext,
1072 PVMSVGA3DSURFACE pSurface)
1073{
1074 HRESULT hr = S_OK;
1075
1076 if (pSurface->formatD3D == pSurface->d3dfmtRequested)
1077 {
1078 hr = pContext->pDevice->UpdateTexture(pSurface->bounce.pTexture, pSurface->u.pTexture);
1079 }
1080 else
1081 {
1082 if (pSurface->enmD3DResType == VMSVGA3D_D3DRESTYPE_TEXTURE)
1083 {
1084 hr = pContext->pDevice->UpdateTexture(pSurface->bounce.pTexture, pSurface->emulated.pTexture);
1085 if (hr == D3D_OK)
1086 {
1087 D3D9Conversion conv(pContext->pDevice);
1088 hr = conv.SelectConversion(pSurface->d3dfmtRequested, pSurface->formatD3D);
1089 if (hr == D3D_OK)
1090 {
1091 hr = conv.ConvertTexture(pContext, pSurface, D3D9Conversion::FromEmulated);
1092 }
1093 }
1094 }
1095 else
1096 {
1097 /** @todo Cubemaps and maybe volume textures. */
1098 hr = pContext->pDevice->UpdateTexture(pSurface->bounce.pTexture, pSurface->u.pTexture);
1099 }
1100 }
1101
1102 return hr;
1103}
1104
1105HRESULT D3D9GetSurfaceLevel(PVMSVGA3DSURFACE pSurface,
1106 uint32_t uFace,
1107 uint32_t uMipmap,
1108 bool fBounce,
1109 IDirect3DSurface9 **ppD3DSurface)
1110{
1111 HRESULT hr;
1112
1113 if ( pSurface->enmD3DResType == VMSVGA3D_D3DRESTYPE_CUBE_TEXTURE
1114 || pSurface->enmD3DResType == VMSVGA3D_D3DRESTYPE_TEXTURE)
1115 {
1116 D3D9TextureType enmType;
1117 if (fBounce)
1118 enmType = D3D9TextureType_Bounce;
1119 else if (pSurface->formatD3D != pSurface->d3dfmtRequested)
1120 enmType = D3D9TextureType_Emulated;
1121 else
1122 enmType = D3D9TextureType_Texture;
1123
1124 hr = D3D9GetTextureLevel(pSurface, enmType, uFace, uMipmap, ppD3DSurface);
1125 }
1126 else if (pSurface->enmD3DResType == VMSVGA3D_D3DRESTYPE_SURFACE)
1127 {
1128 pSurface->u.pSurface->AddRef();
1129 *ppD3DSurface = pSurface->u.pSurface;
1130 hr = S_OK;
1131 }
1132 else
1133 {
1134 AssertMsgFailed(("No surface for type %d\n", pSurface->enmD3DResType));
1135 hr = E_INVALIDARG;
1136 }
1137
1138 return hr;
1139}
1140
1141/** Copy the texture content to the bounce texture.
1142 */
1143HRESULT D3D9GetRenderTargetData(PVMSVGA3DCONTEXT pContext,
1144 PVMSVGA3DSURFACE pSurface,
1145 uint32_t uFace,
1146 uint32_t uMipmap)
1147{
1148 HRESULT hr;
1149
1150 /* Get the corresponding bounce texture surface. */
1151 IDirect3DSurface9 *pDst = NULL;
1152 hr = D3D9GetSurfaceLevel(pSurface, uFace, uMipmap, true, &pDst);
1153 AssertReturn(hr == D3D_OK, hr);
1154
1155 /* Get the actual texture surface, emulated or actual. */
1156 IDirect3DSurface9 *pSrc = NULL;
1157 hr = D3D9GetSurfaceLevel(pSurface, uFace, uMipmap, false, &pSrc);
1158 AssertReturnStmt(hr == D3D_OK,
1159 D3D_RELEASE(pDst), hr);
1160
1161 Assert(pDst != pSrc);
1162
1163 if (pSurface->formatD3D == pSurface->d3dfmtRequested)
1164 {
1165 hr = pContext->pDevice->GetRenderTargetData(pSrc, pDst);
1166 AssertMsg(hr == D3D_OK, ("GetRenderTargetData failed with %x\n", hr));
1167 }
1168 else
1169 {
1170 D3D9Conversion conv(pContext->pDevice);
1171 hr = conv.SelectConversion(pSurface->formatD3D, pSurface->d3dfmtRequested);
1172 if (hr == D3D_OK)
1173 {
1174 hr = conv.ConvertTexture(pContext, pSurface, D3D9Conversion::ToEmulated);
1175 }
1176
1177 if (hr == D3D_OK)
1178 {
1179 hr = pContext->pDevice->GetRenderTargetData(pSrc, pDst);
1180 AssertMsg(hr == D3D_OK, ("GetRenderTargetData failed with %x\n", hr));
1181 }
1182 }
1183
1184 D3D_RELEASE(pSrc);
1185 D3D_RELEASE(pDst);
1186 return hr;
1187}
1188
1189D3DFORMAT D3D9GetActualFormat(PVMSVGA3DSTATE pState, D3DFORMAT d3dfmtRequested)
1190{
1191 RT_NOREF(pState);
1192
1193 switch (d3dfmtRequested)
1194 {
1195 case D3DFMT_UYVY:
1196 if (!pState->fSupportedFormatUYVY) return D3DFMT_A8R8G8B8;
1197 break;
1198 case D3DFMT_YUY2:
1199 if (!pState->fSupportedFormatYUY2) return D3DFMT_A8R8G8B8;
1200 break;
1201 case D3DFMT_A8B8G8R8:
1202 if (!pState->fSupportedFormatA8B8G8R8) return D3DFMT_A8R8G8B8;
1203 break;
1204 default:
1205 break;
1206 }
1207
1208 /* Use the requested format. No emulation required. */
1209 return d3dfmtRequested;
1210}
1211
1212bool D3D9CheckDeviceFormat(IDirect3D9 *pD3D9, DWORD Usage, D3DRESOURCETYPE RType, D3DFORMAT CheckFormat)
1213{
1214 HRESULT hr = pD3D9->CheckDeviceFormat(D3DADAPTER_DEFAULT,
1215 D3DDEVTYPE_HAL,
1216 D3DFMT_X8R8G8B8, /* assume standard 32-bit display mode */
1217 Usage,
1218 RType,
1219 CheckFormat);
1220 return (hr == D3D_OK);
1221}
Note: See TracBrowser for help on using the repository browser.

© 2023 Oracle
ContactPrivacy policyTerms of Use