1 /* 2 ----------------------------------------------------------------------------- 3 This source file is part of OGRE 4 (Object-oriented Graphics Rendering Engine) 5 For the latest info, see http://www.ogre3d.org 6 7 Copyright (c) 2000-2014 Torus Knot Software Ltd 8 9 Permission is hereby granted, free of charge, to any person obtaining a copy 10 of this software and associated documentation files (the "Software"), to deal 11 in the Software without restriction, including without limitation the rights 12 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 13 copies of the Software, and to permit persons to whom the Software is 14 furnished to do so, subject to the following conditions: 15 16 The above copyright notice and this permission notice shall be included in 17 all copies or substantial portions of the Software. 18 19 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 20 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 21 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 22 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 23 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 24 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 25 THE SOFTWARE. 26 ----------------------------------------------------------------------------- 27 */ 28 #include "OgreD3D9HardwareOcclusionQuery.h" 29 #include "OgreRenderSystemCapabilities.h" 30 #include "OgreException.h" 31 #include "OgreD3D9RenderSystem.h" 32 33 namespace Ogre { 34 35 /** 36 * This is a class that is the DirectX9 implementation of 37 * hardware occlusion testing. 38 * 39 * @author Lee Sandberg 40 * 41 * Updated on 12/7/2004 by Chris McGuirk 42 * Updated on 4/8/2005 by Tuan Kuranes email: tuan.kuranes@free.fr 43 */ 44 45 /** 46 * Default object constructor 47 */ D3D9HardwareOcclusionQuery()48 D3D9HardwareOcclusionQuery::D3D9HardwareOcclusionQuery() 49 { 50 51 } 52 53 /** 54 * Object destructor 55 */ ~D3D9HardwareOcclusionQuery()56 D3D9HardwareOcclusionQuery::~D3D9HardwareOcclusionQuery() 57 { 58 DeviceToQueryIterator it = mMapDeviceToQuery.begin(); 59 60 while (it != mMapDeviceToQuery.end()) 61 { 62 SAFE_RELEASE(it->second); 63 ++it; 64 } 65 mMapDeviceToQuery.clear(); 66 } 67 68 //------------------------------------------------------------------ 69 // Occlusion query functions (see base class documentation for this) 70 //-- beginOcclusionQuery()71 void D3D9HardwareOcclusionQuery::beginOcclusionQuery() 72 { 73 IDirect3DDevice9* pCurDevice = D3D9RenderSystem::getActiveD3D9Device(); 74 DeviceToQueryIterator it = mMapDeviceToQuery.find(pCurDevice); 75 76 // No resource exits for current device -> create it. 77 if (it == mMapDeviceToQuery.end() || it->second == NULL) 78 createQuery(pCurDevice); 79 80 81 // Grab the query of the current device. 82 IDirect3DQuery9* pOccQuery = mMapDeviceToQuery[pCurDevice]; 83 84 85 if (pOccQuery != NULL) 86 { 87 pOccQuery->Issue(D3DISSUE_BEGIN); 88 mIsQueryResultStillOutstanding = true; 89 mPixelCount = 0; 90 } 91 } 92 endOcclusionQuery()93 void D3D9HardwareOcclusionQuery::endOcclusionQuery() 94 { 95 IDirect3DDevice9* pCurDevice = D3D9RenderSystem::getActiveD3D9Device(); 96 DeviceToQueryIterator it = mMapDeviceToQuery.find(pCurDevice); 97 98 if (it == mMapDeviceToQuery.end()) 99 { 100 OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR, 101 "End occlusion called without matching begin call !!", 102 "D3D9HardwareOcclusionQuery::endOcclusionQuery" ); 103 } 104 105 IDirect3DQuery9* pOccQuery = mMapDeviceToQuery[pCurDevice]; 106 107 if (pOccQuery != NULL) 108 pOccQuery->Issue(D3DISSUE_END); 109 } 110 111 //------------------------------------------------------------------ pullOcclusionQuery(unsigned int * NumOfFragments)112 bool D3D9HardwareOcclusionQuery::pullOcclusionQuery( unsigned int* NumOfFragments ) 113 { 114 IDirect3DDevice9* pCurDevice = D3D9RenderSystem::getActiveD3D9Device(); 115 DeviceToQueryIterator it = mMapDeviceToQuery.find(pCurDevice); 116 117 if (it == mMapDeviceToQuery.end()) 118 return false; 119 120 if (it->second == NULL) 121 return false; 122 123 // in case you didn't check if query arrived and want the result now. 124 if (mIsQueryResultStillOutstanding) 125 { 126 // Loop until the data becomes available 127 DWORD pixels; 128 const size_t dataSize = sizeof( DWORD ); 129 while (1) 130 { 131 const HRESULT hr = it->second->GetData((void *)&pixels, dataSize, D3DGETDATA_FLUSH); 132 133 if (hr == S_FALSE) 134 continue; 135 if (hr == S_OK) 136 { 137 mPixelCount = pixels; 138 *NumOfFragments = pixels; 139 break; 140 } 141 if (hr == D3DERR_DEVICELOST) 142 { 143 *NumOfFragments = 0; 144 mPixelCount = 0; 145 SAFE_RELEASE(it->second); 146 break; 147 } 148 } 149 mIsQueryResultStillOutstanding = false; 150 } 151 else 152 { 153 // we already stored result from last frames. 154 *NumOfFragments = mPixelCount; 155 } 156 return true; 157 } 158 159 //------------------------------------------------------------------ getLastQuerysPixelcount()160 unsigned int D3D9HardwareOcclusionQuery::getLastQuerysPixelcount() 161 { 162 return mPixelCount; 163 } 164 165 //------------------------------------------------------------------ isStillOutstanding(void)166 bool D3D9HardwareOcclusionQuery::isStillOutstanding(void) 167 { 168 // in case you already asked for this query 169 if (!mIsQueryResultStillOutstanding) 170 return false; 171 172 IDirect3DDevice9* pCurDevice = D3D9RenderSystem::getActiveD3D9Device(); 173 DeviceToQueryIterator it = mMapDeviceToQuery.find(pCurDevice); 174 175 if (it == mMapDeviceToQuery.end()) 176 return false; 177 178 if (it->second == NULL) 179 return false; 180 181 182 DWORD pixels; 183 const HRESULT hr = it->second->GetData( (void *) &pixels, sizeof( DWORD ), 0); 184 185 if (hr == S_FALSE) 186 return true; 187 188 if (hr == D3DERR_DEVICELOST) 189 { 190 mPixelCount = 100000; 191 SAFE_RELEASE(it->second); 192 } 193 194 mPixelCount = pixels; 195 mIsQueryResultStillOutstanding = false; 196 return false; 197 } 198 199 //------------------------------------------------------------------ notifyOnDeviceCreate(IDirect3DDevice9 * d3d9Device)200 void D3D9HardwareOcclusionQuery::notifyOnDeviceCreate(IDirect3DDevice9* d3d9Device) 201 { 202 203 } 204 205 //------------------------------------------------------------------ notifyOnDeviceDestroy(IDirect3DDevice9 * d3d9Device)206 void D3D9HardwareOcclusionQuery::notifyOnDeviceDestroy(IDirect3DDevice9* d3d9Device) 207 { 208 releaseQuery(d3d9Device); 209 } 210 211 //------------------------------------------------------------------ notifyOnDeviceLost(IDirect3DDevice9 * d3d9Device)212 void D3D9HardwareOcclusionQuery::notifyOnDeviceLost(IDirect3DDevice9* d3d9Device) 213 { 214 releaseQuery(d3d9Device); 215 } 216 217 //------------------------------------------------------------------ notifyOnDeviceReset(IDirect3DDevice9 * d3d9Device)218 void D3D9HardwareOcclusionQuery::notifyOnDeviceReset(IDirect3DDevice9* d3d9Device) 219 { 220 221 } 222 223 //------------------------------------------------------------------ createQuery(IDirect3DDevice9 * d3d9Device)224 void D3D9HardwareOcclusionQuery::createQuery(IDirect3DDevice9* d3d9Device) 225 { 226 HRESULT hr; 227 228 // Check if query supported. 229 hr = d3d9Device->CreateQuery(D3DQUERYTYPE_OCCLUSION, NULL); 230 if (FAILED(hr)) 231 { 232 mMapDeviceToQuery[d3d9Device] = NULL; 233 return; 234 } 235 236 // create the occlusion query. 237 IDirect3DQuery9* pCurQuery; 238 hr = d3d9Device->CreateQuery(D3DQUERYTYPE_OCCLUSION, &pCurQuery); 239 240 mMapDeviceToQuery[d3d9Device] = pCurQuery; 241 } 242 243 //------------------------------------------------------------------ releaseQuery(IDirect3DDevice9 * d3d9Device)244 void D3D9HardwareOcclusionQuery::releaseQuery(IDirect3DDevice9* d3d9Device) 245 { 246 DeviceToQueryIterator it = mMapDeviceToQuery.find(d3d9Device); 247 248 // Remove from query resource map. 249 if (it != mMapDeviceToQuery.end()) 250 { 251 SAFE_RELEASE(it->second); 252 mMapDeviceToQuery.erase(it); 253 } 254 } 255 } 256