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 #ifndef QRHIGLES2_P_H
38 #define QRHIGLES2_P_H
39 
40 //
41 //  W A R N I N G
42 //  -------------
43 //
44 // This file is not part of the Qt API.  It exists purely as an
45 // implementation detail.  This header file may change from version to
46 // version without notice, or even be removed.
47 //
48 // We mean it.
49 //
50 
51 #include "qrhigles2_p.h"
52 #include "qrhi_p_p.h"
53 #include "qshaderdescription_p.h"
54 #include <qopengl.h>
55 #include <QSurface>
56 
57 QT_BEGIN_NAMESPACE
58 
59 class QOpenGLExtensions;
60 
61 struct QGles2Buffer : public QRhiBuffer
62 {
63     QGles2Buffer(QRhiImplementation *rhi, Type type, UsageFlags usage, int size);
64     ~QGles2Buffer();
65     void release() override;
66     bool build() override;
67     QRhiBuffer::NativeBuffer nativeBuffer() override;
68 
69     GLuint buffer = 0;
70     GLenum targetForDataOps;
71     QByteArray ubuf;
72     enum Access {
73         AccessNone,
74         AccessVertex,
75         AccessIndex,
76         AccessUniform,
77         AccessStorageRead,
78         AccessStorageWrite,
79         AccessStorageReadWrite,
80         AccessUpdate
81     };
82     struct UsageState {
83         Access access;
84     };
85     UsageState usageState;
86     friend class QRhiGles2;
87 };
88 
89 struct QGles2RenderBuffer : public QRhiRenderBuffer
90 {
91     QGles2RenderBuffer(QRhiImplementation *rhi, Type type, const QSize &pixelSize,
92                        int sampleCount, QRhiRenderBuffer::Flags flags);
93     ~QGles2RenderBuffer();
94     void release() override;
95     bool build() override;
96     QRhiTexture::Format backingFormat() const override;
97 
98     GLuint renderbuffer = 0;
99     GLuint stencilRenderbuffer = 0; // when packed depth-stencil not supported
100     int samples;
101     friend class QRhiGles2;
102 };
103 
104 struct QGles2SamplerData
105 {
106     GLenum glminfilter = 0;
107     GLenum glmagfilter = 0;
108     GLenum glwraps = 0;
109     GLenum glwrapt = 0;
110     GLenum glwrapr = 0;
111     GLenum gltexcomparefunc = 0;
112 };
113 
114 inline bool operator==(const QGles2SamplerData &a, const QGles2SamplerData &b)
115 {
116     return a.glminfilter == b.glminfilter
117             && a.glmagfilter == b.glmagfilter
118             && a.glwraps == b.glwraps
119             && a.glwrapt == b.glwrapt
120             && a.glwrapr == b.glwrapr
121             && a.gltexcomparefunc == b.gltexcomparefunc;
122 }
123 
124 inline bool operator!=(const QGles2SamplerData &a, const QGles2SamplerData &b)
125 {
126     return !(a == b);
127 }
128 
129 struct QGles2Texture : public QRhiTexture
130 {
131     QGles2Texture(QRhiImplementation *rhi, Format format, const QSize &pixelSize,
132                   int sampleCount, Flags flags);
133     ~QGles2Texture();
134     void release() override;
135     bool build() override;
136     bool buildFrom(NativeTexture src) override;
137     NativeTexture nativeTexture() override;
138 
139     bool prepareBuild(QSize *adjustedSize = nullptr);
140 
141     GLuint texture = 0;
142     bool owns = true;
143     GLenum target;
144     GLenum glintformat;
145     GLenum glsizedintformat;
146     GLenum glformat;
147     GLenum gltype;
148     QGles2SamplerData samplerState;
149     bool specified = false;
150     int mipLevelCount = 0;
151 
152     enum Access {
153         AccessNone,
154         AccessSample,
155         AccessFramebuffer,
156         AccessStorageRead,
157         AccessStorageWrite,
158         AccessStorageReadWrite,
159         AccessUpdate,
160         AccessRead
161     };
162     struct UsageState {
163         Access access;
164     };
165     UsageState usageState;
166 
167     uint generation = 0;
168     friend class QRhiGles2;
169 };
170 
171 struct QGles2Sampler : public QRhiSampler
172 {
173     QGles2Sampler(QRhiImplementation *rhi, Filter magFilter, Filter minFilter, Filter mipmapMode,
174                   AddressMode u, AddressMode v, AddressMode w);
175     ~QGles2Sampler();
176     void release() override;
177     bool build() override;
178 
179     QGles2SamplerData d;
180     uint generation = 0;
181     friend class QRhiGles2;
182 };
183 
184 struct QGles2RenderPassDescriptor : public QRhiRenderPassDescriptor
185 {
186     QGles2RenderPassDescriptor(QRhiImplementation *rhi);
187     ~QGles2RenderPassDescriptor();
188     void release() override;
189     bool isCompatible(const QRhiRenderPassDescriptor *other) const override;
190 };
191 
192 struct QGles2RenderTargetData
193 {
QGles2RenderTargetDataQGles2RenderTargetData194     QGles2RenderTargetData(QRhiImplementation *) { }
195 
196     QGles2RenderPassDescriptor *rp = nullptr;
197     QSize pixelSize;
198     float dpr = 1;
199     int sampleCount = 1;
200     int colorAttCount = 0;
201     int dsAttCount = 0;
202     bool srgbUpdateAndBlend = false;
203 };
204 
205 struct QGles2ReferenceRenderTarget : public QRhiRenderTarget
206 {
207     QGles2ReferenceRenderTarget(QRhiImplementation *rhi);
208     ~QGles2ReferenceRenderTarget();
209     void release() override;
210 
211     QSize pixelSize() const override;
212     float devicePixelRatio() const override;
213     int sampleCount() const override;
214 
215     QGles2RenderTargetData d;
216 };
217 
218 struct QGles2TextureRenderTarget : public QRhiTextureRenderTarget
219 {
220     QGles2TextureRenderTarget(QRhiImplementation *rhi, const QRhiTextureRenderTargetDescription &desc, Flags flags);
221     ~QGles2TextureRenderTarget();
222     void release() override;
223 
224     QSize pixelSize() const override;
225     float devicePixelRatio() const override;
226     int sampleCount() const override;
227 
228     QRhiRenderPassDescriptor *newCompatibleRenderPassDescriptor() override;
229     bool build() override;
230 
231     QGles2RenderTargetData d;
232     GLuint framebuffer = 0;
233     friend class QRhiGles2;
234 };
235 
236 struct QGles2ShaderResourceBindings : public QRhiShaderResourceBindings
237 {
238     QGles2ShaderResourceBindings(QRhiImplementation *rhi);
239     ~QGles2ShaderResourceBindings();
240     void release() override;
241     bool build() override;
242 
243     uint generation = 0;
244     friend class QRhiGles2;
245 };
246 
247 struct QGles2UniformDescription
248 {
249     QShaderDescription::VariableType type;
250     int glslLocation;
251     int binding;
252     uint offset;
253     int size;
254     int arrayDim;
255 };
256 
257 Q_DECLARE_TYPEINFO(QGles2UniformDescription, Q_MOVABLE_TYPE);
258 
259 struct QGles2SamplerDescription
260 {
261     int glslLocation;
262     int binding;
263 };
264 
265 Q_DECLARE_TYPEINFO(QGles2SamplerDescription, Q_MOVABLE_TYPE);
266 
267 struct QGles2GraphicsPipeline : public QRhiGraphicsPipeline
268 {
269     QGles2GraphicsPipeline(QRhiImplementation *rhi);
270     ~QGles2GraphicsPipeline();
271     void release() override;
272     bool build() override;
273 
274     GLuint program = 0;
275     GLenum drawMode = GL_TRIANGLES;
276     QVector<QGles2UniformDescription> uniforms;
277     QVector<QGles2SamplerDescription> samplers;
278     uint generation = 0;
279     friend class QRhiGles2;
280 };
281 
282 struct QGles2ComputePipeline : public QRhiComputePipeline
283 {
284     QGles2ComputePipeline(QRhiImplementation *rhi);
285     ~QGles2ComputePipeline();
286     void release() override;
287     bool build() override;
288 
289     GLuint program = 0;
290     QVector<QGles2UniformDescription> uniforms;
291     QVector<QGles2SamplerDescription> samplers;
292     uint generation = 0;
293     friend class QRhiGles2;
294 };
295 
296 struct QGles2CommandBuffer : public QRhiCommandBuffer
297 {
298     QGles2CommandBuffer(QRhiImplementation *rhi);
299     ~QGles2CommandBuffer();
300     void release() override;
301 
302     struct Command {
303         enum Cmd {
304             BeginFrame,
305             EndFrame,
306             ResetFrame,
307             Viewport,
308             Scissor,
309             BlendConstants,
310             StencilRef,
311             BindVertexBuffer,
312             BindIndexBuffer,
313             Draw,
314             DrawIndexed,
315             BindGraphicsPipeline,
316             BindShaderResources,
317             BindFramebuffer,
318             Clear,
319             BufferSubData,
320             GetBufferSubData,
321             CopyTex,
322             ReadPixels,
323             SubImage,
324             CompressedImage,
325             CompressedSubImage,
326             BlitFromRenderbuffer,
327             GenMip,
328             BindComputePipeline,
329             Dispatch,
330             BarriersForPass,
331             Barrier
332         };
333         Cmd cmd;
334 
335         static const int MAX_UBUF_BINDINGS = 32; // should be more than enough
336 
337         // QRhi*/QGles2* references should be kept at minimum (so no
338         // QRhiTexture/Buffer/etc. pointers).
339         union {
340             struct {
341                 float x, y, w, h;
342                 float d0, d1;
343             } viewport;
344             struct {
345                 int x, y, w, h;
346             } scissor;
347             struct {
348                 float r, g, b, a;
349             } blendConstants;
350             struct {
351                 quint32 ref;
352                 QRhiGraphicsPipeline *ps;
353             } stencilRef;
354             struct {
355                 QRhiGraphicsPipeline *ps;
356                 GLuint buffer;
357                 quint32 offset;
358                 int binding;
359             } bindVertexBuffer;
360             struct {
361                 GLuint buffer;
362                 quint32 offset;
363                 GLenum type;
364             } bindIndexBuffer;
365             struct {
366                 QRhiGraphicsPipeline *ps;
367                 quint32 vertexCount;
368                 quint32 firstVertex;
369                 quint32 instanceCount;
370                 quint32 baseInstance;
371             } draw;
372             struct {
373                 QRhiGraphicsPipeline *ps;
374                 quint32 indexCount;
375                 quint32 firstIndex;
376                 quint32 instanceCount;
377                 quint32 baseInstance;
378                 qint32 baseVertex;
379             } drawIndexed;
380             struct {
381                 QRhiGraphicsPipeline *ps;
382             } bindGraphicsPipeline;
383             struct {
384                 QRhiGraphicsPipeline *maybeGraphicsPs;
385                 QRhiComputePipeline *maybeComputePs;
386                 QRhiShaderResourceBindings *srb;
387                 int dynamicOffsetCount;
388                 uint dynamicOffsetPairs[MAX_UBUF_BINDINGS * 2]; // binding, offsetInConstants
389             } bindShaderResources;
390             struct {
391                 GLbitfield mask;
392                 float c[4];
393                 float d;
394                 quint32 s;
395             } clear;
396             struct {
397                 GLuint fbo;
398                 bool srgb;
399                 int colorAttCount;
400             } bindFramebuffer;
401             struct {
402                 GLenum target;
403                 GLuint buffer;
404                 int offset;
405                 int size;
406                 const void *data; // must come from retainData()
407             } bufferSubData;
408             struct {
409                 QRhiBufferReadbackResult *result;
410                 GLenum target;
411                 GLuint buffer;
412                 int offset;
413                 int size;
414             } getBufferSubData;
415             struct {
416                 GLenum srcFaceTarget;
417                 GLuint srcTexture;
418                 int srcLevel;
419                 int srcX;
420                 int srcY;
421                 GLenum dstTarget;
422                 GLuint dstTexture;
423                 GLenum dstFaceTarget;
424                 int dstLevel;
425                 int dstX;
426                 int dstY;
427                 int w;
428                 int h;
429             } copyTex;
430             struct {
431                 QRhiReadbackResult *result;
432                 GLuint texture;
433                 int w;
434                 int h;
435                 QRhiTexture::Format format;
436                 GLenum readTarget;
437                 int level;
438             } readPixels;
439             struct {
440                 GLenum target;
441                 GLuint texture;
442                 GLenum faceTarget;
443                 int level;
444                 int dx;
445                 int dy;
446                 int w;
447                 int h;
448                 GLenum glformat;
449                 GLenum gltype;
450                 int rowStartAlign;
451                 const void *data; // must come from retainImage()
452             } subImage;
453             struct {
454                 GLenum target;
455                 GLuint texture;
456                 GLenum faceTarget;
457                 int level;
458                 GLenum glintformat;
459                 int w;
460                 int h;
461                 int size;
462                 const void *data; // must come from retainData()
463             } compressedImage;
464             struct {
465                 GLenum target;
466                 GLuint texture;
467                 GLenum faceTarget;
468                 int level;
469                 int dx;
470                 int dy;
471                 int w;
472                 int h;
473                 GLenum glintformat;
474                 int size;
475                 const void *data; // must come from retainData()
476             } compressedSubImage;
477             struct {
478                 GLuint renderbuffer;
479                 int w;
480                 int h;
481                 GLenum target;
482                 GLuint texture;
483                 int dstLevel;
484             } blitFromRb;
485             struct {
486                 GLenum target;
487                 GLuint texture;
488             } genMip;
489             struct {
490                 QRhiComputePipeline *ps;
491             } bindComputePipeline;
492             struct {
493                 GLuint x;
494                 GLuint y;
495                 GLuint z;
496             } dispatch;
497             struct {
498                 int trackerIndex;
499             } barriersForPass;
500             struct {
501                 GLbitfield barriers;
502             } barrier;
503         } args;
504     };
505 
506     enum PassType {
507         NoPass,
508         RenderPass,
509         ComputePass
510     };
511 
512     QVector<Command> commands;
513     QVarLengthArray<QRhiPassResourceTracker, 8> passResTrackers;
514     int currentPassResTrackerIndex;
515 
516     PassType recordingPass;
517     QRhiRenderTarget *currentTarget;
518     QRhiGraphicsPipeline *currentGraphicsPipeline;
519     QRhiComputePipeline *currentComputePipeline;
520     uint currentPipelineGeneration;
521     QRhiShaderResourceBindings *currentGraphicsSrb;
522     QRhiShaderResourceBindings *currentComputeSrb;
523     uint currentSrbGeneration;
524 
525     struct GraphicsPassState {
526         bool valid = false;
527         bool scissor;
528         bool cullFace;
529         GLenum cullMode;
530         GLenum frontFace;
531         bool blendEnabled;
532         struct ColorMask { bool r, g, b, a; } colorMask;
533         struct Blend {
534             GLenum srcColor;
535             GLenum dstColor;
536             GLenum srcAlpha;
537             GLenum dstAlpha;
538             GLenum opColor;
539             GLenum opAlpha;
540         } blend;
541         bool depthTest;
542         bool depthWrite;
543         GLenum depthFunc;
544         bool stencilTest;
545         GLuint stencilReadMask;
546         GLuint stencilWriteMask;
547         struct StencilFace {
548             GLenum func;
549             GLenum failOp;
550             GLenum zfailOp;
551             GLenum zpassOp;
552         } stencil[2]; // front, back
553         bool polyOffsetFill;
554         float polyOffsetFactor;
555         float polyOffsetUnits;
556         float lineWidth;
resetQGles2CommandBuffer::GraphicsPassState557         void reset() { valid = false; }
558         struct {
559             // not part of QRhiGraphicsPipeline but used by setGraphicsPipeline()
560             GLint stencilRef = 0;
561         } dynamic;
562     } graphicsPassState;
563 
564     struct ComputePassState {
565         enum Access {
566             Read = 0x01,
567             Write = 0x02
568         };
569         QHash<QRhiResource *, QPair<int, bool> > writtenResources;
resetQGles2CommandBuffer::ComputePassState570         void reset() {
571             writtenResources.clear();
572         }
573     } computePassState;
574 
575     QVector<QByteArray> dataRetainPool;
576     QVector<QImage> imageRetainPool;
577 
578     // relies heavily on implicit sharing (no copies of the actual data will be made)
retainDataQGles2CommandBuffer579     const void *retainData(const QByteArray &data) {
580         dataRetainPool.append(data);
581         return dataRetainPool.constLast().constData();
582     }
retainImageQGles2CommandBuffer583     const void *retainImage(const QImage &image) {
584         imageRetainPool.append(image);
585         return imageRetainPool.constLast().constBits();
586     }
resetCommandsQGles2CommandBuffer587     void resetCommands() {
588         commands.clear();
589         dataRetainPool.clear();
590         imageRetainPool.clear();
591 
592         passResTrackers.clear();
593         currentPassResTrackerIndex = -1;
594     }
resetStateQGles2CommandBuffer595     void resetState() {
596         recordingPass = NoPass;
597         currentTarget = nullptr;
598         resetCommands();
599         resetCachedState();
600     }
resetCachedStateQGles2CommandBuffer601     void resetCachedState() {
602         currentGraphicsPipeline = nullptr;
603         currentComputePipeline = nullptr;
604         currentPipelineGeneration = 0;
605         currentGraphicsSrb = nullptr;
606         currentComputeSrb = nullptr;
607         currentSrbGeneration = 0;
608         graphicsPassState.reset();
609         computePassState.reset();
610     }
611 };
612 
613 Q_DECLARE_TYPEINFO(QGles2CommandBuffer::Command, Q_MOVABLE_TYPE);
614 
615 inline bool operator==(const QGles2CommandBuffer::GraphicsPassState::StencilFace &a,
616                        const QGles2CommandBuffer::GraphicsPassState::StencilFace &b)
617 {
618     return a.func == b.func
619             && a.failOp == b.failOp
620             && a.zfailOp == b.zfailOp
621             && a.zpassOp == b.zpassOp;
622 }
623 
624 inline bool operator!=(const QGles2CommandBuffer::GraphicsPassState::StencilFace &a,
625                        const QGles2CommandBuffer::GraphicsPassState::StencilFace &b)
626 {
627     return !(a == b);
628 }
629 
630 inline bool operator==(const QGles2CommandBuffer::GraphicsPassState::ColorMask &a,
631                        const QGles2CommandBuffer::GraphicsPassState::ColorMask &b)
632 {
633     return a.r == b.r && a.g == b.g && a.b == b.b && a.a == b.a;
634 }
635 
636 inline bool operator!=(const QGles2CommandBuffer::GraphicsPassState::ColorMask &a,
637                        const QGles2CommandBuffer::GraphicsPassState::ColorMask &b)
638 {
639     return !(a == b);
640 }
641 
642 inline bool operator==(const QGles2CommandBuffer::GraphicsPassState::Blend &a,
643                        const QGles2CommandBuffer::GraphicsPassState::Blend &b)
644 {
645     return a.srcColor == b.srcColor
646             && a.dstColor == b.dstColor
647             && a.srcAlpha == b.srcAlpha
648             && a.dstAlpha == b.dstAlpha
649             && a.opColor == b.opColor
650             && a.opAlpha == b.opAlpha;
651 }
652 
653 inline bool operator!=(const QGles2CommandBuffer::GraphicsPassState::Blend &a,
654                        const QGles2CommandBuffer::GraphicsPassState::Blend &b)
655 {
656     return !(a == b);
657 }
658 
659 struct QGles2SwapChain : public QRhiSwapChain
660 {
661     QGles2SwapChain(QRhiImplementation *rhi);
662     ~QGles2SwapChain();
663     void release() override;
664 
665     QRhiCommandBuffer *currentFrameCommandBuffer() override;
666     QRhiRenderTarget *currentFrameRenderTarget() override;
667 
668     QSize surfacePixelSize() override;
669 
670     QRhiRenderPassDescriptor *newCompatibleRenderPassDescriptor() override;
671     bool buildOrResize() override;
672 
673     QSurface *surface = nullptr;
674     QSize pixelSize;
675     QGles2ReferenceRenderTarget rt;
676     QGles2CommandBuffer cb;
677     int frameCount = 0;
678 };
679 
680 class QRhiGles2 : public QRhiImplementation
681 {
682 public:
683     QRhiGles2(QRhiGles2InitParams *params, QRhiGles2NativeHandles *importDevice = nullptr);
684 
685     bool create(QRhi::Flags flags) override;
686     void destroy() override;
687 
688     QRhiGraphicsPipeline *createGraphicsPipeline() override;
689     QRhiComputePipeline *createComputePipeline() override;
690     QRhiShaderResourceBindings *createShaderResourceBindings() override;
691     QRhiBuffer *createBuffer(QRhiBuffer::Type type,
692                              QRhiBuffer::UsageFlags usage,
693                              int size) override;
694     QRhiRenderBuffer *createRenderBuffer(QRhiRenderBuffer::Type type,
695                                          const QSize &pixelSize,
696                                          int sampleCount,
697                                          QRhiRenderBuffer::Flags flags) override;
698     QRhiTexture *createTexture(QRhiTexture::Format format,
699                                const QSize &pixelSize,
700                                int sampleCount,
701                                QRhiTexture::Flags flags) override;
702     QRhiSampler *createSampler(QRhiSampler::Filter magFilter,
703                                QRhiSampler::Filter minFilter,
704                                QRhiSampler::Filter mipmapMode,
705                                QRhiSampler:: AddressMode u,
706                                QRhiSampler::AddressMode v,
707                                QRhiSampler::AddressMode w) override;
708 
709     QRhiTextureRenderTarget *createTextureRenderTarget(const QRhiTextureRenderTargetDescription &desc,
710                                                        QRhiTextureRenderTarget::Flags flags) override;
711 
712     QRhiSwapChain *createSwapChain() override;
713     QRhi::FrameOpResult beginFrame(QRhiSwapChain *swapChain, QRhi::BeginFrameFlags flags) override;
714     QRhi::FrameOpResult endFrame(QRhiSwapChain *swapChain, QRhi::EndFrameFlags flags) override;
715     QRhi::FrameOpResult beginOffscreenFrame(QRhiCommandBuffer **cb, QRhi::BeginFrameFlags flags) override;
716     QRhi::FrameOpResult endOffscreenFrame(QRhi::EndFrameFlags flags) override;
717     QRhi::FrameOpResult finish() override;
718 
719     void resourceUpdate(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates) override;
720 
721     void beginPass(QRhiCommandBuffer *cb,
722                    QRhiRenderTarget *rt,
723                    const QColor &colorClearValue,
724                    const QRhiDepthStencilClearValue &depthStencilClearValue,
725                    QRhiResourceUpdateBatch *resourceUpdates) override;
726     void endPass(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates) override;
727 
728     void setGraphicsPipeline(QRhiCommandBuffer *cb,
729                              QRhiGraphicsPipeline *ps) override;
730 
731     void setShaderResources(QRhiCommandBuffer *cb,
732                             QRhiShaderResourceBindings *srb,
733                             int dynamicOffsetCount,
734                             const QRhiCommandBuffer::DynamicOffset *dynamicOffsets) override;
735 
736     void setVertexInput(QRhiCommandBuffer *cb,
737                         int startBinding, int bindingCount, const QRhiCommandBuffer::VertexInput *bindings,
738                         QRhiBuffer *indexBuf, quint32 indexOffset,
739                         QRhiCommandBuffer::IndexFormat indexFormat) override;
740 
741     void setViewport(QRhiCommandBuffer *cb, const QRhiViewport &viewport) override;
742     void setScissor(QRhiCommandBuffer *cb, const QRhiScissor &scissor) override;
743     void setBlendConstants(QRhiCommandBuffer *cb, const QColor &c) override;
744     void setStencilRef(QRhiCommandBuffer *cb, quint32 refValue) override;
745 
746     void draw(QRhiCommandBuffer *cb, quint32 vertexCount,
747               quint32 instanceCount, quint32 firstVertex, quint32 firstInstance) override;
748 
749     void drawIndexed(QRhiCommandBuffer *cb, quint32 indexCount,
750                      quint32 instanceCount, quint32 firstIndex,
751                      qint32 vertexOffset, quint32 firstInstance) override;
752 
753     void debugMarkBegin(QRhiCommandBuffer *cb, const QByteArray &name) override;
754     void debugMarkEnd(QRhiCommandBuffer *cb) override;
755     void debugMarkMsg(QRhiCommandBuffer *cb, const QByteArray &msg) override;
756 
757     void beginComputePass(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates) override;
758     void endComputePass(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates) override;
759     void setComputePipeline(QRhiCommandBuffer *cb, QRhiComputePipeline *ps) override;
760     void dispatch(QRhiCommandBuffer *cb, int x, int y, int z) override;
761 
762     const QRhiNativeHandles *nativeHandles(QRhiCommandBuffer *cb) override;
763     void beginExternal(QRhiCommandBuffer *cb) override;
764     void endExternal(QRhiCommandBuffer *cb) override;
765 
766     QVector<int> supportedSampleCounts() const override;
767     int ubufAlignment() const override;
768     bool isYUpInFramebuffer() const override;
769     bool isYUpInNDC() const override;
770     bool isClipDepthZeroToOne() const override;
771     QMatrix4x4 clipSpaceCorrMatrix() const override;
772     bool isTextureFormatSupported(QRhiTexture::Format format, QRhiTexture::Flags flags) const override;
773     bool isFeatureSupported(QRhi::Feature feature) const override;
774     int resourceLimit(QRhi::ResourceLimit limit) const override;
775     const QRhiNativeHandles *nativeHandles() override;
776     void sendVMemStatsToProfiler() override;
777     bool makeThreadLocalNativeContextCurrent() override;
778     void releaseCachedResources() override;
779     bool isDeviceLost() const override;
780 
781     bool ensureContext(QSurface *surface = nullptr) const;
782     void executeDeferredReleases();
783     void trackedBufferBarrier(QGles2CommandBuffer *cbD, QGles2Buffer *bufD, QGles2Buffer::Access access);
784     void trackedImageBarrier(QGles2CommandBuffer *cbD, QGles2Texture *texD, QGles2Texture::Access access);
785     void enqueueSubresUpload(QGles2Texture *texD, QGles2CommandBuffer *cbD,
786                              int layer, int level, const QRhiTextureSubresourceUploadDescription &subresDesc);
787     void enqueueResourceUpdates(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates);
788     void trackedRegisterBuffer(QRhiPassResourceTracker *passResTracker,
789                                QGles2Buffer *bufD,
790                                QRhiPassResourceTracker::BufferAccess access,
791                                QRhiPassResourceTracker::BufferStage stage);
792     void trackedRegisterTexture(QRhiPassResourceTracker *passResTracker,
793                                 QGles2Texture *texD,
794                                 QRhiPassResourceTracker::TextureAccess access,
795                                 QRhiPassResourceTracker::TextureStage stage);
796     void executeCommandBuffer(QRhiCommandBuffer *cb);
797     void executeBindGraphicsPipeline(QGles2CommandBuffer *cbD, QGles2GraphicsPipeline *psD);
798     void bindShaderResources(QRhiGraphicsPipeline *maybeGraphicsPs, QRhiComputePipeline *maybeComputePs,
799                              QRhiShaderResourceBindings *srb,
800                              const uint *dynOfsPairs, int dynOfsCount);
801     QGles2RenderTargetData *enqueueBindFramebuffer(QRhiRenderTarget *rt, QGles2CommandBuffer *cbD,
802                                                    bool *wantsColorClear = nullptr, bool *wantsDsClear = nullptr);
803     void enqueueBarriersForPass(QGles2CommandBuffer *cbD);
804     int effectiveSampleCount(int sampleCount) const;
805     QByteArray shaderSource(const QRhiShaderStage &shaderStage, int *glslVersion);
806     bool compileShader(GLuint program, const QRhiShaderStage &shaderStage, int *glslVersion);
807     bool linkProgram(GLuint program);
808     void registerUniformIfActive(const QShaderDescription::BlockVariable &var,
809                                  const QByteArray &namePrefix,
810                                  int binding,
811                                  int baseOffset,
812                                  GLuint program,
813                                  QVector<QGles2UniformDescription> *dst);
814     void gatherUniforms(GLuint program,
815                         const QShaderDescription::UniformBlock &ub,
816                         QVector<QGles2UniformDescription> *dst);
817     void gatherSamplers(GLuint program, const QShaderDescription::InOutVariable &v,
818                         QVector<QGles2SamplerDescription> *dst);
819     bool isProgramBinaryDiskCacheEnabled() const;
820 
821     enum DiskCacheResult {
822         DiskCacheHit,
823         DiskCacheMiss,
824         DiskCacheError
825     };
826     DiskCacheResult tryLoadFromDiskCache(const QRhiShaderStage *stages, int stageCount,
827                                          GLuint program, QByteArray *cacheKey);
828     void trySaveToDiskCache(GLuint program, const QByteArray &cacheKey);
829 
830     QOpenGLContext *ctx = nullptr;
831     bool importedContext = false;
832     QSurfaceFormat requestedFormat;
833     QSurface *fallbackSurface = nullptr;
834     QWindow *maybeWindow = nullptr;
835     mutable bool needsMakeCurrent = false;
836     QOpenGLExtensions *f = nullptr;
837     uint vao = 0;
838     struct Caps {
CapsCaps839         Caps()
840             : ctxMajor(2),
841               ctxMinor(0),
842               maxTextureSize(2048),
843               maxDrawBuffers(4),
844               msaaRenderBuffer(false),
845               npotTextureFull(true),
846               gles(false),
847               fixedIndexPrimitiveRestart(false),
848               bgraExternalFormat(false),
849               bgraInternalFormat(false),
850               r8Format(false),
851               r16Format(false),
852               floatFormats(false),
853               depthTexture(false),
854               packedDepthStencil(false),
855               needsDepthStencilCombinedAttach(false),
856               srgbCapableDefaultFramebuffer(false),
857               coreProfile(false),
858               uniformBuffers(false),
859               elementIndexUint(false),
860               depth24(false),
861               rgba8Format(false),
862               instancing(false),
863               baseVertex(false),
864               compute(false),
865               textureCompareMode(false),
866               properMapBuffer(false),
867               nonBaseLevelFramebufferTexture(false),
868               texelFetch(false)
869         { }
870         int ctxMajor;
871         int ctxMinor;
872         int maxTextureSize;
873         int maxDrawBuffers;
874         int maxSamples;
875         // Multisample fb and blit are supported (GLES 3.0 or OpenGL 3.x). Not
876         // the same as multisample textures!
877         uint msaaRenderBuffer : 1;
878         uint npotTextureFull : 1;
879         uint gles : 1;
880         uint fixedIndexPrimitiveRestart : 1;
881         uint bgraExternalFormat : 1;
882         uint bgraInternalFormat : 1;
883         uint r8Format : 1;
884         uint r16Format : 1;
885         uint floatFormats : 1;
886         uint depthTexture : 1;
887         uint packedDepthStencil : 1;
888         uint needsDepthStencilCombinedAttach : 1;
889         uint srgbCapableDefaultFramebuffer : 1;
890         uint coreProfile : 1;
891         uint uniformBuffers : 1;
892         uint elementIndexUint : 1;
893         uint depth24 : 1;
894         uint rgba8Format : 1;
895         uint instancing : 1;
896         uint baseVertex : 1;
897         uint compute : 1;
898         uint textureCompareMode : 1;
899         uint properMapBuffer : 1;
900         uint nonBaseLevelFramebufferTexture : 1;
901         uint texelFetch : 1;
902     } caps;
903     QGles2SwapChain *currentSwapChain = nullptr;
904     QVector<GLint> supportedCompressedFormats;
905     mutable QVector<int> supportedSampleCountList;
906     QRhiGles2NativeHandles nativeHandlesStruct;
907     mutable bool contextLost = false;
908 
909     struct DeferredReleaseEntry {
910         enum Type {
911             Buffer,
912             Pipeline,
913             Texture,
914             RenderBuffer,
915             TextureRenderTarget
916         };
917         Type type;
918         union {
919             struct {
920                 GLuint buffer;
921             } buffer;
922             struct {
923                 GLuint program;
924             } pipeline;
925             struct {
926                 GLuint texture;
927             } texture;
928             struct {
929                 GLuint renderbuffer;
930                 GLuint renderbuffer2;
931             } renderbuffer;
932             struct {
933                 GLuint framebuffer;
934             } textureRenderTarget;
935         };
936     };
937     QVector<DeferredReleaseEntry> releaseQueue;
938 
939     struct OffscreenFrame {
OffscreenFrameOffscreenFrame940         OffscreenFrame(QRhiImplementation *rhi) : cbWrapper(rhi) { }
941         bool active = false;
942         QGles2CommandBuffer cbWrapper;
943     } ofr;
944 
945     QHash<QRhiShaderStage, uint> m_shaderCache;
946 };
947 
948 Q_DECLARE_TYPEINFO(QRhiGles2::DeferredReleaseEntry, Q_MOVABLE_TYPE);
949 
950 QT_END_NAMESPACE
951 
952 #endif
953