1 #include "texture_d3d9.h"
2 
3 #include <stdexcept>
4 #include <cassert>
5 
6 #include "graphics_interface.h"
7 #include "context_d3d9.h"
8 #include "d3d9_util.h"
9 
10 #include "leak_dumper.h"
11 
12 using namespace std;
13 using namespace Shared::Graphics;
14 
15 namespace Shared{ namespace Graphics{ namespace D3d9{
16 
17 // ===============================================
18 //	class Texture2DD3d9
19 // ===============================================
20 
toFormatD3d(Texture::Format format,int components)21 D3DFORMAT toFormatD3d(Texture::Format format, int components){
22 	switch(format){
23 	case Texture::fAuto:
24 		switch(components){
25 		case 1:
26 			return D3DFMT_L8;
27 		case 3:
28 			return D3DFMT_X8R8G8B8;
29 		case 4:
30 			return D3DFMT_A8R8G8B8;
31 		default:
32 			assert(false);
33 			return D3DFMT_A8R8G8B8;
34 		}
35 		break;
36 	case Texture::fLuminance:
37 		return D3DFMT_L8;
38 	case Texture::fAlpha:
39 		return D3DFMT_A8;
40 	case Texture::fRgb:
41 		return D3DFMT_X8R8G8B8;
42 	case Texture::fRgba:
43 		return D3DFMT_A8R8G8B8;
44 	default:
45 		assert(false);
46 		return D3DFMT_A8R8G8B8;
47 	}
48 }
49 
fillPixels(uint8 * texturePixels,const Pixmap2D * pixmap)50 void fillPixels(uint8 *texturePixels, const Pixmap2D *pixmap){
51 
52 	for(int i=0; i<pixmap->getW(); ++i){
53 		for(int j=0; j<pixmap->getH(); ++j){
54 			int k= j*pixmap->getW()+i;
55 
56 			Vec4<uint8> pixel;
57 
58 			pixmap->getPixel(i, j, pixel.ptr());
59 			switch(pixmap->getComponents()){
60 			case 1:
61 				texturePixels[k]= pixel.x;
62 				break;
63 			case 3:
64 				texturePixels[k*4]= pixel.z;
65 				texturePixels[k*4+1]= pixel.y;
66 				texturePixels[k*4+2]= pixel.x;
67 				break;
68 			case 4:
69 				texturePixels[k*4]= pixel.z;
70 				texturePixels[k*4+1]= pixel.y;
71 				texturePixels[k*4+2]= pixel.x;
72 				texturePixels[k*4+3]= pixel.w;
73 				break;
74 			default:
75 				assert(false);
76 			}
77 		}
78 	}
79 }
80 
init(Filter textureFilter,int maxAnisotropy)81 void Texture2DD3d9::init(Filter textureFilter, int maxAnisotropy){
82 	if(!inited){
83 
84 		//get device
85 		GraphicsInterface &gi= GraphicsInterface::getInstance();
86 		ContextD3d9 *context= static_cast<ContextD3d9*>(gi.getCurrentContext());
87 		IDirect3DDevice9 *d3dDevice= context->getD3dDevice();
88 
89 		bool mipmapCaps= (context->getCaps()->TextureCaps & D3DPTEXTURECAPS_MIPCUBEMAP) != 0;
90 		bool autogenMipmap= mipmapCaps && mipmap;
91 
92 		int w= pixmapInit? pixmap.getW(): defaultSize;
93 		int h= pixmapInit? pixmap.getH(): defaultSize;
94 
95 		//create texture
96 		D3DCALL(d3dDevice->CreateTexture(
97 			w,
98 			h,
99 			autogenMipmap? 0: 1,
100 			autogenMipmap? D3DUSAGE_AUTOGENMIPMAP: 0,
101 			toFormatD3d(format, pixmap.getComponents()),
102 			D3DPOOL_MANAGED,
103 			&d3dTexture,
104 			NULL));
105 
106 		if(pixmapInit){
107 			//lock
108 			D3DLOCKED_RECT lockedRect;
109 			D3DCALL(d3dTexture->LockRect(0, &lockedRect, NULL, 0));
110 
111 			//copy
112 			fillPixels(reinterpret_cast<uint8*>(lockedRect.pBits), &pixmap);
113 
114 			//unlock
115 			D3DCALL(d3dTexture->UnlockRect(0));
116 		}
117 		inited= true;
118 	}
119 }
120 
end()121 void Texture2DD3d9::end(){
122 	if(inited){
123 		d3dTexture->Release();
124 	}
125 }
126 
127 // ===============================================
128 //	class TextureCubeD3d9
129 // ===============================================
130 
init(Filter textureFilter,int maxAnisotropy)131 void TextureCubeD3d9::init(Filter textureFilter, int maxAnisotropy){
132 	//get device
133 	if(!inited){
134 		GraphicsInterface &gi= GraphicsInterface::getInstance();
135 		ContextD3d9 *context= static_cast<ContextD3d9*>(gi.getCurrentContext());
136 		IDirect3DDevice9 *d3dDevice= context->getD3dDevice();
137 
138 		const Pixmap2D *face0= pixmap.getFace(0);
139 		int l= pixmapInit? face0->getW(): defaultSize;
140 		int components= face0->getComponents();
141 
142 		//check dimensions and face components
143 		if(pixmapInit){
144 			for(int i=0; i<6; ++i){
145 				const Pixmap2D *currentFace= pixmap.getFace(i);
146 				if(currentFace->getW()!=l || currentFace->getH()!=l){
147 					throw runtime_error("Can't create Direct3D cube texture: dimensions don't agree");
148 				}
149 				if(currentFace->getComponents()!=components){
150 					throw runtime_error("Can't create Direct3D cube texture: components don't agree");
151 				}
152 			}
153 		}
154 
155 		bool mipmapCaps= (context->getCaps()->TextureCaps & D3DPTEXTURECAPS_MIPCUBEMAP) != 0;
156 		bool autogenMipmap= mipmapCaps && mipmap;
157 
158 		//create texture
159 		D3DCALL(d3dDevice->CreateCubeTexture(
160 			l,
161 			autogenMipmap? 0: 1,
162 			autogenMipmap? D3DUSAGE_AUTOGENMIPMAP: 0,
163 			toFormatD3d(format, components),
164 			D3DPOOL_MANAGED,
165 			&d3dCubeTexture,
166 			NULL));
167 
168 		if(pixmapInit){
169 			for(int i=0; i<6; ++i){
170 
171 				//lock
172 				D3DLOCKED_RECT lockedRect;
173 				D3DCALL(d3dCubeTexture->LockRect(static_cast<D3DCUBEMAP_FACES>(i), 0, &lockedRect, NULL, 0));
174 
175 				//copy
176 				fillPixels(reinterpret_cast<uint8*>(lockedRect.pBits), pixmap.getFace(i));
177 
178 				//unlock
179 				D3DCALL(d3dCubeTexture->UnlockRect(static_cast<D3DCUBEMAP_FACES>(i), 0));
180 			}
181 		}
182 		inited= true;
183 	}
184 }
185 
end()186 void TextureCubeD3d9::end(){
187 	if(inited){
188 		d3dCubeTexture->Release();
189 	}
190 }
191 
192 }}}//end namespace