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