GBitmap *AtlasTexChunk::loadDDSIntoGBitmap(const U8 *ddsBuffer, U32 ddsBufferSize) { D3DXIMAGE_INFO info; D3D9Assert(GFXD3DX.D3DXGetImageInfoFromFileInMemory(ddsBuffer, ddsBufferSize, &info), "AtlasTexChunk::loadDDSIntoGBitmap - failed to get image info."); IDirect3DSurface9 *surf = NULL; D3D9Assert(((GFXD3D9Device*)GFX)->getDevice()->CreateOffscreenPlainSurface( info.Width, info.Height, info.Format, D3DPOOL_SCRATCH, &surf, NULL), "AtlasTexChunk::loadDDSIntoGBitmap - failed to allocate scratch surface."); // We want JPEGs, let's convert it in a klunky way... D3D9Assert(GFXD3DX.D3DXLoadSurfaceFromFileInMemory(surf, NULL, NULL, ddsBuffer, ddsBufferSize, NULL, D3DX_DEFAULT, 0, NULL), "AtlasTexChunk::loadDDSIntoGBitmap - D3DX failed to load from buffer."); ID3DXBuffer *buff = NULL; D3D9Assert(GFXD3DX.D3DXSaveSurfaceToFileInMemory(&buff, D3DXIFF_PNG, surf, NULL, NULL), "AtlasTexChunk::loadDDSIntoGBitmap - D3DX failed to save back to buffer."); MemStream ms(buff->GetBufferSize(), buff->GetBufferPointer(), true, false); GBitmap *bitmap = new GBitmap[1]; bitmap->readBitmap( "png", ms ); // Cleanup! buff->Release(); surf->Release(); return bitmap; }
void GFXD3D9Device::reacquireDefaultPoolResources() { // Now do the dynamic index buffers if( mDynamicPB == NULL ) mDynamicPB = new GFXD3D9PrimitiveBuffer(this, 0, 0, GFXBufferTypeDynamic); D3D9Assert( mD3DDevice->CreateIndexBuffer( sizeof( U16 ) * MAX_DYNAMIC_INDICES, #ifdef TORQUE_OS_XENON D3DUSAGE_WRITEONLY, #else D3DUSAGE_WRITEONLY | D3DUSAGE_DYNAMIC, #endif GFXD3D9IndexFormat[GFXIndexFormat16], D3DPOOL_DEFAULT, &mDynamicPB->ib, NULL ), "Failed to allocate dynamic IB" ); // Grab the depth-stencil... SAFE_RELEASE(mDeviceDepthStencil); D3D9Assert(mD3DDevice->GetDepthStencilSurface(&mDeviceDepthStencil), "GFXD3D9Device::reacquireDefaultPoolResources - couldn't grab reference to device's depth-stencil surface."); SAFE_RELEASE(mDeviceBackbuffer); mD3DDevice->GetBackBuffer( 0, 0, D3DBACKBUFFER_TYPE_MONO, &mDeviceBackbuffer ); // Walk the resource list and zombify everything. GFXResource *walk = mResourceListHead; while(walk) { walk->resurrect(); walk = walk->getNextResource(); } if(mTextureManager) mTextureManager->resurrect(); }
void GFXPCD3D9WindowTarget::createAdditionalSwapChain() { AssertFatal(!mImplicit, "Invalid swap chain type! Implicit swap chains use the device"); // Since we're not going to do a device reset for an additional swap // chain, we can just release our resources and regrab them. SAFE_RELEASE(mSwapChain); SAFE_RELEASE(mDepthStencil); SAFE_RELEASE(mBackbuffer); // If there's a fullscreen window active, don't try to create these additional swap chains. // CodeReview, we need to store the window target with the implicit swap chain better, this line below // could fail if the current render target isn't what we expect. GFXPCD3D9WindowTarget* currTarget = dynamic_cast<GFXPCD3D9WindowTarget*>(mDevice->getActiveRenderTarget()); if (currTarget && currTarget->getWindow()->getVideoMode().fullScreen) return; // Setup our presentation params. initPresentationParams(); // Create our resources! D3D9Assert(mDevice->getDevice()->CreateAdditionalSwapChain(&mPresentationParams, &mSwapChain), "GFXPCD3D9WindowTarget::createAdditionalSwapChain - couldn't reallocate additional swap chain!"); D3D9Assert(mDevice->getDevice()->CreateDepthStencilSurface(mPresentationParams.BackBufferWidth, mPresentationParams.BackBufferHeight, D3DFMT_D24S8, mPresentationParams.MultiSampleType, mPresentationParams.MultiSampleQuality, false, &mDepthStencil, NULL), "GFXPCD3D9WindowTarget::createAdditionalSwapChain: Unable to create stencil/depth surface"); D3D9Assert(mSwapChain->GetBackBuffer(0, D3DBACKBUFFER_TYPE_MONO, &mBackbuffer), "GFXPCD3D9WindowTarget::createAdditionalSwapChain: Unable to get backbuffer!"); }
//----------------------------------------------------------------------------- // unLock //----------------------------------------------------------------------------- void GFXD3D9TextureObject::unlock(U32 mipLevel) { AssertFatal( mLocked, "GFXD3D9TextureObject::unlock - Attempting to unlock a surface that has not been locked" ); #ifndef TORQUE_OS_XENON if( mProfile->isRenderTarget() ) { IDirect3DSurface9 *dest; GFXD3D9TextureObject *to = (GFXD3D9TextureObject *) &(*mLockTex); D3D9Assert( to->get2DTex()->GetSurfaceLevel( 0, &dest ), NULL ); dest->UnlockRect(); dest->Release(); mLocked = false; } else #endif { D3D9Assert( get2DTex()->UnlockRect(mipLevel), "GFXD3D9TextureObject::unlock - could not unlock non-RT texture." ); mLocked = false; } }
void GFXD3D9Device::setVB( GFXVertexBuffer *buffer ) { AssertFatal( mCurrentOpenAllocVB == NULL, "Calling setVertexBuffer() when a vertex buffer is still open for editing" ); mCurrentVB = static_cast<GFXD3D9VertexBuffer *>( buffer ); D3D9Assert( mD3DDevice->SetVertexDeclaration( mCurrentVB->decl ), "Failed to set vertex declaration" ); D3D9Assert( mD3DDevice->SetStreamSource( 0, mCurrentVB->vb, 0, mCurrentVB->mVertexSize ), "Failed to set stream source" ); }
//----------------------------------------------------------------------------- // This function should ONLY be called from GFXDevice::updateStates() !!! //----------------------------------------------------------------------------- void GFXD3D9Device::setTextureInternal( U32 textureUnit, const GFXTextureObject *texture) { if( texture == NULL ) { D3D9Assert(mD3DDevice->SetTexture( textureUnit, NULL ), "Failed to set texture to null!"); return; } GFXD3D9TextureObject *tex = (GFXD3D9TextureObject *) texture; D3D9Assert(mD3DDevice->SetTexture( textureUnit, tex->getTex()), "Failed to set texture to valid value!"); }
void GFXPCD3D9WindowTarget::resolveTo( GFXTextureObject *tex ) { GFXDEBUGEVENT_SCOPE( GFXPCD3D9WindowTarget_resolveTo, ColorI::RED ); IDirect3DSurface9 *surf; D3D9Assert( ((GFXD3D9TextureObject*)(tex))->get2DTex()->GetSurfaceLevel( 0, &surf ), "GFXPCD3D9WindowTarget::resolveTo() - GetSurfaceLevel failed!" ); D3D9Assert( mDevice->getDevice()->StretchRect( mBackbuffer, NULL, surf, NULL, D3DTEXF_NONE ), "GFXPCD3D9WindowTarget::resolveTo() - StretchRect failed!" ); surf->Release(); }
void GFXPCD3D9WindowTarget::activate() { GFXDEBUGEVENT_SCOPE( GFXPCD3D9WindowTarget_activate, ColorI::RED ); LPDIRECT3DDEVICE9 d3dDevice = mDevice->getDevice(); // In debug lets do a complete test to be sure we don't // have a bad depth format for this display mode. #ifdef TORQUE_DEBUG if ( mDepthStencil && mBackbuffer ) { D3DSURFACE_DESC desc; D3D9Assert( mBackbuffer->GetDesc( &desc ), "GFXPCD3D9TextureTarget::activate() - Failed to get surface description!"); D3DFORMAT renderFormat = desc.Format; D3D9Assert( mDepthStencil->GetDesc( &desc ), "GFXPCD3D9TextureTarget::activate() - Failed to get surface description!"); D3DFORMAT depthFormat = desc.Format; HRESULT hr = mDevice->getD3D()->CheckDepthStencilMatch( mDevice->getAdaterIndex(), D3DDEVTYPE_HAL, mDevice->mDisplayMode.Format, renderFormat, depthFormat ); D3D9Assert( hr, "GFXPCD3D9WindowTarget::activate() - Bad depth format for this back buffer!" ); } #endif D3D9Assert( d3dDevice->SetRenderTarget( 0, mBackbuffer ), "GFXPCD3D9WindowTarget::activate() - Failed to set backbuffer target!" ); D3D9Assert( d3dDevice->SetDepthStencilSurface( mDepthStencil ), "GFXPCD3D9WindowTarget::activate() - Failed to set depthstencil target!" ); D3DPRESENT_PARAMETERS pp; mSwapChain->GetPresentParameters(&pp); // Update our video mode here, too. GFXVideoMode vm; vm = mWindow->getVideoMode(); vm.resolution.x = pp.BackBufferWidth; vm.resolution.y = pp.BackBufferHeight; vm.fullScreen = !pp.Windowed; mSize = vm.resolution; }
void GFXD3D9CardProfiler::init() { mD3DDevice = dynamic_cast<GFXD3D9Device *>(GFX)->getDevice(); AssertISV( mD3DDevice, "GFXD3D9CardProfiler::init() - No D3D9 Device found!"); // Grab the caps so we can get our adapter ordinal and look up our name. D3DCAPS9 caps; D3D9Assert(mD3DDevice->GetDeviceCaps(&caps), "GFXD3D9CardProfiler::init - failed to get device caps!"); #ifdef TORQUE_OS_XENON mCardDescription = "Xbox360 GPU"; mChipSet = "ATI"; mVersionString = String::ToString(_XDK_VER); mVideoMemory = 512 * 1024 * 1024; #else WMIVideoInfo wmiVidInfo; if( wmiVidInfo.profileAdapters() ) { const PlatformVideoInfo::PVIAdapter &adapter = wmiVidInfo.getAdapterInformation( caps.AdapterOrdinal ); mCardDescription = adapter.description; mChipSet = adapter.chipSet; mVersionString = adapter.driverVersion; mVideoMemory = adapter.vram; } #endif Parent::init(); }
//----------------------------------------------------------------------------- GFXD3D9VertexBuffer * GFXD3D9Device::createVBPool( const GFXVertexFormat *vertexFormat, U32 vertSize ) { // this is a bit funky, but it will avoid problems with (lack of) copy constructors // with a push_back() situation mVolatileVBList.increment(); StrongRefPtr<GFXD3D9VertexBuffer> newBuff; mVolatileVBList.last() = new GFXD3D9VertexBuffer(); newBuff = mVolatileVBList.last(); newBuff->mNumVerts = 0; newBuff->mBufferType = GFXBufferTypeVolatile; newBuff->mVertexFormat = vertexFormat; newBuff->mVertexSize = vertSize; newBuff->mDevice = this; allocVertexDecl( newBuff ); // Con::printf("Created buff with type %x", vertFlags); D3D9Assert( mD3DDevice->CreateVertexBuffer( vertSize * MAX_DYNAMIC_VERTS, #ifdef TORQUE_OS_XENON D3DUSAGE_WRITEONLY, #else D3DUSAGE_WRITEONLY | D3DUSAGE_DYNAMIC, #endif 0, D3DPOOL_DEFAULT, &newBuff->vb, NULL ), "Failed to allocate dynamic VB" ); return newBuff; }
void GFXD3D9Device::setVertexDecl( const GFXVertexDecl *decl ) { IDirect3DVertexDeclaration9 *dx9Decl = NULL; if ( decl ) dx9Decl = static_cast<const D3D9VertexDecl*>( decl )->decl; D3D9Assert( mD3DDevice->SetVertexDeclaration( dx9Decl ), "GFXD3D9Device::setVertexDecl - Failed to set vertex declaration." ); }
void GFXD3D9Device::drawIndexedPrimitive( GFXPrimitiveType primType, U32 startVertex, U32 minIndex, U32 numVerts, U32 startIndex, U32 primitiveCount ) { // This is done to avoid the function call overhead if possible if( mStateDirty ) updateStates(); if (mCurrentShaderConstBuffer) setShaderConstBufferInternal(mCurrentShaderConstBuffer); AssertFatal( mCurrentPB != NULL, "Trying to call drawIndexedPrimitive with no current index buffer, call setIndexBuffer()" ); if ( mVolatileVB ) startVertex += mVolatileVB->mVolatileStart; D3D9Assert( mD3DDevice->DrawIndexedPrimitive( GFXD3D9PrimType[primType], startVertex, /* mCurrentPB->mVolatileStart + */ minIndex, numVerts, mCurrentPB->mVolatileStart + startIndex, primitiveCount ), "Failed to draw indexed primitive" ); mDeviceStatistics.mDrawCalls++; if ( mVertexBufferFrequency[0] > 1 ) mDeviceStatistics.mPolyCount += primitiveCount * mVertexBufferFrequency[0]; else mDeviceStatistics.mPolyCount += primitiveCount; }
void GFXD3D9Device::drawIndexedPrimitive( GFXPrimitiveType primType, U32 startVertex, U32 minIndex, U32 numVerts, U32 startIndex, U32 primitiveCount ) { // This is done to avoid the function call overhead if possible if( mStateDirty ) updateStates(); if (mCurrentShaderConstBuffer) setShaderConstBufferInternal(mCurrentShaderConstBuffer); AssertFatal( mCurrentOpenAllocVB == NULL, "Calling drawIndexedPrimitive() when a vertex buffer is still open for editing" ); AssertFatal( mCurrentVB != NULL, "Trying to call drawIndexedPrimitive with no current vertex buffer, call setVertexBuffer()" ); AssertFatal( mCurrentOpenAllocPB == NULL, "Calling drawIndexedPrimitive() when a index buffer is still open for editing" ); AssertFatal( mCurrentPB != NULL, "Trying to call drawIndexedPrimitive with no current index buffer, call setIndexBuffer()" ); D3D9Assert( mD3DDevice->DrawIndexedPrimitive( GFXD3D9PrimType[primType], mCurrentVB->mVolatileStart + startVertex, /* mCurrentPB->mVolatileStart + */ minIndex, numVerts, mCurrentPB->mVolatileStart + startIndex, primitiveCount ), "Failed to draw indexed primitive" ); mDeviceStatistics.mDrawCalls++; mDeviceStatistics.mPolyCount += primitiveCount; }
void GFXD3D9Device::setVertexStream( U32 stream, GFXVertexBuffer *buffer ) { GFXD3D9VertexBuffer *d3dBuffer = static_cast<GFXD3D9VertexBuffer*>( buffer ); if ( stream == 0 ) { // Set the volatile buffer which is used to // offset the start index when doing draw calls. if ( d3dBuffer && d3dBuffer->mVolatileStart > 0 ) mVolatileVB = d3dBuffer; else mVolatileVB = NULL; } // NOTE: We do not use the stream offset here for stream 0 // as that feature is *supposedly* not as well supported as // using the start index in drawPrimitive. // // If we can verify that this is not the case then we should // start using this method exclusively for all streams. D3D9Assert( mD3DDevice->SetStreamSource( stream, d3dBuffer ? d3dBuffer->vb : NULL, d3dBuffer && stream != 0 ? d3dBuffer->mVolatileStart * d3dBuffer->mVertexSize : 0, d3dBuffer ? d3dBuffer->mVertexSize : 0 ), "GFXD3D9Device::setVertexStream - Failed to set stream source." ); }
bool GFXD3D9Device::beginSceneInternal() { HRESULT hr = mD3DDevice->BeginScene(); D3D9Assert(hr, "GFXD3D9Device::beginSceneInternal - failed to BeginScene"); mCanCurrentlyRender = SUCCEEDED(hr); return mCanCurrentlyRender; }
void GFXD3D9Device::_setPrimitiveBuffer( GFXPrimitiveBuffer *buffer ) { AssertFatal( mCurrentOpenAllocPB == NULL, "Calling setIndexBuffer() when a index buffer is still open for editing" ); mCurrentPB = static_cast<GFXD3D9PrimitiveBuffer *>( buffer ); D3D9Assert( mD3DDevice->SetIndices( mCurrentPB->ib ), "Failed to set indices" ); }
//----------------------------------------------------------------------------- // allocVertexBuffer //----------------------------------------------------------------------------- GFXVertexBuffer * GFXD3D9Device::allocVertexBuffer( U32 numVerts, const GFXVertexFormat *vertexFormat, U32 vertSize, GFXBufferType bufferType ) { GFXD3D9VertexBuffer *res = new GFXD3D9VertexBuffer( this, numVerts, vertexFormat, vertSize, bufferType ); // Determine usage flags U32 usage = 0; D3DPOOL pool = D3DPOOL_DEFAULT; res->mNumVerts = 0; // Assumptions: // - static buffers are write once, use many // - dynamic buffers are write many, use many // - volatile buffers are write once, use once // You may never read from a buffer. switch(bufferType) { case GFXBufferTypeStatic: pool = D3DPOOL_MANAGED; res->registerResourceWithDevice(this); break; case GFXBufferTypeDynamic: case GFXBufferTypeVolatile: pool = D3DPOOL_DEFAULT; res->registerResourceWithDevice(this); usage |= D3DUSAGE_WRITEONLY; #ifndef TORQUE_OS_XENON usage |= D3DUSAGE_DYNAMIC; #endif break; } // Create vertex buffer if(bufferType == GFXBufferTypeVolatile) { // Get volatile stuff from a pool... AssertFatal( numVerts <= MAX_DYNAMIC_VERTS, "Cannot allocate that many verts in a volatile vertex buffer, increase MAX_DYNAMIC_VERTS! -- BJG" ); // This is all we need here, everything else lives in the lock method on the // buffer... -- BJG } else { allocVertexDecl( res ); // Get a new buffer... D3D9Assert( mD3DDevice->CreateVertexBuffer( vertSize * numVerts, usage, 0, pool, &res->vb, NULL ), "Failed to allocate VB" ); } res->mNumVerts = numVerts; return res; }
//----------------------------------------------------------------------------- // Reset D3D device //----------------------------------------------------------------------------- void GFXPCD3D9Device::reset( D3DPRESENT_PARAMETERS &d3dpp ) { if(!mD3DDevice) return; mInitialized = false; mMultisampleType = d3dpp.MultiSampleType; mMultisampleLevel = d3dpp.MultiSampleQuality; _validateMultisampleParams(d3dpp.BackBufferFormat, mMultisampleType, mMultisampleLevel); // Clean up some commonly dangling state. This helps prevents issues with // items that are destroyed by the texture manager callbacks and recreated // later, but still left bound. setVertexBuffer(NULL); setPrimitiveBuffer(NULL); for(S32 i=0; i<getNumSamplers(); i++) setTexture(i, NULL); // Deal with the depth/stencil buffer. if(mDeviceDepthStencil) { Con::printf("GFXPCD3D9Device::reset - depthstencil %x has %d ref's", mDeviceDepthStencil, mDeviceDepthStencil->AddRef()-1); mDeviceDepthStencil->Release(); } // First release all the stuff we allocated from D3DPOOL_DEFAULT releaseDefaultPoolResources(); // reset device Con::printf( "--- Resetting D3D Device ---" ); HRESULT hres = S_OK; hres = mD3DDevice->Reset( &d3dpp ); if( FAILED( hres ) ) { while( mD3DDevice->TestCooperativeLevel() == D3DERR_DEVICELOST ) { Sleep( 100 ); } hres = mD3DDevice->Reset( &d3dpp ); } D3D9Assert( hres, "GFXD3D9Device::reset - Failed to create D3D Device!" ); mInitialized = true; // Setup default states initStates(); // Now re aquire all the resources we trashed earlier reacquireDefaultPoolResources(); // Mark everything dirty and flush to card, for sanity. updateStates(true); }
//----------------------------------------------------------------------------- // allocPrimitiveBuffer //----------------------------------------------------------------------------- GFXPrimitiveBuffer * GFXD3D9Device::allocPrimitiveBuffer( U32 numIndices, U32 numPrimitives, GFXBufferType bufferType ) { // Allocate a buffer to return GFXD3D9PrimitiveBuffer * res = new GFXD3D9PrimitiveBuffer(this, numIndices, numPrimitives, bufferType); // Determine usage flags U32 usage = 0; D3DPOOL pool = D3DPOOL_DEFAULT; // Assumptions: // - static buffers are write once, use many // - dynamic buffers are write many, use many // - volatile buffers are write once, use once // You may never read from a buffer. switch(bufferType) { case GFXBufferTypeStatic: pool = isD3D9Ex() ? D3DPOOL_DEFAULT : D3DPOOL_MANAGED; break; case GFXBufferTypeDynamic: case GFXBufferTypeVolatile: #ifndef TORQUE_OS_XENON usage |= D3DUSAGE_DYNAMIC; #endif break; } // Register resource res->registerResourceWithDevice(this); // We never allow reading from a primitive buffer. usage |= D3DUSAGE_WRITEONLY; // Create d3d index buffer if(bufferType == GFXBufferTypeVolatile) { // Get it from the pool if it's a volatile... AssertFatal( numIndices < MAX_DYNAMIC_INDICES, "Cannot allocate that many indices in a volatile buffer, increase MAX_DYNAMIC_INDICES." ); res->ib = mDynamicPB->ib; // mDynamicPB->ib->AddRef(); res->mVolatileBuffer = mDynamicPB; } else { // Otherwise, get it as a seperate buffer... D3D9Assert(mD3DDevice->CreateIndexBuffer( sizeof(U16) * numIndices , usage, GFXD3D9IndexFormat[GFXIndexFormat16], pool, &res->ib, 0), "Failed to allocate an index buffer."); } return res; }
void GFXPCD3D9TextureTarget::resolve() { GFXDEBUGEVENT_SCOPE( GFXPCD3D9TextureTarget_resolve, ColorI::RED ); for (U32 i = 0; i < MaxRenderSlotId; i++) { // We use existance @ mResolveTargets as a flag that we need to copy // data from the rendertarget into the texture. if (mResolveTargets[i]) { IDirect3DSurface9 *surf; D3D9Assert( mResolveTargets[i]->get2DTex()->GetSurfaceLevel( 0, &surf ), "GFXPCD3D9TextureTarget::resolve() - GetSurfaceLevel failed!" ); D3D9Assert( mDevice->getDevice()->StretchRect( mTargets[i], NULL, surf, NULL, D3DTEXF_NONE ), "GFXPCD3D9TextureTarget::resolve() - StretchRect failed!" ); surf->Release(); } } }
void GFXPCD3D9TextureTarget::attachTexture( RenderSlot slot, GFXCubemap *tex, U32 face, U32 mipLevel/*=0*/ ) { GFXDEBUGEVENT_SCOPE( GFXPCD3D9TextureTarget_attachTexture_Cubemap, ColorI::RED ); AssertFatal(slot < MaxRenderSlotId, "GFXPCD3D9TextureTarget::attachTexture - out of range slot."); // Mark state as dirty so device can know to update. invalidateState(); // Release what we had, it's definitely going to change. mDevice->destroyD3DResource( mTargets[slot] ); // SAFE_RELEASE mTargets[slot] = NULL; mResolveTargets[slot] = NULL; // Cast the texture object to D3D... AssertFatal(!tex || dynamic_cast<GFXD3D9Cubemap*>(tex), "GFXD3DTextureTarget::attachTexture - invalid cubemap object."); GFXD3D9Cubemap *cube = static_cast<GFXD3D9Cubemap*>(tex); if(slot == Color0) { mTargetSize = Point2I::Zero; mTargetFormat = GFXFormatR8G8B8A8; } // Are we clearing? if(!tex) { // Yup - just exit, it'll stay NULL. return; } D3D9Assert(cube->mCubeTex->GetCubeMapSurface( (D3DCUBEMAP_FACES)face, mipLevel, &mTargets[slot] ), "GFXD3DTextureTarget::attachTexture - could not get surface level for the passed texture!"); // Update surface size if(slot == Color0) { IDirect3DSurface9 *surface = mTargets[Color0]; if ( surface ) { D3DSURFACE_DESC sd; surface->GetDesc(&sd); mTargetSize = Point2I(sd.Width, sd.Height); S32 format = sd.Format; GFXREVERSE_LOOKUP( GFXD3D9TextureFormat, GFXFormat, format ); mTargetFormat = (GFXFormat)format; } } }
void GFXD3D9PrimitiveBuffer::lock(U16 indexStart, U16 indexEnd, U16 **indexPtr) { AssertFatal(!mLocked, "GFXD3D9PrimitiveBuffer::lock - Can't lock a primitive buffer more than once!"); mLocked = true; U32 flags=0; switch(mBufferType) { case GFXBufferTypeStatic: // flags |= D3DLOCK_DISCARD; break; case GFXBufferTypeDynamic: // Always discard the content within a locked region. flags |= D3DLOCK_DISCARD; break; case GFXBufferTypeVolatile: // Get our range now... AssertFatal(indexStart == 0, "Cannot get a subrange on a volatile buffer."); AssertFatal(indexEnd < MAX_DYNAMIC_INDICES, "Cannot get more than MAX_DYNAMIC_INDICES in a volatile buffer. Up the constant!"); // Get the primtive buffer mVolatileBuffer = ((GFXD3D9Device*)mDevice)->mDynamicPB; AssertFatal( mVolatileBuffer, "GFXD3D9PrimitiveBuffer::lock - No dynamic primitive buffer was available!"); // We created the pool when we requested this volatile buffer, so assume it exists... if( mVolatileBuffer->mIndexCount + indexEnd > MAX_DYNAMIC_INDICES ) { flags |= D3DLOCK_DISCARD; mVolatileStart = indexStart = 0; indexEnd = indexEnd; } else { flags |= D3DLOCK_NOOVERWRITE; mVolatileStart = indexStart = mVolatileBuffer->mIndexCount; indexEnd += mVolatileBuffer->mIndexCount; } mVolatileBuffer->mIndexCount = indexEnd + 1; ib = mVolatileBuffer->ib; break; } D3D9Assert( ib->Lock(indexStart * sizeof(U16), (indexEnd - indexStart) * sizeof(U16), (void**)indexPtr, flags), "GFXD3D9PrimitiveBuffer::lock - Could not lock primitive buffer."); }
void GFXD3D9Device::setVertexStreamFrequency( U32 stream, U32 frequency ) { if ( frequency == 0 ) frequency = 1; else { if ( stream == 0 ) frequency = D3DSTREAMSOURCE_INDEXEDDATA | frequency; else frequency = D3DSTREAMSOURCE_INSTANCEDATA | frequency; } D3D9Assert( mD3DDevice->SetStreamSourceFreq( stream, frequency ), "GFXD3D9Device::setVertexStreamFrequency - Failed to set stream frequency." ); }
void GFXD3D9Device::drawPrimitive( GFXPrimitiveType primType, U32 vertexStart, U32 primitiveCount ) { // This is done to avoid the function call overhead if possible if( mStateDirty ) updateStates(); if (mCurrentShaderConstBuffer) setShaderConstBufferInternal(mCurrentShaderConstBuffer); if ( mVolatileVB ) vertexStart += mVolatileVB->mVolatileStart; D3D9Assert( mD3DDevice->DrawPrimitive( GFXD3D9PrimType[primType], vertexStart, primitiveCount ), "Failed to draw primitives" ); mDeviceStatistics.mDrawCalls++; if ( mVertexBufferFrequency[0] > 1 ) mDeviceStatistics.mPolyCount += primitiveCount * mVertexBufferFrequency[0]; else mDeviceStatistics.mPolyCount += primitiveCount; }
GFXFormat GFXPCD3D9Device::selectSupportedFormat(GFXTextureProfile *profile, const Vector<GFXFormat> &formats, bool texture, bool mustblend, bool mustfilter) { DWORD usage = 0; if(profile->isDynamic()) usage |= D3DUSAGE_DYNAMIC; if(profile->isRenderTarget()) usage |= D3DUSAGE_RENDERTARGET; if(profile->isZTarget()) usage |= D3DUSAGE_DEPTHSTENCIL; if(mustblend) usage |= D3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING; if(mustfilter) usage |= D3DUSAGE_QUERY_FILTER; D3DDISPLAYMODE mode; D3D9Assert(mD3D->GetAdapterDisplayMode(mAdapterIndex, &mode), "Unable to get adapter mode."); D3DRESOURCETYPE type; if(texture) type = D3DRTYPE_TEXTURE; else type = D3DRTYPE_SURFACE; for(U32 i=0; i<formats.size(); i++) { if(mD3D->CheckDeviceFormat(mAdapterIndex, D3DDEVTYPE_HAL, mode.Format, usage, type, GFXD3D9TextureFormat[formats[i]]) == D3D_OK) return formats[i]; } return GFXFormatR8G8B8A8; }
void GFXD3D9Device::_updateRenderTargets() { if ( mRTDirty || ( mCurrentRT && mCurrentRT->isPendingState() ) ) { if ( mRTDeactivate ) { mRTDeactivate->deactivate(); mRTDeactivate = NULL; } // NOTE: The render target changes are not really accurate // as the GFXTextureTarget supports MRT internally. So when // we activate a GFXTarget it could result in multiple calls // to SetRenderTarget on the actual device. mDeviceStatistics.mRenderTargetChanges++; mCurrentRT->activate(); mRTDirty = false; } if ( mViewportDirty ) { D3DVIEWPORT9 viewport; viewport.X = mViewport.point.x; viewport.Y = mViewport.point.y; viewport.Width = mViewport.extent.x; viewport.Height = mViewport.extent.y; viewport.MinZ = 0.0; viewport.MaxZ = 1.0; D3D9Assert( mD3DDevice->SetViewport( &viewport ), "GFXD3D9Device::_updateRenderTargets() - Error setting viewport!" ); mViewportDirty = false; } }
/// Load a texture from a proper DDSFile instance. bool GFXD3D9TextureManager::_loadTexture(GFXTextureObject *aTexture, DDSFile *dds) { PROFILE_SCOPE(GFXD3D9TextureManager_loadTextureDDS); GFXD3D9TextureObject *texture = static_cast<GFXD3D9TextureObject*>(aTexture); // Fill the texture... for( int i = 0; i < aTexture->mMipLevels; i++ ) { PROFILE_SCOPE(GFXD3DTexMan_loadSurface); LPDIRECT3DSURFACE9 surf = NULL; D3D9Assert(texture->get2DTex()->GetSurfaceLevel( i, &surf ), "Failed to get surface"); #if defined(TORQUE_OS_XENON) XGTEXTURE_DESC surfDesc; dMemset(&surfDesc, 0, sizeof(XGTEXTURE_DESC)); XGGetSurfaceDesc(surf, &surfDesc); RECT srcRect; srcRect.top = srcRect.left = 0; srcRect.bottom = dds->getHeight(i); srcRect.right = dds->getWidth(i); D3DXLoadSurfaceFromMemory(surf, NULL, NULL, dds->mSurfaces[0]->mMips[i], (D3DFORMAT)MAKELINFMT(GFXD3D9TextureFormat[dds->mFormat]), dds->getSurfacePitch(i), NULL, &srcRect, false, 0, 0, D3DX_FILTER_NONE, 0); #else GFXD3D9Device* dev = static_cast<GFXD3D9Device *>(GFX); if (dev->isD3D9Ex()) { RECT r; r.top = r.left = 0; r.bottom = dds->getHeight(i); r.right = dds->getWidth(i); D3DXLoadSurfaceFromMemory(surf, NULL, NULL, dds->mSurfaces[0]->mMips[i], GFXD3D9TextureFormat[dds->mFormat], dds->getSurfacePitch(i), NULL, &r, D3DX_DEFAULT, 0); } else { D3DLOCKED_RECT lockedRect; D3D9Assert( surf->LockRect( &lockedRect, NULL, 0 ), "Failed to lock surface level for load" ); AssertFatal( dds->mSurfaces.size() > 0, "Assumption failed. DDSFile has no surfaces." ); if ( dds->getSurfacePitch( i ) != lockedRect.Pitch ) { // Do a row-by-row copy. U32 srcPitch = dds->getSurfacePitch( i ); U32 srcHeight = dds->getHeight(); U8* srcBytes = dds->mSurfaces[0]->mMips[i]; U8* dstBytes = (U8*)lockedRect.pBits; for (U32 i = 0; i<srcHeight; i++) { dMemcpy( dstBytes, srcBytes, srcPitch ); dstBytes += lockedRect.Pitch; srcBytes += srcPitch; } surf->UnlockRect(); surf->Release(); return true; } dMemcpy( lockedRect.pBits, dds->mSurfaces[0]->mMips[i], dds->getSurfaceSize(i) ); surf->UnlockRect(); } #endif surf->Release(); } return true; }
void GFXD3D9Device::allocVertexDecl( GFXD3D9VertexBuffer *vertBuff ) { PROFILE_SCOPE( GFXD3D9Device_AllocVertexDecl ); if ( vertBuff->decl ) return; const GFXVertexFormat *vertexFormat = vertBuff->mVertexFormat; // First check the map... you shouldn't allocate VBs very often // if you want performance. The map lookup should never become // a performance bottleneck. vertBuff->decl = mVertexDecls[vertexFormat->getDescription()]; if ( vertBuff->decl ) return; // Setup the declaration struct. U32 elemCount = vertexFormat->getElementCount(); U32 offset = 0; D3DVERTEXELEMENT9 *vd = new D3DVERTEXELEMENT9[ elemCount + 1 ]; for ( U32 i=0; i < elemCount; i++ ) { const GFXVertexElement &element = vertexFormat->getElement( i ); vd[i].Stream = 0; vd[i].Offset = offset; vd[i].Type = GFXD3D9DeclType[element.getType()]; vd[i].Method = D3DDECLMETHOD_DEFAULT; // We force the usage index of 0 for everything but // texture coords for now... this may change later. vd[i].UsageIndex = 0; if ( element.isSemantic( GFXSemantic::POSITION ) ) vd[i].Usage = D3DDECLUSAGE_POSITION; else if ( element.isSemantic( GFXSemantic::NORMAL ) ) vd[i].Usage = D3DDECLUSAGE_NORMAL; else if ( element.isSemantic( GFXSemantic::COLOR ) ) vd[i].Usage = D3DDECLUSAGE_COLOR; else if ( element.isSemantic( GFXSemantic::TANGENT ) ) vd[i].Usage = D3DDECLUSAGE_TANGENT; else if ( element.isSemantic( GFXSemantic::BINORMAL ) ) vd[i].Usage = D3DDECLUSAGE_BINORMAL; else { // Anything that falls thru to here will be a texture coord. vd[i].Usage = D3DDECLUSAGE_TEXCOORD; vd[i].UsageIndex = element.getSemanticIndex(); } offset += element.getSizeInBytes(); } D3DVERTEXELEMENT9 declEnd = D3DDECL_END(); vd[elemCount] = declEnd; D3D9Assert( mD3DDevice->CreateVertexDeclaration( vd, &vertBuff->decl ), "GFXD3D9Device::allocVertexDecl - Failed to create vertex declaration!" ); delete[] vd; // Store it in the cache. mVertexDecls[vertexFormat->getDescription()] = vertBuff->decl; }
//----------------------------------------------------------------------------- // loadTexture - raw //----------------------------------------------------------------------------- bool GFXD3D9TextureManager::_loadTexture( GFXTextureObject *inTex, void *raw ) { PROFILE_SCOPE(GFXD3D9TextureManager_loadTextureRaw); GFXD3D9TextureObject *texture = (GFXD3D9TextureObject *) inTex; // currently only for volume textures... if( texture->getDepth() < 1 ) return false; U32 bytesPerPix = 1; switch( texture->mFormat ) { case GFXFormatR8G8B8: bytesPerPix = 3; break; case GFXFormatR8G8B8A8: case GFXFormatR8G8B8X8: bytesPerPix = 4; break; } U32 rowPitch = texture->getWidth() * bytesPerPix; U32 slicePitch = texture->getWidth() * texture->getHeight() * bytesPerPix; D3DBOX box; box.Left = 0; box.Right = texture->getWidth(); box.Front = 0; box.Back = texture->getDepth(); box.Top = 0; box.Bottom = texture->getHeight(); LPDIRECT3DVOLUME9 volume = NULL; D3D9Assert( texture->get3DTex()->GetVolumeLevel( 0, &volume ), "Failed to load volume" ); #ifdef TORQUE_OS_XENON D3DLOCKED_BOX lockedBox; volume->LockBox( &lockedBox, &box, 0 ); dMemcpy( lockedBox.pBits, raw, slicePitch * texture->getDepth() ); volume->UnlockBox(); #else D3D9Assert( GFXD3DX.D3DXLoadVolumeFromMemory( volume, NULL, NULL, raw, GFXD3D9TextureFormat[texture->mFormat], rowPitch, slicePitch, NULL, &box, #ifdef TORQUE_OS_XENON false, 0, 0, 0, // Unique to Xenon -pw #endif D3DX_FILTER_NONE, 0 ), "Failed to load volume texture" ); #endif volume->Release(); return true; }
//----------------------------------------------------------------------------- // _innerCreateTexture //----------------------------------------------------------------------------- void GFXD3D9TextureManager::_innerCreateTexture( GFXD3D9TextureObject *retTex, U32 height, U32 width, U32 depth, GFXFormat format, GFXTextureProfile *profile, U32 numMipLevels, bool forceMips, S32 antialiasLevel) { GFXD3D9Device* d3d = static_cast<GFXD3D9Device*>(GFX); // Some relevant helper information... bool supportsAutoMips = GFX->getCardProfiler()->queryProfile("autoMipMapLevel", true); DWORD usage = 0; // 0, D3DUSAGE_RENDERTARGET, or D3DUSAGE_DYNAMIC D3DPOOL pool = D3DPOOL_DEFAULT; retTex->mProfile = profile; D3DFORMAT d3dTextureFormat = GFXD3D9TextureFormat[format]; #ifndef TORQUE_OS_XENON if( retTex->mProfile->isDynamic() ) { usage = D3DUSAGE_DYNAMIC; } else { usage = 0; pool = d3d->isD3D9Ex() ? D3DPOOL_DEFAULT : D3DPOOL_MANAGED; } if( retTex->mProfile->isRenderTarget() ) { pool = D3DPOOL_DEFAULT; usage |= D3DUSAGE_RENDERTARGET; } if(retTex->mProfile->isZTarget()) { usage |= D3DUSAGE_DEPTHSTENCIL; pool = D3DPOOL_DEFAULT; } if( retTex->mProfile->isSystemMemory() ) { pool = D3DPOOL_SYSTEMMEM; } if( supportsAutoMips && !forceMips && !retTex->mProfile->isSystemMemory() && numMipLevels == 0 && !(depth > 0) ) { usage |= D3DUSAGE_AUTOGENMIPMAP; } #else if(retTex->mProfile->isRenderTarget()) { d3dTextureFormat = (D3DFORMAT)MAKELEFMT(d3dTextureFormat); } #endif // Set the managed flag... retTex->isManaged = (pool == D3DPOOL_MANAGED) || d3d->isD3D9Ex(); if( depth > 0 ) { #ifdef TORQUE_OS_XENON D3D9Assert( mD3DDevice->CreateVolumeTexture( width, height, depth, numMipLevels, 0 /* usage ignored on the 360 */, d3dTextureFormat, pool, retTex->get3DTexPtr(), NULL), "Failed to create volume texture" ); #else D3D9Assert( GFXD3DX.D3DXCreateVolumeTexture( mD3DDevice, width, height, depth, numMipLevels, usage, d3dTextureFormat, pool, retTex->get3DTexPtr() ), "GFXD3D9TextureManager::_createTexture - failed to create volume texture!" ); #endif retTex->mTextureSize.set( width, height, depth ); retTex->mMipLevels = retTex->get3DTex()->GetLevelCount(); // required for 3D texture support - John Kabus retTex->mFormat = format; } else { #ifdef TORQUE_OS_XENON D3D9Assert( mD3DDevice->CreateTexture(width, height, numMipLevels, usage, d3dTextureFormat, pool, retTex->get2DTexPtr(), NULL), "Failed to create texture" ); retTex->mMipLevels = retTex->get2DTex()->GetLevelCount(); #else // Figure out AA settings for depth and render targets D3DMULTISAMPLE_TYPE mstype; DWORD mslevel; switch (antialiasLevel) { case 0 : mstype = D3DMULTISAMPLE_NONE; mslevel = 0; break; case AA_MATCH_BACKBUFFER : mstype = d3d->getMultisampleType(); mslevel = d3d->getMultisampleLevel(); break; default : { mstype = D3DMULTISAMPLE_NONMASKABLE; mslevel = antialiasLevel; #ifdef TORQUE_DEBUG DWORD MaxSampleQualities; d3d->getD3D()->CheckDeviceMultiSampleType(mAdapterIndex, D3DDEVTYPE_HAL, d3dTextureFormat, FALSE, D3DMULTISAMPLE_NONMASKABLE, &MaxSampleQualities); AssertFatal(mslevel < MaxSampleQualities, "Invalid AA level!"); #endif } break; } bool fastCreate = true; // Check for power of 2 textures - this is a problem with FX 5xxx cards // with current drivers - 3/2/05 if( !isPow2(width) || !isPow2(height) ) { fastCreate = false; } if(retTex->mProfile->isZTarget()) { D3D9Assert(mD3DDevice->CreateDepthStencilSurface(width, height, d3dTextureFormat, mstype, mslevel, retTex->mProfile->canDiscard(), retTex->getSurfacePtr(), NULL), "Failed to create Z surface" ); retTex->mFormat = format; // Assigning format like this should be fine. } else { // Try to create the texture directly - should gain us a bit in high // performance cases where we know we're creating good stuff and we // don't want to bother with D3DX - slow function. HRESULT res = D3DERR_INVALIDCALL; if( fastCreate ) { res = mD3DDevice->CreateTexture(width, height, numMipLevels, usage, d3dTextureFormat, pool, retTex->get2DTexPtr(), NULL); } if( !fastCreate || (res != D3D_OK) ) { D3D9Assert( GFXD3DX.D3DXCreateTexture( mD3DDevice, width, height, numMipLevels, usage, d3dTextureFormat, pool, retTex->get2DTexPtr() ), "GFXD3D9TextureManager::_createTexture - failed to create texture!" ); } // If this is a render target, and it wants AA or wants to match the backbuffer (for example, to share the z) // Check the caps though, if we can't stretchrect between textures, use the old RT method. (Which hopefully means // that they can't force AA on us as well.) if (retTex->mProfile->isRenderTarget() && mslevel != 0 && (mDeviceCaps.Caps2 && D3DDEVCAPS2_CAN_STRETCHRECT_FROM_TEXTURES)) { D3D9Assert(mD3DDevice->CreateRenderTarget(width, height, d3dTextureFormat, mstype, mslevel, false, retTex->getSurfacePtr(), NULL), "GFXD3D9TextureManager::_createTexture - unable to create render target"); } // All done! retTex->mMipLevels = retTex->get2DTex()->GetLevelCount(); } #endif // Get the actual size of the texture... D3DSURFACE_DESC probeDesc; ZeroMemory(&probeDesc, sizeof probeDesc); if( retTex->get2DTex() != NULL ) D3D9Assert( retTex->get2DTex()->GetLevelDesc( 0, &probeDesc ), "Failed to get surface description"); else if( retTex->getSurface() != NULL ) D3D9Assert( retTex->getSurface()->GetDesc( &probeDesc ), "Failed to get surface description"); retTex->mTextureSize.set(probeDesc.Width, probeDesc.Height, 0); int fmt = probeDesc.Format; #if !defined(TORQUE_OS_XENON) GFXREVERSE_LOOKUP( GFXD3D9TextureFormat, GFXFormat, fmt ); retTex->mFormat = (GFXFormat)fmt; #else retTex->mFormat = format; #endif } }