📄 qpaintengine_d3d.cpp
字号:
const TCHAR *className = (TCHAR*)cname.utf16(); m_dummy = CreateWindow(className, className, 0, 0, 0, 1, 1, 0, 0, qWinAppInst(), 0); } , { m_dummy = CreateWindowA(cname.toLatin1(), cname.toLatin1(), 0, 0, 0, 1, 1, 0, 0, qWinAppInst(), 0); }); D3DPRESENT_PARAMETERS params; initPresentParameters(¶ms); params.hDeviceWindow = m_dummy; HRESULT res = object->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, 0, D3DCREATE_PUREDEVICE|D3DCREATE_HARDWARE_VERTEXPROCESSING|D3DCREATE_NOWINDOWCHANGES|D3DCREATE_FPU_PRESERVE, ¶ms, &m_device); if (FAILED(res) || m_device == 0) qWarning("QDirect3DPaintEngine: failed to create Direct3D device (error=0x%x).", res);}void QD3DSurfaceManager::updateMaxSize(){ int w = 0, h = 0; QMap<QPaintDevice *, D3DSwapChain *>::const_iterator i = m_swapchains.constBegin(); while (i != m_swapchains.constEnd()) { int nw = i.key()->width(); if (nw > w) w = nw; int nh = i.key()->height(); if (nh > h) h = nh; ++i; } QSize newsize = QSize(w, h); if (newsize != m_max_size) { m_status |= MaxSizeChanged; m_max_size = newsize; }}void QD3DSurfaceManager::initPresentParameters(D3DPRESENT_PARAMETERS *params){ ZeroMemory(params, sizeof(D3DPRESENT_PARAMETERS)); params->Windowed = true; params->SwapEffect = D3DSWAPEFFECT_COPY; params->BackBufferFormat = D3DFMT_UNKNOWN; params->PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE; params->Flags = D3DPRESENTFLAG_LOCKABLE_BACKBUFFER;}QD3DSurfaceManager::D3DSwapChain *QD3DSurfaceManager::createSwapChain(QWidget *w){ D3DPRESENT_PARAMETERS params; initPresentParameters(¶ms); params.hDeviceWindow = w->winId(); D3DSwapChain *swapchain = new D3DSwapChain(); swapchain->size = w->size(); if (FAILED(m_device->CreateAdditionalSwapChain(¶ms, &swapchain->swapchain))) qWarning("QDirect3DPaintEngine: CreateAdditionalSwapChain failed"); if (FAILED(swapchain->swapchain->GetBackBuffer(0, D3DBACKBUFFER_TYPE_MONO, &swapchain->surface))) qWarning("QDirect3DPaintEngine: GetBackBuffer failed"); m_swapchains.insert(w, swapchain); connect(w, SIGNAL(destroyed(QObject *)), SLOT(cleanupPaintDevice(QObject *))); // init with background color QColor bg = w->palette().color(QPalette::Background); m_device->ColorFill(swapchain->surface, 0, D3DCOLOR_ARGB(bg.alpha(), bg.red(),bg.green(),bg.blue())); return swapchain;}void QD3DSurfaceManager::cleanupPaintDevice(QObject *object){ QWidget *w = static_cast<QWidget *>(object); releasePaintDevice(w);}int QD3DStateManager::m_mask_channels[4][4] = {{1,0,0,0},{0,1,0,0},{0,0,1,0},{0,0,0,1}};QD3DDrawHelper::QD3DDrawHelper(QDirect3DPaintEnginePrivate *pe) : m_pe(pe), m_d3dvbuff(0), m_maskSurface(0), m_depthStencilSurface(0), m_locked(false), m_mask(0), m_startindex(0), m_index(0), m_vbuff(0), m_clearmask(true), m_isLine(false), m_firstPoint(true){ resetMask();#ifdef QT_DEBUG_VERTEXBUFFER_ACCESS memset(accesscontrol, 0, QT_VERTEX_BUF_SIZE * sizeof(VertexBufferAccess));#endif // create vertex buffer afterReset();}QD3DDrawHelper::~QD3DDrawHelper(){ if (m_maskSurface) m_maskSurface->Release(); if (m_mask) m_mask->Release(); if (m_depthStencilSurface) m_depthStencilSurface->Release(); if (m_d3dvbuff) m_d3dvbuff->Release();}inline void QD3DDrawHelper::lockVertexBuffer(){ if (!m_locked) { DWORD lockflags = D3DLOCK_NOOVERWRITE; if (m_startindex >= QT_VERTEX_RESET_LIMIT) { m_startindex = 0; m_index = 0;#ifdef QT_DEBUG_VERTEXBUFFER_ACCESS for (int i=0; i<QT_VERTEX_BUF_SIZE; ++i) { if (accesscontrol[i] != (WRITE|READ) && accesscontrol[i] != CLEAR) qDebug() << "Vertex Buffer: Access Error"; } memset(accesscontrol, 0, QT_VERTEX_BUF_SIZE * sizeof(VertexBufferAccess));#endif lockflags = D3DLOCK_DISCARD; } if (FAILED(m_d3dvbuff->Lock(0, 0, (void**)&m_vbuff, lockflags))) { qWarning() << "QDirect3DPaintEngine: unable to lock vertex buffer."; } m_locked = true; }}inline void QD3DDrawHelper::unlockVertexBuffer(){ if (m_locked) { if (FAILED(m_d3dvbuff->Unlock())) { qWarning() << "QDirect3DPaintEngine: unable to unlock vertex buffer."; } m_locked = false; }}void QD3DDrawHelper::setClipPath(const QPainterPath &path, QD3DBatchItem **item){ lockVertexBuffer(); m_item = *item; m_item->m_maskpos.x = m_item->m_maskpos.y = 0; m_item->m_maskpos.channel = 3; m_item->m_info |= QD3DBatchItem::BI_CLIP; bool winding = (path.fillRule() == Qt::WindingFill); if (winding) m_item->m_info |= QD3DBatchItem::BI_WINDING; if (!path.isEmpty()) { m_item->m_info |= QD3DBatchItem::BI_MASK; m_item->m_info &= ~QD3DBatchItem::BI_AA; m_color = 0; QRectF brect = pathToVertexArrays(path); queueRect(brect, m_item, 0); } *item = m_item;}void QD3DDrawHelper::queueAntialiasedMask(const QPolygonF &poly, QD3DBatchItem **item, const QRectF &brect){ lockVertexBuffer(); m_item = *item; m_item->m_info |= QD3DBatchItem::BI_MASK; setWinding(m_item->m_info & QD3DBatchItem::BI_WINDING); int xoffset = m_item->m_maskpos.x; int yoffset = m_item->m_maskpos.y; int x = brect.left(); int y = brect.top(); m_item->m_xoffset = (xoffset - x) + 1; m_item->m_yoffset = (yoffset - y) + 1; m_boundingRect = brect; tessellate(poly); *item = m_item;}QRectF QD3DDrawHelper::queueAliasedMask(const QPainterPath &path, QD3DBatchItem **item, D3DCOLOR color){ lockVertexBuffer(); m_color = color; m_item = *item; m_item->m_info |= QD3DBatchItem::BI_MASK; bool winding = (path.fillRule() == Qt::WindingFill); if (winding) m_item->m_info |= QD3DBatchItem::BI_WINDING; QRectF result = pathToVertexArrays(path); *item = m_item; return result;}// used for drawing aliased transformed rects directly// don't use for antialiased or masked drawingvoid QD3DDrawHelper::queueRect(const QRectF &rect, QD3DBatchItem *item, D3DCOLOR color, const QPolygonF &trect){ lockVertexBuffer(); qreal zval = (item->m_info & QD3DBatchItem::BI_CLIP) ? 0.0f : 0.5f; item->m_info |= QD3DBatchItem::BI_BRECT; // if the item does not have a mask, the offset is different if (!(item->m_info & QD3DBatchItem::BI_MASK)) { item->m_offset = m_index; item->m_count = (item->m_info & QD3DBatchItem::BI_AA) ? 0 : -2; } qreal x1 = rect.left(); qreal y1 = rect.top(); qreal x2 = rect.right(); qreal y2 = rect.bottom(); QPointF tc = trect.at(0); vertex v1 = { {x1, y1, zval} , color, tc.x(), tc.y(), 0.f, 0.f, 0.f , 0.f , 0.f, 0.f }; tc = trect.at(1); vertex v2 = { {x2, y1, zval} , color, tc.x(), tc.y(), 0.f, 0.f, 0.f , 0.f , 0.f, 0.f}; tc = trect.at(2); vertex v3 = { {x2, y2, zval} , color, tc.x(), tc.y(), 0.f, 0.f, 0.f , 0.f , 0.f, 0.f};; tc = trect.at(3); vertex v4 = { {x1, y2, zval} , color, tc.x(), tc.y(), 0.f, 0.f, 0.f , 0.f , 0.f, 0.f};#ifdef QT_DEBUG_VERTEXBUFFER_ACCESS for (int i=m_index; i<(m_index + 4); ++i) { if ((m_index + 4) > QT_VERTEX_BUF_SIZE) qDebug() << "Vertex Buffer: Buffer overflow"; if (accesscontrol[i] != CLEAR) qDebug() << "Vertex Buffer: Access Error"; accesscontrol[i] |= WRITE; }#endif m_vbuff[m_index++] = v1; m_vbuff[m_index++] = v2; m_vbuff[m_index++] = v3; m_vbuff[m_index++] = v4; m_startindex = m_index;}QD3DMaskPosition QD3DDrawHelper::allocateMaskPosition(const QRectF &brect, bool *breakbatch){ int w = brect.width(); int h = brect.height(); w += 3; h += 3; if (w > m_width) w = m_width; if (h > m_height) h = m_height; *breakbatch = false; if ((m_height - m_mask_offsetY2) >= h && (m_width - m_mask_position.x) >= w) { m_mask_position.y = m_mask_offsetY2; } else if ((m_width - m_mask_offsetX2) >= w) { m_mask_position.y = QD3D_MASK_MARGIN; m_mask_position.x = m_mask_offsetX2; } else if (m_mask_position.channel < 3) { ++m_mask_position.channel; m_mask_position.x = m_mask_position.y = QD3D_MASK_MARGIN; m_mask_offsetX2 = m_mask_offsetY2 = QD3D_MASK_MARGIN; } else { resetMask(); *breakbatch = true; } int newoffset = m_mask_position.x + w; if (m_mask_offsetX2 < newoffset) m_mask_offsetX2 = newoffset; m_mask_offsetY2 = (m_mask_position.y + h); return m_mask_position;}void QD3DDrawHelper::queueRect(const QRectF &rect, QD3DBatchItem *item, D3DCOLOR color){ lockVertexBuffer(); QRectF brect; item->m_info |= QD3DBatchItem::BI_BRECT; qreal zval = (item->m_info & QD3DBatchItem::BI_CLIP) ? 0.0f : 0.5f; if (item->m_info & QD3DBatchItem::BI_AA) { int xoffset = item->m_maskpos.x; int yoffset = item->m_maskpos.y; int x = rect.left(); int y = rect.top(); brect = QRectF(x, y, rect.width() + 1, rect.height() + 1); item->m_xoffset = (xoffset - x) + 1; item->m_yoffset = (yoffset - y) + 1; // if the item does not have a mask, the offset is different if (!(item->m_info & QD3DBatchItem::BI_MASK)) { item->m_offset = m_index; item->m_count = 0; } } else { brect = rect; if (!(item->m_info & QD3DBatchItem::BI_MASK)) { item->m_offset = m_index; item->m_count = -2; } } qreal left = brect.left(); qreal right = brect.right(); qreal top = brect.top(); qreal bottom = brect.bottom(); vertex v1 = { {left, bottom, zval}, color, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f}; vertex v2 = { {left, top, zval}, color, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f}; vertex v3 = { {right, top, zval}, color, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f}; vertex v4 = { {right, bottom, zval}, color, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f};#ifdef QT_DEBUG_VERTEXBUFFER_ACCESS for (int i=m_index; i<(m_index + 4); ++i) { if ((m_index + 4) > QT_VERTEX_BUF_SIZE) qDebug() << "Vertex Buffer: Buffer overflow"; if (accesscontrol[i] != CLEAR) qDebug() << "Vertex Buffer: Access Error"; accesscontrol[i] |= WRITE; }#endif m_vbuff[m_index++] = v1; m_vbuff[m_index++] = v2; m_vbuff[m_index++] = v3; m_vbuff[m_index++] = v4; m_startindex = m_index;}void QD3DDrawHelper::queueAntialiasedLines(const QPainterPath &path, QD3DBatchItem **item, const QRectF &brect){ lockVertexBuffer(); m_item = *item; m_item->m_info |= QD3DBatchItem::BI_MASK; setWinding(m_item->m_info & QD3DBatchItem::BI_WINDING); int xoffset = m_item->m_maskpos.x; int yoffset = m_item->m_maskpos.y; int x = brect.left(); int y = brect.top(); m_item->m_xoffset = (xoffset - x) + 1; m_item->m_yoffset = (yoffset - y) + 1; m_boundingRect = brect; m_xoffset = (x - xoffset) + 0.5f; m_yoffset = (y - yoffset) + 0.5f; QPointF last; for (int i = 0; i < path.elementCount(); ++i) { QPainterPath::Element element = path.elementAt(i); //Q_ASSERT(!element.isCurveTo()); if (element.isLineTo()) QTessellator::tessellateRect(last, element, m_item->m_width); last = element; } m_item->m_offset = m_startindex; m_item->m_count = ( m_index - m_startindex ) / 3; m_startindex = m_index; *item = m_item;}void QD3DDrawHelper:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -