Slightly optimize uploading D3DFMT_A8R8G8B8 data to textures.
[dolphin.git] / Source / Plugins / Plugin_VideoDX9 / Src / D3DTexture.cpp
blob4ddc7950fac5a6aa0c5007b0517f5961c76f8114
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/
18 #include "D3DBase.h"
19 #include "D3DTexture.h"
21 namespace D3D
24 LPDIRECT3DTEXTURE9 CreateTexture2D(const u8* buffer, const int width, const int height, const int pitch, D3DFORMAT fmt, bool swap_r_b, int levels)
26 u32* pBuffer = (u32*)buffer;
27 LPDIRECT3DTEXTURE9 pTexture;
29 // crazy bitmagic, sorry :)
30 bool isPow2 = !((width&(width-1)) || (height&(height-1)));
31 bool bExpand = false;
33 if (fmt == D3DFMT_A8P8) {
34 fmt = D3DFMT_A8L8;
35 bExpand = true;
38 HRESULT hr;
39 // TODO(ector): Allow mipmaps for non-pow textures on newer cards?
40 // TODO(ector): Use the game-specified mipmaps?
41 if (levels > 0)
42 hr = dev->CreateTexture(width, height, levels, 0, fmt, D3DPOOL_MANAGED, &pTexture, NULL);
43 else
44 hr = dev->CreateTexture(width, height, 0, D3DUSAGE_AUTOGENMIPMAP, fmt, D3DPOOL_MANAGED, &pTexture, NULL);
46 if (FAILED(hr))
47 return 0;
48 int level = 0;
49 D3DLOCKED_RECT Lock;
50 pTexture->LockRect(level, &Lock, NULL, 0);
51 switch (fmt)
53 case D3DFMT_L8:
54 case D3DFMT_A8:
55 case D3DFMT_A4L4:
57 const u8 *pIn = buffer;
58 for (int y = 0; y < height; y++)
60 u8* pBits = ((u8*)Lock.pBits + (y * Lock.Pitch));
61 memcpy(pBits, pIn, width);
62 pIn += pitch;
65 break;
66 case D3DFMT_R5G6B5:
68 const u16 *pIn = (u16*)buffer;
69 for (int y = 0; y < height; y++)
71 u16* pBits = (u16*)((u8*)Lock.pBits + (y * Lock.Pitch));
72 memcpy(pBits, pIn, width * 2);
73 pIn += pitch;
76 break;
77 case D3DFMT_A8L8:
79 if (bExpand) { // I8
80 const u8 *pIn = buffer;
81 // TODO(XK): Find a better way that does not involve either unpacking
82 // or downsampling (i.e. A4L4)
83 for (int y = 0; y < height; y++)
85 u8* pBits = ((u8*)Lock.pBits + (y * Lock.Pitch));
86 for(int i = 0; i < width * 2; i += 2) {
87 pBits[i] = pIn[i / 2];
88 pBits[i + 1] = pIn[i / 2];
90 pIn += pitch;
92 } else { // IA8
93 const u16 *pIn = (u16*)buffer;
95 for (int y = 0; y < height; y++)
97 u16* pBits = (u16*)((u8*)Lock.pBits + (y * Lock.Pitch));
98 memcpy(pBits, pIn, width * 2);
99 pIn += pitch;
103 break;
104 case D3DFMT_A8R8G8B8:
106 if(pitch * 4 == Lock.Pitch && !swap_r_b)
108 memcpy(Lock.pBits,buffer,Lock.Pitch*height);
110 else
112 u32* pIn = pBuffer;
113 if (!swap_r_b) {
114 for (int y = 0; y < height; y++)
116 u32 *pBits = (u32*)((u8*)Lock.pBits + (y * Lock.Pitch));
117 memcpy(pBits, pIn, width * 4);
118 pIn += pitch;
120 } else {
121 for (int y = 0; y < height; y++)
123 u8 *pIn8 = (u8 *)pIn;
124 u8 *pBits = (u8 *)((u8*)Lock.pBits + (y * Lock.Pitch));
125 for (int x = 0; x < width * 4; x += 4) {
126 pBits[x + 0] = pIn8[x + 2];
127 pBits[x + 1] = pIn8[x + 1];
128 pBits[x + 2] = pIn8[x + 0];
129 pBits[x + 3] = pIn8[x + 3];
131 pIn += pitch;
136 break;
137 case D3DFMT_DXT1:
138 memcpy(Lock.pBits,buffer,((width+3)/4)*((height+3)/4)*8);
139 break;
140 default:
141 PanicAlert("D3D: Invalid texture format %i", fmt);
143 pTexture->UnlockRect(level);
144 return pTexture;
147 LPDIRECT3DTEXTURE9 CreateOnlyTexture2D(const int width, const int height, D3DFORMAT fmt)
149 LPDIRECT3DTEXTURE9 pTexture;
150 // crazy bitmagic, sorry :)
151 bool isPow2 = !((width&(width-1)) || (height&(height-1)));
152 bool bExpand = false;
153 HRESULT hr;
154 // TODO(ector): Allow mipmaps for non-pow textures on newer cards?
155 // TODO(ector): Use the game-specified mipmaps?
156 if (!isPow2)
157 hr = dev->CreateTexture(width, height, 1, 0, fmt, D3DPOOL_MANAGED, &pTexture, NULL);
158 else
159 hr = dev->CreateTexture(width, height, 0, D3DUSAGE_AUTOGENMIPMAP, fmt, D3DPOOL_MANAGED, &pTexture, NULL);
161 if (FAILED(hr))
162 return 0;
163 return pTexture;
166 void ReplaceTexture2D(LPDIRECT3DTEXTURE9 pTexture, const u8* buffer, const int width, const int height, const int pitch, D3DFORMAT fmt, bool swap_r_b, int level)
168 u32* pBuffer = (u32*)buffer;
169 D3DLOCKED_RECT Lock;
170 pTexture->LockRect(level, &Lock, NULL, 0);
171 u32* pIn = pBuffer;
173 bool bExpand = false;
175 if (fmt == D3DFMT_A8P8) {
176 fmt = D3DFMT_A8L8;
177 bExpand = true;
179 switch (fmt)
181 case D3DFMT_A8R8G8B8:
182 if(pitch * 4 == Lock.Pitch && !swap_r_b)
184 memcpy(Lock.pBits, pBuffer, Lock.Pitch*height);
186 else if (!swap_r_b)
188 for (int y = 0; y < height; y++)
190 u32 *pBits = (u32*)((u8*)Lock.pBits + (y * Lock.Pitch));
191 memcpy(pBits, pIn, width * 4);
192 pIn += pitch;
195 else
197 for (int y = 0; y < height; y++)
199 u8 *pIn8 = (u8 *)pIn;
200 u8 *pBits = (u8 *)((u8*)Lock.pBits + (y * Lock.Pitch));
201 for (int x = 0; x < width * 4; x += 4)
203 pBits[x + 0] = pIn8[x + 2];
204 pBits[x + 1] = pIn8[x + 1];
205 pBits[x + 2] = pIn8[x + 0];
206 pBits[x + 3] = pIn8[x + 3];
208 pIn += pitch;
211 break;
212 case D3DFMT_L8:
213 case D3DFMT_A8:
214 case D3DFMT_A4L4:
216 const u8 *pIn = buffer;
217 for (int y = 0; y < height; y++)
219 u8* pBits = ((u8*)Lock.pBits + (y * Lock.Pitch));
220 memcpy(pBits, pIn, width);
221 pIn += pitch;
224 break;
225 case D3DFMT_R5G6B5:
227 const u16 *pIn = (u16*)buffer;
228 for (int y = 0; y < height; y++)
230 u16* pBits = (u16*)((u8*)Lock.pBits + (y * Lock.Pitch));
231 memcpy(pBits, pIn, width * 2);
232 pIn += pitch;
235 break;
236 case D3DFMT_A8L8:
238 if (bExpand) { // I8
239 const u8 *pIn = buffer;
240 // TODO(XK): Find a better way that does not involve either unpacking
241 // or downsampling (i.e. A4L4)
242 for (int y = 0; y < height; y++)
244 u8* pBits = ((u8*)Lock.pBits + (y * Lock.Pitch));
245 for(int i = 0; i < width * 2; i += 2) {
246 pBits[i] = pIn[i / 2];
247 pBits[i + 1] = pIn[i / 2];
249 pIn += pitch;
251 } else { // IA8
252 const u16 *pIn = (u16*)buffer;
254 for (int y = 0; y < height; y++)
256 u16* pBits = (u16*)((u8*)Lock.pBits + (y * Lock.Pitch));
257 memcpy(pBits, pIn, width * 2);
258 pIn += pitch;
262 break;
263 case D3DFMT_DXT1:
264 memcpy(Lock.pBits,buffer,((width+3)/4)*((height+3)/4)*8);
265 break;
267 pTexture->UnlockRect(level);
270 } // namespace