1/****************************************************************************
2**
3** Copyright (C) 2019 The Qt Company Ltd.
4** Contact: http://www.qt.io/licensing/
5**
6** This file is part of the Qt Gui module
7**
8** $QT_BEGIN_LICENSE:LGPL3$
9** Commercial License Usage
10** Licensees holding valid commercial Qt licenses may use this file in
11** accordance with the commercial license agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and The Qt Company. For licensing terms
14** and conditions see http://www.qt.io/terms-conditions. For further
15** information use the contact form at http://www.qt.io/contact-us.
16**
17** GNU Lesser General Public License Usage
18** Alternatively, this file may be used under the terms of the GNU Lesser
19** General Public License version 3 as published by the Free Software
20** Foundation and appearing in the file LICENSE.LGPLv3 included in the
21** packaging of this file. Please review the following information to
22** ensure the GNU Lesser General Public License version 3 requirements
23** will be met: https://www.gnu.org/licenses/lgpl.html.
24**
25** GNU General Public License Usage
26** Alternatively, this file may be used under the terms of the GNU
27** General Public License version 2.0 or later as published by the Free
28** Software Foundation and appearing in the file LICENSE.GPL included in
29** the packaging of this file. Please review the following information to
30** ensure the GNU General Public License version 2.0 requirements will be
31** met: http://www.gnu.org/licenses/gpl-2.0.html.
32**
33** $QT_END_LICENSE$
34**
35****************************************************************************/
36
37#include "qrhinull_p_p.h"
38#include <qmath.h>
39#include <QPainter>
40
41QT_BEGIN_NAMESPACE
42
43/*!
44 \class QRhiNullInitParams
45 \internal
46 \inmodule QtGui
47 \brief Null backend specific initialization parameters.
48
49 A Null QRhi needs no special parameters for initialization.
50
51 \badcode
52 QRhiNullInitParams params;
53 rhi = QRhi::create(QRhi::Null, &params);
54 \endcode
55
56 The Null backend does not issue any graphics calls and creates no
57 resources. All QRhi operations will succeed as normal so applications can
58 still be run, albeit potentially at an unthrottled speed, depending on
59 their frame rendering strategy. The backend reports resources to
60 QRhiProfiler as usual.
61 */
62
63/*!
64 \class QRhiNullNativeHandles
65 \internal
66 \inmodule QtGui
67 \brief Empty.
68 */
69
70QRhiNull::QRhiNull(QRhiNullInitParams *params)
71 : offscreenCommandBuffer(this)
72{
73 Q_UNUSED(params);
74}
75
76bool QRhiNull::create(QRhi::Flags flags)
77{
78 Q_UNUSED(flags);
79 return true;
80}
81
82void QRhiNull::destroy()
83{
84}
85
86QVector<int> QRhiNull::supportedSampleCounts() const
87{
88 return { 1 };
89}
90
91QRhiSwapChain *QRhiNull::createSwapChain()
92{
93 return new QNullSwapChain(this);
94}
95
96QRhiBuffer *QRhiNull::createBuffer(QRhiBuffer::Type type, QRhiBuffer::UsageFlags usage, int size)
97{
98 return new QNullBuffer(this, type, usage, size);
99}
100
101int QRhiNull::ubufAlignment() const
102{
103 return 256;
104}
105
106bool QRhiNull::isYUpInFramebuffer() const
107{
108 return false;
109}
110
111bool QRhiNull::isYUpInNDC() const
112{
113 return true;
114}
115
116bool QRhiNull::isClipDepthZeroToOne() const
117{
118 return true;
119}
120
121QMatrix4x4 QRhiNull::clipSpaceCorrMatrix() const
122{
123 return QMatrix4x4(); // identity
124}
125
126bool QRhiNull::isTextureFormatSupported(QRhiTexture::Format format, QRhiTexture::Flags flags) const
127{
128 Q_UNUSED(format);
129 Q_UNUSED(flags);
130 return true;
131}
132
133bool QRhiNull::isFeatureSupported(QRhi::Feature feature) const
134{
135 Q_UNUSED(feature);
136 return true;
137}
138
139int QRhiNull::resourceLimit(QRhi::ResourceLimit limit) const
140{
141 switch (limit) {
142 case QRhi::TextureSizeMin:
143 return 1;
144 case QRhi::TextureSizeMax:
145 return 16384;
146 case QRhi::MaxColorAttachments:
147 return 8;
148 case QRhi::FramesInFlight:
149 return 1;
150 case QRhi::MaxAsyncReadbackFrames:
151 return 1;
152 default:
153 Q_UNREACHABLE();
154 return 0;
155 }
156}
157
158const QRhiNativeHandles *QRhiNull::nativeHandles()
159{
160 return &nativeHandlesStruct;
161}
162
163void QRhiNull::sendVMemStatsToProfiler()
164{
165 // nothing to do here
166}
167
168bool QRhiNull::makeThreadLocalNativeContextCurrent()
169{
170 // not applicable
171 return false;
172}
173
174void QRhiNull::releaseCachedResources()
175{
176 // nothing to do here
177}
178
179bool QRhiNull::isDeviceLost() const
180{
181 return false;
182}
183
184QRhiRenderBuffer *QRhiNull::createRenderBuffer(QRhiRenderBuffer::Type type, const QSize &pixelSize,
185 int sampleCount, QRhiRenderBuffer::Flags flags)
186{
187 return new QNullRenderBuffer(this, type, pixelSize, sampleCount, flags);
188}
189
190QRhiTexture *QRhiNull::createTexture(QRhiTexture::Format format, const QSize &pixelSize,
191 int sampleCount, QRhiTexture::Flags flags)
192{
193 return new QNullTexture(this, format, pixelSize, sampleCount, flags);
194}
195
196QRhiSampler *QRhiNull::createSampler(QRhiSampler::Filter magFilter, QRhiSampler::Filter minFilter,
197 QRhiSampler::Filter mipmapMode,
198 QRhiSampler::AddressMode u, QRhiSampler::AddressMode v, QRhiSampler::AddressMode w)
199{
200 return new QNullSampler(this, magFilter, minFilter, mipmapMode, u, v, w);
201}
202
203QRhiTextureRenderTarget *QRhiNull::createTextureRenderTarget(const QRhiTextureRenderTargetDescription &desc,
204 QRhiTextureRenderTarget::Flags flags)
205{
206 return new QNullTextureRenderTarget(this, desc, flags);
207}
208
209QRhiGraphicsPipeline *QRhiNull::createGraphicsPipeline()
210{
211 return new QNullGraphicsPipeline(this);
212}
213
214QRhiComputePipeline *QRhiNull::createComputePipeline()
215{
216 return new QNullComputePipeline(this);
217}
218
219QRhiShaderResourceBindings *QRhiNull::createShaderResourceBindings()
220{
221 return new QNullShaderResourceBindings(this);
222}
223
224void QRhiNull::setGraphicsPipeline(QRhiCommandBuffer *cb, QRhiGraphicsPipeline *ps)
225{
226 Q_UNUSED(cb);
227 Q_UNUSED(ps);
228}
229
230void QRhiNull::setShaderResources(QRhiCommandBuffer *cb, QRhiShaderResourceBindings *srb,
231 int dynamicOffsetCount,
232 const QRhiCommandBuffer::DynamicOffset *dynamicOffsets)
233{
234 Q_UNUSED(cb);
235 Q_UNUSED(srb);
236 Q_UNUSED(dynamicOffsetCount);
237 Q_UNUSED(dynamicOffsets);
238}
239
240void QRhiNull::setVertexInput(QRhiCommandBuffer *cb,
241 int startBinding, int bindingCount, const QRhiCommandBuffer::VertexInput *bindings,
242 QRhiBuffer *indexBuf, quint32 indexOffset, QRhiCommandBuffer::IndexFormat indexFormat)
243{
244 Q_UNUSED(cb);
245 Q_UNUSED(startBinding);
246 Q_UNUSED(bindingCount);
247 Q_UNUSED(bindings);
248 Q_UNUSED(indexBuf);
249 Q_UNUSED(indexOffset);
250 Q_UNUSED(indexFormat);
251}
252
253void QRhiNull::setViewport(QRhiCommandBuffer *cb, const QRhiViewport &viewport)
254{
255 Q_UNUSED(cb);
256 Q_UNUSED(viewport);
257}
258
259void QRhiNull::setScissor(QRhiCommandBuffer *cb, const QRhiScissor &scissor)
260{
261 Q_UNUSED(cb);
262 Q_UNUSED(scissor);
263}
264
265void QRhiNull::setBlendConstants(QRhiCommandBuffer *cb, const QColor &c)
266{
267 Q_UNUSED(cb);
268 Q_UNUSED(c);
269}
270
271void QRhiNull::setStencilRef(QRhiCommandBuffer *cb, quint32 refValue)
272{
273 Q_UNUSED(cb);
274 Q_UNUSED(refValue);
275}
276
277void QRhiNull::draw(QRhiCommandBuffer *cb, quint32 vertexCount,
278 quint32 instanceCount, quint32 firstVertex, quint32 firstInstance)
279{
280 Q_UNUSED(cb);
281 Q_UNUSED(vertexCount);
282 Q_UNUSED(instanceCount);
283 Q_UNUSED(firstVertex);
284 Q_UNUSED(firstInstance);
285}
286
287void QRhiNull::drawIndexed(QRhiCommandBuffer *cb, quint32 indexCount,
288 quint32 instanceCount, quint32 firstIndex, qint32 vertexOffset, quint32 firstInstance)
289{
290 Q_UNUSED(cb);
291 Q_UNUSED(indexCount);
292 Q_UNUSED(instanceCount);
293 Q_UNUSED(firstIndex);
294 Q_UNUSED(vertexOffset);
295 Q_UNUSED(firstInstance);
296}
297
298void QRhiNull::debugMarkBegin(QRhiCommandBuffer *cb, const QByteArray &name)
299{
300 Q_UNUSED(cb);
301 Q_UNUSED(name);
302}
303
304void QRhiNull::debugMarkEnd(QRhiCommandBuffer *cb)
305{
306 Q_UNUSED(cb);
307}
308
309void QRhiNull::debugMarkMsg(QRhiCommandBuffer *cb, const QByteArray &msg)
310{
311 Q_UNUSED(cb);
312 Q_UNUSED(msg);
313}
314
315void QRhiNull::setComputePipeline(QRhiCommandBuffer *cb, QRhiComputePipeline *ps)
316{
317 Q_UNUSED(cb);
318 Q_UNUSED(ps);
319}
320
321void QRhiNull::dispatch(QRhiCommandBuffer *cb, int x, int y, int z)
322{
323 Q_UNUSED(cb);
324 Q_UNUSED(x);
325 Q_UNUSED(y);
326 Q_UNUSED(z);
327}
328
329const QRhiNativeHandles *QRhiNull::nativeHandles(QRhiCommandBuffer *cb)
330{
331 Q_UNUSED(cb);
332 return nullptr;
333}
334
335void QRhiNull::beginExternal(QRhiCommandBuffer *cb)
336{
337 Q_UNUSED(cb);
338}
339
340void QRhiNull::endExternal(QRhiCommandBuffer *cb)
341{
342 Q_UNUSED(cb);
343}
344
345QRhi::FrameOpResult QRhiNull::beginFrame(QRhiSwapChain *swapChain, QRhi::BeginFrameFlags flags)
346{
347 Q_UNUSED(flags);
348 currentSwapChain = swapChain;
349 QRhiProfilerPrivate *rhiP = profilerPrivateOrNull();
350 QRHI_PROF_F(beginSwapChainFrame(swapChain));
351 return QRhi::FrameOpSuccess;
352}
353
354QRhi::FrameOpResult QRhiNull::endFrame(QRhiSwapChain *swapChain, QRhi::EndFrameFlags flags)
355{
356 Q_UNUSED(flags);
357 QNullSwapChain *swapChainD = QRHI_RES(QNullSwapChain, swapChain);
358 QRhiProfilerPrivate *rhiP = profilerPrivateOrNull();
359 QRHI_PROF_F(endSwapChainFrame(swapChain, swapChainD->frameCount + 1));
360 QRHI_PROF_F(swapChainFrameGpuTime(swapChain, 0.000666f));
361 swapChainD->frameCount += 1;
362 currentSwapChain = nullptr;
363 return QRhi::FrameOpSuccess;
364}
365
366QRhi::FrameOpResult QRhiNull::beginOffscreenFrame(QRhiCommandBuffer **cb, QRhi::BeginFrameFlags flags)
367{
368 Q_UNUSED(flags);
369 *cb = &offscreenCommandBuffer;
370 return QRhi::FrameOpSuccess;
371}
372
373QRhi::FrameOpResult QRhiNull::endOffscreenFrame(QRhi::EndFrameFlags flags)
374{
375 Q_UNUSED(flags);
376 return QRhi::FrameOpSuccess;
377}
378
379QRhi::FrameOpResult QRhiNull::finish()
380{
381 return QRhi::FrameOpSuccess;
382}
383
384void QRhiNull::simulateTextureUpload(const QRhiResourceUpdateBatchPrivate::TextureOp &u)
385{
386 QNullTexture *texD = QRHI_RES(QNullTexture, u.dst);
387 for (int layer = 0; layer < QRhi::MAX_LAYERS; ++layer) {
388 for (int level = 0; level < QRhi::MAX_LEVELS; ++level) {
389 for (const QRhiTextureSubresourceUploadDescription &subresDesc : qAsConst(t: u.subresDesc[layer][level])) {
390 if (!subresDesc.image().isNull()) {
391 const QImage src = subresDesc.image();
392 QPainter painter(&texD->image[layer][level]);
393 const QSize srcSize = subresDesc.sourceSize().isEmpty()
394 ? src.size() : subresDesc.sourceSize();
395 painter.setCompositionMode(QPainter::CompositionMode_Source);
396 painter.drawImage(p: subresDesc.destinationTopLeft(), image: src,
397 sr: QRect(subresDesc.sourceTopLeft(), srcSize));
398 } else if (!subresDesc.data().isEmpty()) {
399 const QSize subresSize = q->sizeForMipLevel(mipLevel: level, baseLevelSize: texD->pixelSize());
400 int w = subresSize.width();
401 int h = subresSize.height();
402 if (!subresDesc.sourceSize().isEmpty()) {
403 w = subresDesc.sourceSize().width();
404 h = subresDesc.sourceSize().height();
405 }
406 // sourceTopLeft is not supported on this path as per QRhi docs
407 const char *src = subresDesc.data().constData();
408 const int srcBpl = w * 4;
409 const QPoint dstOffset = subresDesc.destinationTopLeft();
410 uchar *dst = texD->image[layer][level].bits();
411 const int dstBpl = texD->image[layer][level].bytesPerLine();
412 for (int y = 0; y < h; ++y) {
413 memcpy(dest: dst + dstOffset.x() * 4 + (y + dstOffset.y()) * dstBpl,
414 src: src + y * srcBpl,
415 n: size_t(srcBpl));
416 }
417 }
418 }
419 }
420 }
421}
422
423void QRhiNull::simulateTextureCopy(const QRhiResourceUpdateBatchPrivate::TextureOp &u)
424{
425 QNullTexture *srcD = QRHI_RES(QNullTexture, u.src);
426 QNullTexture *dstD = QRHI_RES(QNullTexture, u.dst);
427 const QImage &srcImage(srcD->image[u.desc.sourceLayer()][u.desc.sourceLevel()]);
428 QImage &dstImage(dstD->image[u.desc.destinationLayer()][u.desc.destinationLevel()]);
429 const QPoint dstPos = u.desc.destinationTopLeft();
430 const QSize size = u.desc.pixelSize().isEmpty() ? srcD->pixelSize() : u.desc.pixelSize();
431 const QPoint srcPos = u.desc.sourceTopLeft();
432
433 QPainter painter(&dstImage);
434 painter.setCompositionMode(QPainter::CompositionMode_Source);
435 painter.drawImage(targetRect: QRect(dstPos, size), image: srcImage, sourceRect: QRect(srcPos, size));
436}
437
438void QRhiNull::simulateTextureGenMips(const QRhiResourceUpdateBatchPrivate::TextureOp &u)
439{
440 QNullTexture *texD = QRHI_RES(QNullTexture, u.dst);
441 const QSize baseSize = texD->pixelSize();
442 const int levelCount = q->mipLevelsForSize(size: baseSize);
443 for (int level = 1; level < levelCount; ++level)
444 texD->image[0][level] = texD->image[0][0].scaled(s: q->sizeForMipLevel(mipLevel: level, baseLevelSize: baseSize));
445}
446
447void QRhiNull::resourceUpdate(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates)
448{
449 Q_UNUSED(cb);
450 QRhiResourceUpdateBatchPrivate *ud = QRhiResourceUpdateBatchPrivate::get(b: resourceUpdates);
451 for (const QRhiResourceUpdateBatchPrivate::BufferOp &u : ud->bufferOps) {
452 if (u.type == QRhiResourceUpdateBatchPrivate::BufferOp::DynamicUpdate
453 || u.type == QRhiResourceUpdateBatchPrivate::BufferOp::StaticUpload)
454 {
455 QNullBuffer *bufD = QRHI_RES(QNullBuffer, u.buf);
456 memcpy(dest: bufD->data.data() + u.offset, src: u.data.constData(), n: size_t(u.data.size()));
457 } else if (u.type == QRhiResourceUpdateBatchPrivate::BufferOp::Read) {
458 QRhiBufferReadbackResult *result = u.result;
459 result->data.resize(size: u.readSize);
460 QNullBuffer *bufD = QRHI_RES(QNullBuffer, u.buf);
461 memcpy(dest: result->data.data(), src: bufD->data.constData() + u.offset, n: size_t(u.readSize));
462 if (result->completed)
463 result->completed();
464 }
465 }
466 for (const QRhiResourceUpdateBatchPrivate::TextureOp &u : ud->textureOps) {
467 if (u.type == QRhiResourceUpdateBatchPrivate::TextureOp::Upload) {
468 if (u.dst->format() == QRhiTexture::RGBA8)
469 simulateTextureUpload(u);
470 } else if (u.type == QRhiResourceUpdateBatchPrivate::TextureOp::Copy) {
471 if (u.src->format() == QRhiTexture::RGBA8 && u.dst->format() == QRhiTexture::RGBA8)
472 simulateTextureCopy(u);
473 } else if (u.type == QRhiResourceUpdateBatchPrivate::TextureOp::Read) {
474 QRhiReadbackResult *result = u.result;
475 QNullTexture *texD = QRHI_RES(QNullTexture, u.rb.texture());
476 if (texD) {
477 result->format = texD->format();
478 result->pixelSize = q->sizeForMipLevel(mipLevel: u.rb.level(), baseLevelSize: texD->pixelSize());
479 } else {
480 Q_ASSERT(currentSwapChain);
481 result->format = QRhiTexture::RGBA8;
482 result->pixelSize = currentSwapChain->currentPixelSize();
483 }
484 quint32 bytesPerLine = 0;
485 quint32 byteSize = 0;
486 textureFormatInfo(format: result->format, size: result->pixelSize, bpl: &bytesPerLine, byteSize: &byteSize);
487 if (texD && texD->format() == QRhiTexture::RGBA8) {
488 result->data.resize(size: int(byteSize));
489 const QImage &src(texD->image[u.rb.layer()][u.rb.level()]);
490 char *dst = result->data.data();
491 for (int y = 0, h = src.height(); y < h; ++y) {
492 memcpy(dest: dst, src: src.constScanLine(y), n: bytesPerLine);
493 dst += bytesPerLine;
494 }
495 } else {
496 result->data.fill(c: 0, size: int(byteSize));
497 }
498 if (result->completed)
499 result->completed();
500 } else if (u.type == QRhiResourceUpdateBatchPrivate::TextureOp::GenMips) {
501 if (u.dst->format() == QRhiTexture::RGBA8)
502 simulateTextureGenMips(u);
503 }
504 }
505 ud->free();
506}
507
508void QRhiNull::beginPass(QRhiCommandBuffer *cb,
509 QRhiRenderTarget *rt,
510 const QColor &colorClearValue,
511 const QRhiDepthStencilClearValue &depthStencilClearValue,
512 QRhiResourceUpdateBatch *resourceUpdates)
513{
514 Q_UNUSED(rt);
515 Q_UNUSED(colorClearValue);
516 Q_UNUSED(depthStencilClearValue);
517 if (resourceUpdates)
518 resourceUpdate(cb, resourceUpdates);
519}
520
521void QRhiNull::endPass(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates)
522{
523 if (resourceUpdates)
524 resourceUpdate(cb, resourceUpdates);
525}
526
527void QRhiNull::beginComputePass(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates)
528{
529 if (resourceUpdates)
530 resourceUpdate(cb, resourceUpdates);
531}
532
533void QRhiNull::endComputePass(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates)
534{
535 if (resourceUpdates)
536 resourceUpdate(cb, resourceUpdates);
537}
538
539QNullBuffer::QNullBuffer(QRhiImplementation *rhi, Type type, UsageFlags usage, int size)
540 : QRhiBuffer(rhi, type, usage, size)
541{
542}
543
544QNullBuffer::~QNullBuffer()
545{
546 release();
547}
548
549void QNullBuffer::release()
550{
551 data.clear();
552
553 QRHI_PROF;
554 QRHI_PROF_F(releaseBuffer(this));
555}
556
557bool QNullBuffer::build()
558{
559 data.fill(c: '\0', size: m_size);
560
561 QRHI_PROF;
562 QRHI_PROF_F(newBuffer(this, uint(m_size), 1, 0));
563 return true;
564}
565
566QNullRenderBuffer::QNullRenderBuffer(QRhiImplementation *rhi, Type type, const QSize &pixelSize,
567 int sampleCount, QRhiRenderBuffer::Flags flags)
568 : QRhiRenderBuffer(rhi, type, pixelSize, sampleCount, flags)
569{
570}
571
572QNullRenderBuffer::~QNullRenderBuffer()
573{
574 release();
575}
576
577void QNullRenderBuffer::release()
578{
579 QRHI_PROF;
580 QRHI_PROF_F(releaseRenderBuffer(this));
581}
582
583bool QNullRenderBuffer::build()
584{
585 QRHI_PROF;
586 QRHI_PROF_F(newRenderBuffer(this, false, false, 1));
587 return true;
588}
589
590QRhiTexture::Format QNullRenderBuffer::backingFormat() const
591{
592 return m_type == Color ? QRhiTexture::RGBA8 : QRhiTexture::UnknownFormat;
593}
594
595QNullTexture::QNullTexture(QRhiImplementation *rhi, Format format, const QSize &pixelSize,
596 int sampleCount, Flags flags)
597 : QRhiTexture(rhi, format, pixelSize, sampleCount, flags)
598{
599}
600
601QNullTexture::~QNullTexture()
602{
603 release();
604}
605
606void QNullTexture::release()
607{
608 QRHI_PROF;
609 QRHI_PROF_F(releaseTexture(this));
610}
611
612bool QNullTexture::build()
613{
614 QRHI_RES_RHI(QRhiNull);
615 const bool isCube = m_flags.testFlag(flag: CubeMap);
616 const bool hasMipMaps = m_flags.testFlag(flag: MipMapped);
617 QSize size = m_pixelSize.isEmpty() ? QSize(1, 1) : m_pixelSize;
618 const int mipLevelCount = hasMipMaps ? rhiD->q->mipLevelsForSize(size) : 1;
619 const int layerCount = isCube ? 6 : 1;
620
621 if (m_format == RGBA8) {
622 for (int layer = 0; layer < layerCount; ++layer) {
623 for (int level = 0; level < mipLevelCount; ++level) {
624 image[layer][level] = QImage(rhiD->q->sizeForMipLevel(mipLevel: level, baseLevelSize: size),
625 QImage::Format_RGBA8888_Premultiplied);
626 image[layer][level].fill(color: Qt::yellow);
627 }
628 }
629 }
630
631 QRHI_PROF;
632 QRHI_PROF_F(newTexture(this, true, mipLevelCount, layerCount, 1));
633 return true;
634}
635
636bool QNullTexture::buildFrom(QRhiTexture::NativeTexture src)
637{
638 Q_UNUSED(src)
639 QRHI_RES_RHI(QRhiNull);
640 const bool isCube = m_flags.testFlag(flag: CubeMap);
641 const bool hasMipMaps = m_flags.testFlag(flag: MipMapped);
642 QSize size = m_pixelSize.isEmpty() ? QSize(1, 1) : m_pixelSize;
643 const int mipLevelCount = hasMipMaps ? rhiD->q->mipLevelsForSize(size) : 1;
644 QRHI_PROF;
645 QRHI_PROF_F(newTexture(this, false, mipLevelCount, isCube ? 6 : 1, 1));
646 return true;
647}
648
649QNullSampler::QNullSampler(QRhiImplementation *rhi, Filter magFilter, Filter minFilter, Filter mipmapMode,
650 AddressMode u, AddressMode v, AddressMode w)
651 : QRhiSampler(rhi, magFilter, minFilter, mipmapMode, u, v, w)
652{
653}
654
655QNullSampler::~QNullSampler()
656{
657 release();
658}
659
660void QNullSampler::release()
661{
662}
663
664bool QNullSampler::build()
665{
666 return true;
667}
668
669QNullRenderPassDescriptor::QNullRenderPassDescriptor(QRhiImplementation *rhi)
670 : QRhiRenderPassDescriptor(rhi)
671{
672}
673
674QNullRenderPassDescriptor::~QNullRenderPassDescriptor()
675{
676 release();
677}
678
679void QNullRenderPassDescriptor::release()
680{
681}
682
683bool QNullRenderPassDescriptor::isCompatible(const QRhiRenderPassDescriptor *other) const
684{
685 Q_UNUSED(other);
686 return true;
687}
688
689QNullReferenceRenderTarget::QNullReferenceRenderTarget(QRhiImplementation *rhi)
690 : QRhiRenderTarget(rhi),
691 d(rhi)
692{
693}
694
695QNullReferenceRenderTarget::~QNullReferenceRenderTarget()
696{
697 release();
698}
699
700void QNullReferenceRenderTarget::release()
701{
702}
703
704QSize QNullReferenceRenderTarget::pixelSize() const
705{
706 return d.pixelSize;
707}
708
709float QNullReferenceRenderTarget::devicePixelRatio() const
710{
711 return d.dpr;
712}
713
714int QNullReferenceRenderTarget::sampleCount() const
715{
716 return 1;
717}
718
719QNullTextureRenderTarget::QNullTextureRenderTarget(QRhiImplementation *rhi,
720 const QRhiTextureRenderTargetDescription &desc,
721 Flags flags)
722 : QRhiTextureRenderTarget(rhi, desc, flags),
723 d(rhi)
724{
725}
726
727QNullTextureRenderTarget::~QNullTextureRenderTarget()
728{
729 release();
730}
731
732void QNullTextureRenderTarget::release()
733{
734}
735
736QRhiRenderPassDescriptor *QNullTextureRenderTarget::newCompatibleRenderPassDescriptor()
737{
738 return new QNullRenderPassDescriptor(m_rhi);
739}
740
741bool QNullTextureRenderTarget::build()
742{
743 d.rp = QRHI_RES(QNullRenderPassDescriptor, m_renderPassDesc);
744 if (m_desc.cbeginColorAttachments() != m_desc.cendColorAttachments()) {
745 QRhiTexture *tex = m_desc.cbeginColorAttachments()->texture();
746 QRhiRenderBuffer *rb = m_desc.cbeginColorAttachments()->renderBuffer();
747 d.pixelSize = tex ? tex->pixelSize() : rb->pixelSize();
748 } else if (m_desc.depthStencilBuffer()) {
749 d.pixelSize = m_desc.depthStencilBuffer()->pixelSize();
750 } else if (m_desc.depthTexture()) {
751 d.pixelSize = m_desc.depthTexture()->pixelSize();
752 }
753 return true;
754}
755
756QSize QNullTextureRenderTarget::pixelSize() const
757{
758 return d.pixelSize;
759}
760
761float QNullTextureRenderTarget::devicePixelRatio() const
762{
763 return d.dpr;
764}
765
766int QNullTextureRenderTarget::sampleCount() const
767{
768 return 1;
769}
770
771QNullShaderResourceBindings::QNullShaderResourceBindings(QRhiImplementation *rhi)
772 : QRhiShaderResourceBindings(rhi)
773{
774}
775
776QNullShaderResourceBindings::~QNullShaderResourceBindings()
777{
778 release();
779}
780
781void QNullShaderResourceBindings::release()
782{
783}
784
785bool QNullShaderResourceBindings::build()
786{
787 return true;
788}
789
790QNullGraphicsPipeline::QNullGraphicsPipeline(QRhiImplementation *rhi)
791 : QRhiGraphicsPipeline(rhi)
792{
793}
794
795QNullGraphicsPipeline::~QNullGraphicsPipeline()
796{
797 release();
798}
799
800void QNullGraphicsPipeline::release()
801{
802}
803
804bool QNullGraphicsPipeline::build()
805{
806 QRHI_RES_RHI(QRhiNull);
807 if (!rhiD->sanityCheckGraphicsPipeline(ps: this))
808 return false;
809
810 return true;
811}
812
813QNullComputePipeline::QNullComputePipeline(QRhiImplementation *rhi)
814 : QRhiComputePipeline(rhi)
815{
816}
817
818QNullComputePipeline::~QNullComputePipeline()
819{
820 release();
821}
822
823void QNullComputePipeline::release()
824{
825}
826
827bool QNullComputePipeline::build()
828{
829 return true;
830}
831
832QNullCommandBuffer::QNullCommandBuffer(QRhiImplementation *rhi)
833 : QRhiCommandBuffer(rhi)
834{
835}
836
837QNullCommandBuffer::~QNullCommandBuffer()
838{
839 release();
840}
841
842void QNullCommandBuffer::release()
843{
844 // nothing to do here
845}
846
847QNullSwapChain::QNullSwapChain(QRhiImplementation *rhi)
848 : QRhiSwapChain(rhi),
849 rt(rhi),
850 cb(rhi)
851{
852}
853
854QNullSwapChain::~QNullSwapChain()
855{
856 release();
857}
858
859void QNullSwapChain::release()
860{
861 QRHI_PROF;
862 QRHI_PROF_F(releaseSwapChain(this));
863}
864
865QRhiCommandBuffer *QNullSwapChain::currentFrameCommandBuffer()
866{
867 return &cb;
868}
869
870QRhiRenderTarget *QNullSwapChain::currentFrameRenderTarget()
871{
872 return &rt;
873}
874
875QSize QNullSwapChain::surfacePixelSize()
876{
877 return QSize(1280, 720);
878}
879
880QRhiRenderPassDescriptor *QNullSwapChain::newCompatibleRenderPassDescriptor()
881{
882 return new QNullRenderPassDescriptor(m_rhi);
883}
884
885bool QNullSwapChain::buildOrResize()
886{
887 m_currentPixelSize = surfacePixelSize();
888 rt.d.rp = QRHI_RES(QNullRenderPassDescriptor, m_renderPassDesc);
889 rt.d.pixelSize = m_currentPixelSize;
890 frameCount = 0;
891 QRHI_PROF;
892 QRHI_PROF_F(resizeSwapChain(this, 1, 0, 1));
893 return true;
894}
895
896QT_END_NAMESPACE
897

source code of qtbase/src/gui/rhi/qrhinull.cpp