@@ -57,6 +57,7 @@ void W3DSmudgeManager::init(void)
5757{
5858 SmudgeManager::init ();
5959 ReAcquireResources ();
60+ testHardwareSupport ();
6061}
6162
6263void W3DSmudgeManager::reset (void )
@@ -133,210 +134,73 @@ void W3DSmudgeManager::ReAcquireResources(void)
133134 }
134135}
135136
136- /* Copies a portion of the current render target into a specified buffer*/
137- Int copyRect (unsigned char *buf, Int bufSize, Int oX, Int oY, Int width, Int height)
137+ Bool W3DSmudgeManager::testHardwareSupport (void )
138138{
139- IDirect3DSurface8 *surface=NULL ; // /<previous render target
140- IDirect3DSurface8 *tempSurface=NULL ;
141- Int result = 0 ;
142-
143- LPDIRECT3DDEVICE8 m_pDev=DX8Wrapper::_Get_D3D_Device8 ();
144-
145- if (!m_pDev)
146- goto error;
147-
148- m_pDev->GetRenderTarget (&surface);
149-
150- if (!surface)
151- goto error;
152-
153- D3DSURFACE_DESC desc;
154- surface->GetDesc (&desc);
155-
156- RECT srcRect;
157- srcRect.left =oX;
158- srcRect.top =oY;
159- srcRect.right =oX+width;
160- srcRect.bottom =oY+height;
161- DEBUG_ASSERTCRASH (srcRect.left >= 0 , (" copyRect - Invalid size" ));
162- DEBUG_ASSERTCRASH (srcRect.top >= 0 , (" copyRect - Invalid size" ));
163- DEBUG_ASSERTCRASH (srcRect.right < (LONG)desc.Width , (" copyRect - Invalid size" ));
164- DEBUG_ASSERTCRASH (srcRect.bottom < (LONG)desc.Height , (" copyRect - Invalid size" ));
165-
166- POINT dstPoint;
167- dstPoint.x =0 ;
168- dstPoint.y =0 ;
169-
170- HRESULT hr;
171- hr=m_pDev->CreateImageSurface (width, height, desc.Format , &tempSurface);
172-
173- if (hr != S_OK)
174- goto error;
175-
176- hr=m_pDev->CopyRects (surface,&srcRect,1 ,tempSurface,&dstPoint);
177-
178- if (hr != S_OK)
179- goto error;
180-
181- D3DLOCKED_RECT lrect;
182-
183- hr=tempSurface->LockRect (&lrect,NULL ,D3DLOCK_READONLY);
184-
185- if (hr != S_OK)
186- goto error;
187-
188- tempSurface->GetDesc (&desc);
189- UnsignedInt bytesPerPixel;
190- bytesPerPixel = DX8Wrapper::Bytes_Per_Pixel (desc.Format );
191-
192- if (bytesPerPixel == 0 )
193- goto error;
194-
195- Int rowSize;
196- Int totalSize;
197- rowSize = width * bytesPerPixel;
198- totalSize = height * rowSize;
199-
200- if (totalSize > bufSize)
201- totalSize = bufSize;
202-
203- UnsignedByte* dst;
204- UnsignedByte* src;
205- Int rowCount;
206- Int row;
207- dst = buf;
208- src = (UnsignedByte*)lrect.pBits ;
209- rowCount = totalSize / rowSize;
210-
211- for (row = 0 ; row < rowCount; ++row)
139+ // Return cached result if already checked
140+ if (m_hardwareSupportStatus != SMUDGE_SUPPORT_UNKNOWN)
212141 {
213- memcpy (dst, src, rowSize);
214- dst += rowSize;
215- src += lrect.Pitch ;
142+ return m_hardwareSupportStatus == SMUDGE_SUPPORT_YES;
216143 }
217144
218- result = totalSize;
219- tempSurface->UnlockRect ();
220-
221- error:
222- if (surface)
223- surface->Release ();
224- if (tempSurface)
225- tempSurface->Release ();
226-
227- return result;
228- }
229-
230- #define UNIQUE_COLOR (0x12345678 )
231- #define BLOCK_SIZE (8 )
232-
233- Bool W3DSmudgeManager::testHardwareSupport (void )
234- {
235- if (m_hardwareSupportStatus == SMUDGE_SUPPORT_UNKNOWN)
236- { // we have not done the test yet.
237-
238- IDirect3DTexture8 *backTexture=W3DShaderManager::getRenderTexture ();
239- if (!backTexture)
240- { // do trivial test first to see if render target exists.
241- m_hardwareSupportStatus = SMUDGE_SUPPORT_NO;
242- return FALSE ;
243- }
244-
245- if (!W3DShaderManager::isRenderingToTexture ())
246- return FALSE ; // can't do the test unless we're rendering to texture.
247-
248- VertexMaterialClass *vmat=VertexMaterialClass::Get_Preset (VertexMaterialClass::PRELIT_DIFFUSE);
249- DX8Wrapper::Set_Material (vmat);
250- REF_PTR_RELEASE (vmat); // no need to keep a reference since it's a preset.
251-
252- ShaderClass shader=ShaderClass::_PresetOpaqueShader;
253- shader.Set_Depth_Compare (ShaderClass::PASS_ALWAYS);
254- shader.Set_Depth_Mask (ShaderClass::DEPTH_WRITE_DISABLE);
255- DX8Wrapper::Set_Shader (shader);
256- DX8Wrapper::Set_Texture (0 ,NULL );
257- DX8Wrapper::Apply_Render_State_Changes (); // force update of view and projection matrices
258-
259- struct _TRANS_LIT_TEX_VERTEX {
260- Vector4 p;
261- DWORD color; // diffuse color
262- float u;
263- float v;
264- } v[4 ];
265-
266- // bottom right
267- v[0 ].p = Vector4 ( BLOCK_SIZE-0 .5f , BLOCK_SIZE-0 .5f , 0 .0f , 1 .0f );
268- v[0 ].u = BLOCK_SIZE/(Real)TheDisplay->getWidth ();
269- v[0 ].v = BLOCK_SIZE/(Real)TheDisplay->getHeight ();
270- // top right
271- v[1 ].p = Vector4 ( BLOCK_SIZE-0 .5f , 0 -0 .5f , 0 .0f , 1 .0f );
272- v[1 ].u = BLOCK_SIZE/(Real)TheDisplay->getWidth ();
273- v[1 ].v = 0 ;
274- // bottom left
275- v[2 ].p = Vector4 ( 0 -0 .5f , BLOCK_SIZE-0 .5f , 0 .0f , 1 .0f );
276- v[2 ].u = 0 ;
277- v[2 ].v = BLOCK_SIZE/(Real)TheDisplay->getHeight ();
278- // top left
279- v[3 ].p = Vector4 ( 0 -0 .5f , 0 -0 .5f , 0 .0f , 1 .0f );
280- v[3 ].u = 0 ;
281- v[3 ].v = 0 ;
282-
283- v[0 ].color = UNIQUE_COLOR;
284- v[1 ].color = UNIQUE_COLOR;
285- v[2 ].color = UNIQUE_COLOR;
286- v[3 ].color = UNIQUE_COLOR;
287-
288- LPDIRECT3DDEVICE8 pDev=DX8Wrapper::_Get_D3D_Device8 ();
289-
290- // draw polygons like this is very inefficient but for only 2 triangles, it's
291- // not worth bothering with index/vertex buffers.
292- pDev->SetVertexShader (D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_TEX1);
293-
294- pDev->DrawPrimitiveUP (D3DPT_TRIANGLESTRIP, 2 , v, sizeof (_TRANS_LIT_TEX_VERTEX));
295-
296- DWORD refData[BLOCK_SIZE*BLOCK_SIZE];
297- memset (refData,0 ,sizeof (refData));
298- Int bufSize=copyRect ((unsigned char *)refData,sizeof (refData),0 ,0 ,BLOCK_SIZE,BLOCK_SIZE); // copy area we just rendered using solid color
299- if (!bufSize)
300- {
301- m_hardwareSupportStatus = SMUDGE_SUPPORT_NO;
302- return FALSE ;
303- }
304-
305- DX8Wrapper::Set_DX8_Texture (0 ,backTexture);
145+ LPDIRECT3DDEVICE8 d3d8Device = DX8Wrapper::_Get_D3D_Device8 ();
146+ LPDIRECT3D8 d3d8Interface = DX8Wrapper::_Get_D3D8 ();
147+ if (!d3d8Device || !d3d8Interface)
148+ {
149+ m_hardwareSupportStatus = SMUDGE_SUPPORT_NO;
150+ return false ;
151+ }
306152
307- DWORD testData[BLOCK_SIZE*BLOCK_SIZE] ;
308- memset (testData, 0xff , sizeof (testData) );
153+ D3DCAPS8 caps ;
154+ d3d8Device-> GetDeviceCaps (&caps );
309155
310- v[0 ].color = 0xffffffff ;
311- v[1 ].color = 0xffffffff ;
312- v[2 ].color = 0xffffffff ;
313- v[3 ].color = 0xffffffff ;
156+ // DX8 requires dynamic textures to efficiently update smudge texture
157+ if (!(caps.Caps2 & D3DCAPS2_DYNAMICTEXTURES))
158+ {
159+ m_hardwareSupportStatus = SMUDGE_SUPPORT_NO;
160+ return false ;
161+ }
314162
315- pDev->DrawPrimitiveUP (D3DPT_TRIANGLESTRIP, 2 , v, sizeof (_TRANS_LIT_TEX_VERTEX));
316- bufSize=copyRect ((unsigned char *)testData,sizeof (testData),0 ,0 ,BLOCK_SIZE,BLOCK_SIZE);
163+ IDirect3DTexture8 *backTexture = W3DShaderManager::getRenderTexture ();
164+ if (!backTexture)
165+ {
166+ m_hardwareSupportStatus = SMUDGE_SUPPORT_NO;
167+ return FALSE ;
168+ }
317169
318- if (!bufSize)
319- {
320- m_hardwareSupportStatus = SMUDGE_SUPPORT_NO;
321- return FALSE ;
322- }
170+ IDirect3DSurface8* surface;
171+ if (FAILED (backTexture->GetSurfaceLevel (0 , &surface)))
172+ {
173+ m_hardwareSupportStatus = SMUDGE_SUPPORT_NO;
174+ return false ;
175+ }
323176
324- // compare the 2 buffers to see if they match.
325- if (memcmp (testData,refData,bufSize) == 0 )
326- {
327- m_hardwareSupportStatus = SMUDGE_SUPPORT_YES;
328- return TRUE ;
329- }
177+ D3DSURFACE_DESC desc;
178+ surface->GetDesc (&desc);
179+ surface->Release ();
180+
181+ // Check if the device supports render-to-texture for this format
182+ HRESULT hr = d3d8Interface->CheckDeviceFormat (
183+ D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
184+ DX8Wrapper::_Get_D3D_Back_Buffer_Format (),
185+ D3DUSAGE_RENDERTARGET,
186+ D3DRTYPE_TEXTURE,
187+ desc.Format
188+ );
189+
190+ if (hr != D3D_OK)
191+ {
330192 m_hardwareSupportStatus = SMUDGE_SUPPORT_NO;
193+ return false ;
331194 }
332195
333- return (SMUDGE_SUPPORT_YES == m_hardwareSupportStatus);
196+ m_hardwareSupportStatus = SMUDGE_SUPPORT_YES;
197+ return true ;
334198}
335199
336200void W3DSmudgeManager::render (RenderInfoClass &rinfo)
337201{
338202 // Verify that the card supports the effect.
339- if (! testHardwareSupport () )
203+ if (m_hardwareSupportStatus == SMUDGE_SUPPORT_NO )
340204 return ;
341205
342206 CameraClass &camera=rinfo.Camera ;
0 commit comments