[WASAPI] fix stream types and frequencies enumeration
[xbmc.git] / xbmc / guilib / DirectXGraphics.cpp
blob5bab89575e9255cdbe048bda54631e0a8b7615fb
1 /*
2 * Copyright (C) 2005-2018 Team Kodi
3 * This file is part of Kodi - https://kodi.tv
5 * SPDX-License-Identifier: GPL-2.0-or-later
6 * See LICENSES/README.md for more information.
7 */
9 #include "DirectXGraphics.h"
11 #include "Texture.h"
12 #include "XBTF.h"
14 LPVOID XPhysicalAlloc(SIZE_T s, DWORD ulPhysicalAddress, DWORD ulAlignment, DWORD flProtect)
16 return malloc(s);
19 void XPhysicalFree(LPVOID lpAddress)
21 free(lpAddress);
24 DWORD GetD3DFormat(XB_D3DFORMAT format)
26 #ifndef MAKEFOURCC
27 #define MAKEFOURCC(ch0, ch1, ch2, ch3) \
28 ((DWORD)(BYTE)(ch0) | ((DWORD)(BYTE)(ch1) << 8) | \
29 ((DWORD)(BYTE)(ch2) << 16) | ((DWORD)(BYTE)(ch3) << 24 ))
30 #endif
31 switch (format)
33 case XB_D3DFMT_A8R8G8B8:
34 case XB_D3DFMT_LIN_A8R8G8B8:
35 case XB_D3DFMT_P8:
36 return 21;
37 case XB_D3DFMT_DXT1:
38 return MAKEFOURCC('D', 'X', 'T', '1');
39 case XB_D3DFMT_DXT2:
40 return MAKEFOURCC('D', 'X', 'T', '2');
41 case XB_D3DFMT_DXT4:
42 return MAKEFOURCC('D', 'X', 'T', '4');
43 default:
44 return 0;
48 DWORD BytesPerPixelFromFormat(XB_D3DFORMAT format)
50 switch (format)
52 case XB_D3DFMT_A8R8G8B8:
53 case XB_D3DFMT_LIN_A8R8G8B8:
54 case XB_D3DFMT_DXT4:
55 return 4;
56 case XB_D3DFMT_P8:
57 case XB_D3DFMT_DXT1:
58 case XB_D3DFMT_DXT2:
59 return 1;
60 default:
61 return 0;
65 bool IsPalettedFormat(XB_D3DFORMAT format)
67 if (format == XB_D3DFMT_P8)
68 return true;
69 return false;
72 void ParseTextureHeader(D3DTexture *tex, XB_D3DFORMAT &fmt, DWORD &width, DWORD &height, DWORD &pitch, DWORD &offset)
74 fmt = (XB_D3DFORMAT)((tex->Format & 0xff00) >> 8);
75 offset = tex->Data;
76 if (tex->Size)
78 width = (tex->Size & 0x00000fff) + 1;
79 height = ((tex->Size & 0x00fff000) >> 12) + 1;
80 pitch = (((tex->Size & 0xff000000) >> 24) + 1) << 6;
82 else
84 width = 1 << ((tex->Format & 0x00f00000) >> 20);
85 height = 1 << ((tex->Format & 0x0f000000) >> 24);
86 pitch = width * BytesPerPixelFromFormat(fmt);
90 bool IsSwizzledFormat(XB_D3DFORMAT format)
92 switch (format)
94 case XB_D3DFMT_A8R8G8B8:
95 case XB_D3DFMT_P8:
96 return true;
97 default:
98 return false;
102 // Unswizzle.
103 // Format is:
105 // 00 01 04 05
106 // 02 03 06 07
107 // 08 09 12 13
108 // 10 11 14 15 ...
110 // Currently only works for 32bit and 8bit textures, with power of 2 width and height
111 void Unswizzle(const void *src, unsigned int depth, unsigned int width, unsigned int height, void *dest)
113 if (height == 0 || width == 0)
114 return;
116 for (UINT y = 0; y < height; y++)
118 UINT sy = 0;
119 if (y < width)
121 for (int bit = 0; bit < 16; bit++)
122 sy |= ((y >> bit) & 1) << (2*bit);
123 sy <<= 1; // y counts twice
125 else
127 UINT y_mask = y % width;
128 for (int bit = 0; bit < 16; bit++)
129 sy |= ((y_mask >> bit) & 1) << (2*bit);
130 sy <<= 1; // y counts twice
131 sy += (y / width) * width * width;
133 BYTE *d = (BYTE *)dest + y * width * depth;
134 for (UINT x = 0; x < width; x++)
136 UINT sx = 0;
137 if (x < height * 2)
139 for (int bit = 0; bit < 16; bit++)
140 sx |= ((x >> bit) & 1) << (2*bit);
142 else
144 int x_mask = x % (2*height);
145 for (int bit = 0; bit < 16; bit++)
146 sx |= ((x_mask >> bit) & 1) << (2*bit);
147 sx += (x / (2 * height)) * 2 * height * height;
149 BYTE *s = (BYTE *)src + (sx + sy)*depth;
150 for (unsigned int i = 0; i < depth; ++i)
151 *d++ = *s++;
156 void DXT1toARGB(const void *src, void *dest, unsigned int destWidth)
158 const BYTE *b = (const BYTE *)src;
159 // colour is in R5G6B5 format, convert to R8G8B8
160 DWORD colour[4];
161 BYTE red[4];
162 BYTE green[4];
163 BYTE blue[4];
164 for (int i = 0; i < 2; i++)
166 red[i] = b[2*i+1] & 0xf8;
167 green[i] = ((b[2*i+1] & 0x7) << 5) | ((b[2*i] & 0xe0) >> 3);
168 blue[i] = (b[2*i] & 0x1f) << 3;
169 colour[i] = (red[i] << 16) | (green[i] << 8) | blue[i];
171 if (colour[0] > colour[1])
173 red[2] = (2 * red[0] + red[1] + 1) / 3;
174 green[2] = (2 * green[0] + green[1] + 1) / 3;
175 blue[2] = (2 * blue[0] + blue[1] + 1) / 3;
176 red[3] = (red[0] + 2 * red[1] + 1) / 3;
177 green[3] = (green[0] + 2 * green[1] + 1) / 3;
178 blue[3] = (blue[0] + 2 * blue[1] + 1) / 3;
179 for (int i = 0; i < 4; i++)
180 colour[i] = (red[i] << 16) | (green[i] << 8) | blue[i] | 0xFF000000;
182 else
184 red[2] = (red[0] + red[1]) / 2;
185 green[2] = (green[0] + green[1]) / 2;
186 blue[2] = (blue[0] + blue[1]) / 2;
187 for (int i = 0; i < 3; i++)
188 colour[i] = (red[i] << 16) | (green[i] << 8) | blue[i] | 0xFF000000;
189 colour[3] = 0; // transparent
191 // ok, now grab the bits
192 for (int y = 0; y < 4; y++)
194 DWORD *d = (DWORD *)dest + destWidth * y;
195 *d++ = colour[(b[4 + y] & 0x03)];
196 *d++ = colour[(b[4 + y] & 0x0c) >> 2];
197 *d++ = colour[(b[4 + y] & 0x30) >> 4];
198 *d++ = colour[(b[4 + y] & 0xc0) >> 6];
202 void DXT4toARGB(const void *src, void *dest, unsigned int destWidth)
204 const BYTE *b = (const BYTE *)src;
205 BYTE alpha[8];
206 alpha[0] = b[0];
207 alpha[1] = b[1];
208 if (alpha[0] > alpha[1])
210 alpha[2] = (6 * alpha[0] + 1 * alpha[1]+ 3) / 7;
211 alpha[3] = (5 * alpha[0] + 2 * alpha[1] + 3) / 7; // bit code 011
212 alpha[4] = (4 * alpha[0] + 3 * alpha[1] + 3) / 7; // bit code 100
213 alpha[5] = (3 * alpha[0] + 4 * alpha[1] + 3) / 7; // bit code 101
214 alpha[6] = (2 * alpha[0] + 5 * alpha[1] + 3) / 7; // bit code 110
215 alpha[7] = (1 * alpha[0] + 6 * alpha[1] + 3) / 7; // bit code 111
217 else
219 alpha[2] = (4 * alpha[0] + 1 * alpha[1] + 2) / 5; // Bit code 010
220 alpha[3] = (3 * alpha[0] + 2 * alpha[1] + 2) / 5; // Bit code 011
221 alpha[4] = (2 * alpha[0] + 3 * alpha[1] + 2) / 5; // Bit code 100
222 alpha[5] = (1 * alpha[0] + 4 * alpha[1] + 2) / 5; // Bit code 101
223 alpha[6] = 0; // Bit code 110
224 alpha[7] = 255; // Bit code 111
226 // ok, now grab the bits
227 BYTE a[4][4];
228 a[0][0] = alpha[(b[2] & 0xe0) >> 5];
229 a[0][1] = alpha[(b[2] & 0x1c) >> 2];
230 a[0][2] = alpha[((b[2] & 0x03) << 1) | ((b[3] & 0x80) >> 7)];
231 a[0][3] = alpha[(b[3] & 0x70) >> 4];
232 a[1][0] = alpha[(b[3] & 0x0e) >> 1];
233 a[1][1] = alpha[((b[3] & 0x01) << 2) | ((b[4] & 0xc0) >> 6)];
234 a[1][2] = alpha[(b[4] & 0x38) >> 3];
235 a[1][3] = alpha[(b[4] & 0x07)];
236 a[2][0] = alpha[(b[5] & 0xe0) >> 5];
237 a[2][1] = alpha[(b[5] & 0x1c) >> 2];
238 a[2][2] = alpha[((b[5] & 0x03) << 1) | ((b[6] & 0x80) >> 7)];
239 a[2][3] = alpha[(b[6] & 0x70) >> 4];
240 a[3][0] = alpha[(b[6] & 0x0e) >> 1];
241 a[3][1] = alpha[((b[6] & 0x01) << 2) | ((b[7] & 0xc0) >> 6)];
242 a[3][2] = alpha[(b[7] & 0x38) >> 3];
243 a[3][3] = alpha[(b[7] & 0x07)];
245 b = (BYTE *)src + 8;
246 // colour is in R5G6B5 format, convert to R8G8B8
247 DWORD colour[4];
248 BYTE red[4];
249 BYTE green[4];
250 BYTE blue[4];
251 for (int i = 0; i < 2; i++)
253 red[i] = b[2*i+1] & 0xf8;
254 green[i] = ((b[2*i+1] & 0x7) << 5) | ((b[2*i] & 0xe0) >> 3);
255 blue[i] = (b[2*i] & 0x1f) << 3;
257 red[2] = (2 * red[0] + red[1] + 1) / 3;
258 green[2] = (2 * green[0] + green[1] + 1) / 3;
259 blue[2] = (2 * blue[0] + blue[1] + 1) / 3;
260 red[3] = (red[0] + 2 * red[1] + 1) / 3;
261 green[3] = (green[0] + 2 * green[1] + 1) / 3;
262 blue[3] = (blue[0] + 2 * blue[1] + 1) / 3;
263 for (int i = 0; i < 4; i++)
264 colour[i] = (red[i] << 16) | (green[i] << 8) | blue[i];
265 // and assign them to our texture
266 for (int y = 0; y < 4; y++)
268 DWORD *d = (DWORD *)dest + destWidth * y;
269 *d++ = colour[(b[4 + y] & 0x03)] | (a[y][0] << 24);
270 *d++ = colour[(b[4 + y] & 0x0e) >> 2] | (a[y][1] << 24);
271 *d++ = colour[(b[4 + y] & 0x30) >> 4] | (a[y][2] << 24);
272 *d++ = colour[(b[4 + y] & 0xe0) >> 6] | (a[y][3] << 24);
277 void ConvertDXT1(const void *src, unsigned int width, unsigned int height, void *dest)
279 for (unsigned int y = 0; y < height; y += 4)
281 for (unsigned int x = 0; x < width; x += 4)
283 const BYTE *s = (const BYTE *)src + y * width / 2 + x * 2;
284 DWORD *d = (DWORD *)dest + y * width + x;
285 DXT1toARGB(s, d, width);
290 void ConvertDXT4(const void *src, unsigned int width, unsigned int height, void *dest)
292 // [4 4 4 4][4 4 4 4]
296 for (unsigned int y = 0; y < height; y += 4)
298 for (unsigned int x = 0; x < width; x += 4)
300 const BYTE *s = (const BYTE *)src + y * width + x * 4;
301 DWORD *d = (DWORD *)dest + y * width + x;
302 DXT4toARGB(s, d, width);
307 void GetTextureFromData(D3DTexture* pTex, void* texData, std::unique_ptr<CTexture>* ppTexture)
309 XB_D3DFORMAT fmt;
310 DWORD width, height, pitch, offset;
311 ParseTextureHeader(pTex, fmt, width, height, pitch, offset);
313 *ppTexture = CTexture::CreateTexture(width, height, XB_FMT_A8R8G8B8);
315 if (*ppTexture)
317 BYTE *texDataStart = (BYTE *)texData;
318 COLOR *color = (COLOR *)texData;
319 texDataStart += offset;
320 /* DXMERGE - We should really support DXT1,DXT2 and DXT4 in both renderers
321 Perhaps we should extend CTexture::Update() to support a bunch of different texture types
322 Rather than assuming linear 32bits
323 We could just override, as at least then all the loading code from various texture formats
324 will be in one place
326 BYTE *dstPixels = (BYTE *)lr.pBits;
327 DWORD destPitch = lr.Pitch;
328 if (fmt == XB_D3DFMT_DXT1) // Not sure if these are 100% correct, but they seem to work :P
330 pitch /= 2;
331 destPitch /= 4;
333 else if (fmt == XB_D3DFMT_DXT2)
335 destPitch /= 4;
337 else if (fmt == XB_D3DFMT_DXT4)
339 pitch /= 4;
340 destPitch /= 4;
343 if (fmt == XB_D3DFMT_DXT1)
345 pitch = width * 4;
346 BYTE *decoded = new BYTE[pitch * height];
347 ConvertDXT1(texDataStart, width, height, decoded);
348 texDataStart = decoded;
350 else if (fmt == XB_D3DFMT_DXT2 || fmt == XB_D3DFMT_DXT4)
352 pitch = width * 4;
353 BYTE *decoded = new BYTE[pitch * height];
354 ConvertDXT4(texDataStart, width, height, decoded);
355 texDataStart = decoded;
357 if (IsSwizzledFormat(fmt))
358 { // first we unswizzle
359 BYTE *unswizzled = new BYTE[pitch * height];
360 Unswizzle(texDataStart, BytesPerPixelFromFormat(fmt), width, height, unswizzled);
361 texDataStart = unswizzled;
364 if (IsPalettedFormat(fmt))
365 (*ppTexture)->LoadPaletted(width, height, pitch, XB_FMT_A8R8G8B8, texDataStart, color);
366 else
367 (*ppTexture)->LoadFromMemory(width, height, pitch, XB_FMT_A8R8G8B8, true, texDataStart);
369 if (IsSwizzledFormat(fmt) || fmt == XB_D3DFMT_DXT1 || fmt == XB_D3DFMT_DXT2 || fmt == XB_D3DFMT_DXT4)
371 delete[] texDataStart;