📄 qpaintengine_d3d.cpp
字号:
m_texturestates[Stage][Type] = Value; } return m_pDevice->SetTextureStageState(Stage, Type, Value);}STDMETHODIMP QD3DStateManager::SetSamplerState(DWORD Sampler, D3DSAMPLERSTATETYPE Type, DWORD Value){ if (Sampler < D3D_STAGE_COUNT && Type < D3D_SAMPLE_STATES) { if (m_samplerstates[Sampler][Type] == Value) return S_OK; m_samplerstates[Sampler][Type] = Value; } return m_pDevice->SetSamplerState(Sampler, Type, Value);}STDMETHODIMP QD3DStateManager::SetNPatchMode(FLOAT NumSegments){ return m_pDevice->SetNPatchMode(NumSegments);}STDMETHODIMP QD3DStateManager::SetFVF(DWORD FVF){ return m_pDevice->SetFVF(FVF);}STDMETHODIMP QD3DStateManager::SetVertexShader(LPDIRECT3DVERTEXSHADER9 pShader){ if (m_vertexshader == pShader) return S_OK; m_vertexshader = pShader; return m_pDevice->SetVertexShader(pShader);}STDMETHODIMP QD3DStateManager::SetVertexShaderConstantF(UINT RegisterIndex, CONST FLOAT *pConstantData, UINT RegisterCount){ return m_pDevice->SetVertexShaderConstantF(RegisterIndex, pConstantData, RegisterCount);}STDMETHODIMP QD3DStateManager::SetVertexShaderConstantI(UINT RegisterIndex, CONST INT *pConstantData, UINT RegisterCount){ return m_pDevice->SetVertexShaderConstantI(RegisterIndex, pConstantData, RegisterCount);}STDMETHODIMP QD3DStateManager::SetVertexShaderConstantB(UINT RegisterIndex, CONST BOOL *pConstantData, UINT RegisterCount){ return m_pDevice->SetVertexShaderConstantB(RegisterIndex, pConstantData, RegisterCount);}STDMETHODIMP QD3DStateManager::SetPixelShader(LPDIRECT3DPIXELSHADER9 pShader){ if (m_pixelshader == pShader) return S_OK; m_pixelshader = pShader; return m_pDevice->SetPixelShader(pShader);}STDMETHODIMP QD3DStateManager::SetPixelShaderConstantF(UINT RegisterIndex, CONST FLOAT *pConstantData, UINT RegisterCount){ return m_pDevice->SetPixelShaderConstantF(RegisterIndex, pConstantData, RegisterCount);}STDMETHODIMP QD3DStateManager::SetPixelShaderConstantI(UINT RegisterIndex, CONST INT *pConstantData, UINT RegisterCount){ return m_pDevice->SetPixelShaderConstantI(RegisterIndex, pConstantData, RegisterCount);}STDMETHODIMP QD3DStateManager::SetPixelShaderConstantB(UINT RegisterIndex, CONST BOOL *pConstantData, UINT RegisterCount){ return m_pDevice->SetPixelShaderConstantB(RegisterIndex, pConstantData, RegisterCount);}#define QD3D_GRADIENT_CACHE_SIZE 60#define QD3D_GRADIENT_PALETTE_SIZE 1024class QD3DGradientCache{ struct CacheInfo { inline CacheInfo(QGradientStops s, qreal op) : stops(s), opacity(op) {} IDirect3DTexture9 *texture; QGradientStops stops; qreal opacity; }; typedef QMultiHash<quint64, CacheInfo> QD3DGradientColorTableHash;public: QD3DGradientCache(LPDIRECT3DDEVICE9 device); ~QD3DGradientCache(); inline IDirect3DTexture9 *getBuffer(const QGradientStops &stops, qreal opacity);protected: inline void generateGradientColorTable(const QGradientStops& s, uint *colorTable, int size, qreal opacity) const; IDirect3DTexture9 *addCacheElement(quint64 hash_val, const QGradientStops &stops, qreal opacity); void cleanCache(); QD3DGradientColorTableHash cache; LPDIRECT3DDEVICE9 m_device;};QD3DGradientCache::QD3DGradientCache(LPDIRECT3DDEVICE9 device) : m_device(device){}QD3DGradientCache::~QD3DGradientCache(){ cleanCache();}inline IDirect3DTexture9 *QD3DGradientCache::getBuffer(const QGradientStops &stops, qreal opacity){ quint64 hash_val = 0; for (int i = 0; i < stops.size() && i <= 2; i++) hash_val += stops[i].second.rgba(); QD3DGradientColorTableHash::const_iterator it = cache.constFind(hash_val); if (it == cache.constEnd()) return addCacheElement(hash_val, stops, opacity); else { do { const CacheInfo &cache_info = it.value(); if (cache_info.stops == stops && cache_info.opacity == opacity) { return cache_info.texture; } ++it; } while (it != cache.constEnd() && it.key() == hash_val); // an exact match for these stops and opacity was not found, create new cache return addCacheElement(hash_val, stops, opacity); }}void QD3DGradientCache::generateGradientColorTable(const QGradientStops& s, uint *colorTable, int size, qreal opacity) const{ int pos = 0; qreal fpos = 0.0; qreal incr = 1.0 / qreal(size); QVector<uint> colors(s.size()); for (int i = 0; i < s.size(); ++i) colors[i] = s[i].second.rgba(); uint alpha = qRound(opacity * 255); while (fpos < s.first().first) { colorTable[pos] = ARGB_COMBINE_ALPHA(colors[0], alpha); pos++; fpos += incr; } for (int i = 0; i < s.size() - 1; ++i) { qreal delta = 1/(s[i+1].first - s[i].first); while (fpos < s[i+1].first && pos < size) { int dist = int(256 * ((fpos - s[i].first) * delta)); int idist = 256 - dist; uint current_color = ARGB_COMBINE_ALPHA(colors[i], alpha); uint next_color = ARGB_COMBINE_ALPHA(colors[i+1], alpha);#if Q_BYTE_ORDER == Q_LITTLE_ENDIAN colorTable[pos] = INTERPOLATE_PIXEL_256(current_color, idist, next_color, dist);#else uint c = INTERPOLATE_PIXEL_256(current_color, idist, next_color, dist); colorTable[pos] = ( (c << 24) & 0xff000000) | ((c >> 24) & 0x000000ff) | ((c << 8) & 0x00ff0000) | ((c >> 8) & 0x0000ff00);#endif // Q_BYTE_ORDER ++pos; fpos += incr; } } for (;pos < size; ++pos) colorTable[pos] = colors[s.size() - 1];}IDirect3DTexture9 *QD3DGradientCache::addCacheElement(quint64 hash_val, const QGradientStops &stops, qreal opacity){ if (cache.size() == QD3D_GRADIENT_CACHE_SIZE) { int elem_to_remove = qrand() % QD3D_GRADIENT_CACHE_SIZE; uint key = cache.keys()[elem_to_remove]; // need to call release on each removed cache entry: QD3DGradientColorTableHash::const_iterator it = cache.constFind(key); do { it.value().texture->Release(); } while (++it != cache.constEnd() && it.key() == key); cache.remove(key); // may remove more than 1, but OK } CacheInfo cache_entry(stops, opacity); uint buffer[QD3D_GRADIENT_PALETTE_SIZE]; generateGradientColorTable(stops, buffer, QD3D_GRADIENT_PALETTE_SIZE, opacity); if (FAILED(m_device->CreateTexture(QD3D_GRADIENT_PALETTE_SIZE, 1, 1, 0, D3DFMT_A8R8G8B8, D3DPOOL_MANAGED, &cache_entry.texture, 0))) { qWarning("QD3DGradientCache::addCacheElement(): unable to create Direct3D texture."); return 0; } D3DLOCKED_RECT rect; if (FAILED(cache_entry.texture->LockRect(0, &rect, 0, 0))) { qDebug() << "QD3DGradientCache::addCacheElement(): unable to lock texture rect."; return 0; } memcpy(rect.pBits, buffer, rect.Pitch); cache_entry.texture->UnlockRect(0); return cache.insert(hash_val, cache_entry).value().texture;}void QD3DGradientCache::cleanCache(){ QD3DGradientColorTableHash::const_iterator it = cache.constBegin(); for (; it != cache.constEnd(); ++it) { const CacheInfo &cache_info = it.value(); cache_info.texture->Release(); } cache.clear();}QD3DSurfaceManager::QD3DSurfaceManager() : m_status(NoStatus), m_dummy(0), m_device(0), m_pd(0), m_current(0){}QD3DSurfaceManager::~QD3DSurfaceManager(){}void QD3DSurfaceManager::setPaintDevice(QPaintDevice *pd){ m_status = NoStatus; m_pd = pd; m_current = 0; if (m_device->TestCooperativeLevel() != D3D_OK) { m_status = NeedsResetting; return; } m_current = m_swapchains.value(pd, 0); QWidget *w = static_cast<QWidget*>(pd); if (m_current) { if (m_current->size != w->size()) { m_swapchains.remove(pd); m_current->surface->Release(); m_current->swapchain->Release(); delete m_current; m_current = 0; } } if (!m_current) { m_current = createSwapChain(w); updateMaxSize(); }}int QD3DSurfaceManager::status() const{ return m_status;}void QD3DSurfaceManager::reset(){ QList<QPaintDevice *> pds = m_swapchains.keys(); QMap<QPaintDevice *, D3DSwapChain *>::const_iterator i = m_swapchains.constBegin(); while (i != m_swapchains.constEnd()) { i.value()->surface->Release(); i.value()->swapchain->Release(); ++i; } qDeleteAll(m_swapchains.values()); m_swapchains.clear(); D3DPRESENT_PARAMETERS params; initPresentParameters(¶ms); params.hDeviceWindow = m_dummy; HRESULT res = m_device->Reset(¶ms); if (FAILED(res)) { switch (res) { case D3DERR_DEVICELOST: qWarning("QDirect3DPaintEngine: Reset failed (D3DERR_DEVICELOST)"); break; case D3DERR_DRIVERINTERNALERROR: qWarning("QDirect3DPaintEngine: Reset failed (D3DERR_DRIVERINTERNALERROR)"); break; case D3DERR_OUTOFVIDEOMEMORY: qWarning("QDirect3DPaintEngine: Reset failed (D3DERR_OUTOFVIDEOMEMORY)"); break; default: qWarning("QDirect3DPaintEngine: Reset failed"); }; } for (int i=0; i<pds.count(); ++i) { QWidget *w = static_cast<QWidget*>(pds.at(i)); createSwapChain(w); } // reset the mask as well m_status = MaxSizeChanged; setPaintDevice(m_pd); updateMaxSize();}LPDIRECT3DSURFACE9 QD3DSurfaceManager::renderTarget(){ return m_current ? m_current->surface : 0;}LPDIRECT3DSURFACE9 QD3DSurfaceManager::surface(QPaintDevice *pd){ D3DSwapChain *swapchain = m_swapchains.value(pd, 0); return swapchain ? swapchain->surface : 0;}LPDIRECT3DSWAPCHAIN9 QD3DSurfaceManager::swapChain(QPaintDevice *pd){ D3DSwapChain *swapchain = m_swapchains.value(pd, 0); return swapchain ? swapchain->swapchain : 0;}void QD3DSurfaceManager::releasePaintDevice(QPaintDevice *pd){ D3DSwapChain *swapchain = m_swapchains.take(pd); if (swapchain) { swapchain->surface->Release(); swapchain->swapchain->Release(); delete swapchain; if (swapchain == m_current) m_current = 0; }}LPDIRECT3DDEVICE9 QD3DSurfaceManager::device(){ return m_device;}void QD3DSurfaceManager::cleanup(){ QPixmapCache::clear(); qd3d_glyph_cache()->cleanCache(); // release doomed textures for (int k=0; k<qd3d_release_list.size(); ++k) qd3d_release_list.at(k)->Release(); qd3d_release_list.clear(); QMap<QPaintDevice *, D3DSwapChain *>::const_iterator i = m_swapchains.constBegin(); while (i != m_swapchains.constEnd()) { i.value()->surface->Release(); i.value()->swapchain->Release(); ++i; } qDeleteAll(m_swapchains.values()); if (m_device) m_device->Release(); DestroyWindow(m_dummy); QString cname(QLatin1String("qt_d3d_dummy")); QT_WA({ UnregisterClass((TCHAR*)cname.utf16(), (HINSTANCE)qWinAppInst()); } , { UnregisterClassA(cname.toLatin1(), (HINSTANCE)qWinAppInst()); });}QSize QD3DSurfaceManager::maxSize() const{ return m_max_size;}extern "C" { LRESULT CALLBACK QtWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam);};void QD3DSurfaceManager::init(LPDIRECT3D9 object){ QString cname(QLatin1String("qt_d3d_dummy")); uint style = CS_DBLCLKS | CS_SAVEBITS; ATOM atom; QT_WA({ WNDCLASS wc; wc.style = style; wc.lpfnWndProc = (WNDPROC)QtWndProc; wc.cbClsExtra = 0; wc.cbWndExtra = 0; wc.hInstance = (HINSTANCE)qWinAppInst(); wc.hIcon = 0; wc.hCursor = 0; wc.hbrBackground = 0; wc.lpszMenuName = 0; wc.lpszClassName = (TCHAR*)cname.utf16(); atom = RegisterClass(&wc); } , { WNDCLASSA wc; wc.style = style; wc.lpfnWndProc = (WNDPROC)QtWndProc; wc.cbClsExtra = 0; wc.cbWndExtra = 0; wc.hInstance = (HINSTANCE)qWinAppInst(); wc.hIcon = 0; wc.hCursor = 0; wc.hbrBackground = 0; wc.lpszMenuName = 0; QByteArray tempArray = cname.toLatin1(); wc.lpszClassName = tempArray; atom = RegisterClassA(&wc); }); QT_WA({
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -