blob: ac7b384cb6fea9cb7c7520dc5b6451dac166d8a0 [file] [log] [blame]
/****************************************************************************
**
** Copyright (C) 2019 The Qt Company Ltd.
** Contact: http://www.qt.io/licensing/
**
** This file is part of the Qt Gui module
**
** $QT_BEGIN_LICENSE:LGPL3$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see http://www.qt.io/terms-conditions. For further
** information use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 3 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPLv3 included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 3 requirements
** will be met: https://www.gnu.org/licenses/lgpl.html.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 2.0 or later as published by the Free
** Software Foundation and appearing in the file LICENSE.GPL included in
** the packaging of this file. Please review the following information to
** ensure the GNU General Public License version 2.0 requirements will be
** met: http://www.gnu.org/licenses/gpl-2.0.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef QRHIGLES2_P_H
#define QRHIGLES2_P_H
//
// W A R N I N G
// -------------
//
// This file is not part of the Qt API. It exists purely as an
// implementation detail. This header file may change from version to
// version without notice, or even be removed.
//
// We mean it.
//
#include "qrhigles2_p.h"
#include "qrhi_p_p.h"
#include "qshaderdescription_p.h"
#include <qopengl.h>
#include <QSurface>
QT_BEGIN_NAMESPACE
class QOpenGLExtensions;
struct QGles2Buffer : public QRhiBuffer
{
QGles2Buffer(QRhiImplementation *rhi, Type type, UsageFlags usage, int size);
~QGles2Buffer();
void release() override;
bool build() override;
QRhiBuffer::NativeBuffer nativeBuffer() override;
GLuint buffer = 0;
GLenum targetForDataOps;
QByteArray ubuf;
enum Access {
AccessNone,
AccessVertex,
AccessIndex,
AccessUniform,
AccessStorageRead,
AccessStorageWrite,
AccessStorageReadWrite,
AccessUpdate
};
struct UsageState {
Access access;
};
UsageState usageState;
friend class QRhiGles2;
};
struct QGles2RenderBuffer : public QRhiRenderBuffer
{
QGles2RenderBuffer(QRhiImplementation *rhi, Type type, const QSize &pixelSize,
int sampleCount, QRhiRenderBuffer::Flags flags);
~QGles2RenderBuffer();
void release() override;
bool build() override;
QRhiTexture::Format backingFormat() const override;
GLuint renderbuffer = 0;
GLuint stencilRenderbuffer = 0; // when packed depth-stencil not supported
int samples;
friend class QRhiGles2;
};
struct QGles2SamplerData
{
GLenum glminfilter = 0;
GLenum glmagfilter = 0;
GLenum glwraps = 0;
GLenum glwrapt = 0;
GLenum glwrapr = 0;
GLenum gltexcomparefunc = 0;
};
inline bool operator==(const QGles2SamplerData &a, const QGles2SamplerData &b)
{
return a.glminfilter == b.glminfilter
&& a.glmagfilter == b.glmagfilter
&& a.glwraps == b.glwraps
&& a.glwrapt == b.glwrapt
&& a.glwrapr == b.glwrapr
&& a.gltexcomparefunc == b.gltexcomparefunc;
}
inline bool operator!=(const QGles2SamplerData &a, const QGles2SamplerData &b)
{
return !(a == b);
}
struct QGles2Texture : public QRhiTexture
{
QGles2Texture(QRhiImplementation *rhi, Format format, const QSize &pixelSize,
int sampleCount, Flags flags);
~QGles2Texture();
void release() override;
bool build() override;
bool buildFrom(NativeTexture src) override;
NativeTexture nativeTexture() override;
bool prepareBuild(QSize *adjustedSize = nullptr);
GLuint texture = 0;
bool owns = true;
GLenum target;
GLenum glintformat;
GLenum glsizedintformat;
GLenum glformat;
GLenum gltype;
QGles2SamplerData samplerState;
bool specified = false;
int mipLevelCount = 0;
enum Access {
AccessNone,
AccessSample,
AccessFramebuffer,
AccessStorageRead,
AccessStorageWrite,
AccessStorageReadWrite,
AccessUpdate,
AccessRead
};
struct UsageState {
Access access;
};
UsageState usageState;
uint generation = 0;
friend class QRhiGles2;
};
struct QGles2Sampler : public QRhiSampler
{
QGles2Sampler(QRhiImplementation *rhi, Filter magFilter, Filter minFilter, Filter mipmapMode,
AddressMode u, AddressMode v, AddressMode w);
~QGles2Sampler();
void release() override;
bool build() override;
QGles2SamplerData d;
uint generation = 0;
friend class QRhiGles2;
};
struct QGles2RenderPassDescriptor : public QRhiRenderPassDescriptor
{
QGles2RenderPassDescriptor(QRhiImplementation *rhi);
~QGles2RenderPassDescriptor();
void release() override;
bool isCompatible(const QRhiRenderPassDescriptor *other) const override;
};
struct QGles2RenderTargetData
{
QGles2RenderTargetData(QRhiImplementation *) { }
QGles2RenderPassDescriptor *rp = nullptr;
QSize pixelSize;
float dpr = 1;
int sampleCount = 1;
int colorAttCount = 0;
int dsAttCount = 0;
bool srgbUpdateAndBlend = false;
};
struct QGles2ReferenceRenderTarget : public QRhiRenderTarget
{
QGles2ReferenceRenderTarget(QRhiImplementation *rhi);
~QGles2ReferenceRenderTarget();
void release() override;
QSize pixelSize() const override;
float devicePixelRatio() const override;
int sampleCount() const override;
QGles2RenderTargetData d;
};
struct QGles2TextureRenderTarget : public QRhiTextureRenderTarget
{
QGles2TextureRenderTarget(QRhiImplementation *rhi, const QRhiTextureRenderTargetDescription &desc, Flags flags);
~QGles2TextureRenderTarget();
void release() override;
QSize pixelSize() const override;
float devicePixelRatio() const override;
int sampleCount() const override;
QRhiRenderPassDescriptor *newCompatibleRenderPassDescriptor() override;
bool build() override;
QGles2RenderTargetData d;
GLuint framebuffer = 0;
friend class QRhiGles2;
};
struct QGles2ShaderResourceBindings : public QRhiShaderResourceBindings
{
QGles2ShaderResourceBindings(QRhiImplementation *rhi);
~QGles2ShaderResourceBindings();
void release() override;
bool build() override;
uint generation = 0;
friend class QRhiGles2;
};
struct QGles2UniformDescription
{
QShaderDescription::VariableType type;
int glslLocation;
int binding;
uint offset;
int size;
int arrayDim;
};
Q_DECLARE_TYPEINFO(QGles2UniformDescription, Q_MOVABLE_TYPE);
struct QGles2SamplerDescription
{
int glslLocation;
int binding;
};
Q_DECLARE_TYPEINFO(QGles2SamplerDescription, Q_MOVABLE_TYPE);
struct QGles2GraphicsPipeline : public QRhiGraphicsPipeline
{
QGles2GraphicsPipeline(QRhiImplementation *rhi);
~QGles2GraphicsPipeline();
void release() override;
bool build() override;
GLuint program = 0;
GLenum drawMode = GL_TRIANGLES;
QVector<QGles2UniformDescription> uniforms;
QVector<QGles2SamplerDescription> samplers;
uint generation = 0;
friend class QRhiGles2;
};
struct QGles2ComputePipeline : public QRhiComputePipeline
{
QGles2ComputePipeline(QRhiImplementation *rhi);
~QGles2ComputePipeline();
void release() override;
bool build() override;
GLuint program = 0;
QVector<QGles2UniformDescription> uniforms;
QVector<QGles2SamplerDescription> samplers;
uint generation = 0;
friend class QRhiGles2;
};
struct QGles2CommandBuffer : public QRhiCommandBuffer
{
QGles2CommandBuffer(QRhiImplementation *rhi);
~QGles2CommandBuffer();
void release() override;
struct Command {
enum Cmd {
BeginFrame,
EndFrame,
ResetFrame,
Viewport,
Scissor,
BlendConstants,
StencilRef,
BindVertexBuffer,
BindIndexBuffer,
Draw,
DrawIndexed,
BindGraphicsPipeline,
BindShaderResources,
BindFramebuffer,
Clear,
BufferSubData,
GetBufferSubData,
CopyTex,
ReadPixels,
SubImage,
CompressedImage,
CompressedSubImage,
BlitFromRenderbuffer,
GenMip,
BindComputePipeline,
Dispatch,
BarriersForPass,
Barrier
};
Cmd cmd;
static const int MAX_UBUF_BINDINGS = 32; // should be more than enough
// QRhi*/QGles2* references should be kept at minimum (so no
// QRhiTexture/Buffer/etc. pointers).
union {
struct {
float x, y, w, h;
float d0, d1;
} viewport;
struct {
int x, y, w, h;
} scissor;
struct {
float r, g, b, a;
} blendConstants;
struct {
quint32 ref;
QRhiGraphicsPipeline *ps;
} stencilRef;
struct {
QRhiGraphicsPipeline *ps;
GLuint buffer;
quint32 offset;
int binding;
} bindVertexBuffer;
struct {
GLuint buffer;
quint32 offset;
GLenum type;
} bindIndexBuffer;
struct {
QRhiGraphicsPipeline *ps;
quint32 vertexCount;
quint32 firstVertex;
quint32 instanceCount;
quint32 baseInstance;
} draw;
struct {
QRhiGraphicsPipeline *ps;
quint32 indexCount;
quint32 firstIndex;
quint32 instanceCount;
quint32 baseInstance;
qint32 baseVertex;
} drawIndexed;
struct {
QRhiGraphicsPipeline *ps;
} bindGraphicsPipeline;
struct {
QRhiGraphicsPipeline *maybeGraphicsPs;
QRhiComputePipeline *maybeComputePs;
QRhiShaderResourceBindings *srb;
int dynamicOffsetCount;
uint dynamicOffsetPairs[MAX_UBUF_BINDINGS * 2]; // binding, offsetInConstants
} bindShaderResources;
struct {
GLbitfield mask;
float c[4];
float d;
quint32 s;
} clear;
struct {
GLuint fbo;
bool srgb;
int colorAttCount;
} bindFramebuffer;
struct {
GLenum target;
GLuint buffer;
int offset;
int size;
const void *data; // must come from retainData()
} bufferSubData;
struct {
QRhiBufferReadbackResult *result;
GLenum target;
GLuint buffer;
int offset;
int size;
} getBufferSubData;
struct {
GLenum srcFaceTarget;
GLuint srcTexture;
int srcLevel;
int srcX;
int srcY;
GLenum dstTarget;
GLuint dstTexture;
GLenum dstFaceTarget;
int dstLevel;
int dstX;
int dstY;
int w;
int h;
} copyTex;
struct {
QRhiReadbackResult *result;
GLuint texture;
int w;
int h;
QRhiTexture::Format format;
GLenum readTarget;
int level;
} readPixels;
struct {
GLenum target;
GLuint texture;
GLenum faceTarget;
int level;
int dx;
int dy;
int w;
int h;
GLenum glformat;
GLenum gltype;
int rowStartAlign;
const void *data; // must come from retainImage()
} subImage;
struct {
GLenum target;
GLuint texture;
GLenum faceTarget;
int level;
GLenum glintformat;
int w;
int h;
int size;
const void *data; // must come from retainData()
} compressedImage;
struct {
GLenum target;
GLuint texture;
GLenum faceTarget;
int level;
int dx;
int dy;
int w;
int h;
GLenum glintformat;
int size;
const void *data; // must come from retainData()
} compressedSubImage;
struct {
GLuint renderbuffer;
int w;
int h;
GLenum target;
GLuint texture;
int dstLevel;
} blitFromRb;
struct {
GLenum target;
GLuint texture;
} genMip;
struct {
QRhiComputePipeline *ps;
} bindComputePipeline;
struct {
GLuint x;
GLuint y;
GLuint z;
} dispatch;
struct {
int trackerIndex;
} barriersForPass;
struct {
GLbitfield barriers;
} barrier;
} args;
};
enum PassType {
NoPass,
RenderPass,
ComputePass
};
QVector<Command> commands;
QVarLengthArray<QRhiPassResourceTracker, 8> passResTrackers;
int currentPassResTrackerIndex;
PassType recordingPass;
QRhiRenderTarget *currentTarget;
QRhiGraphicsPipeline *currentGraphicsPipeline;
QRhiComputePipeline *currentComputePipeline;
uint currentPipelineGeneration;
QRhiShaderResourceBindings *currentGraphicsSrb;
QRhiShaderResourceBindings *currentComputeSrb;
uint currentSrbGeneration;
struct GraphicsPassState {
bool valid = false;
bool scissor;
bool cullFace;
GLenum cullMode;
GLenum frontFace;
bool blendEnabled;
struct ColorMask { bool r, g, b, a; } colorMask;
struct Blend {
GLenum srcColor;
GLenum dstColor;
GLenum srcAlpha;
GLenum dstAlpha;
GLenum opColor;
GLenum opAlpha;
} blend;
bool depthTest;
bool depthWrite;
GLenum depthFunc;
bool stencilTest;
GLuint stencilReadMask;
GLuint stencilWriteMask;
struct StencilFace {
GLenum func;
GLenum failOp;
GLenum zfailOp;
GLenum zpassOp;
} stencil[2]; // front, back
bool polyOffsetFill;
float polyOffsetFactor;
float polyOffsetUnits;
float lineWidth;
void reset() { valid = false; }
struct {
// not part of QRhiGraphicsPipeline but used by setGraphicsPipeline()
GLint stencilRef = 0;
} dynamic;
} graphicsPassState;
struct ComputePassState {
enum Access {
Read = 0x01,
Write = 0x02
};
QHash<QRhiResource *, QPair<int, bool> > writtenResources;
void reset() {
writtenResources.clear();
}
} computePassState;
QVector<QByteArray> dataRetainPool;
QVector<QImage> imageRetainPool;
// relies heavily on implicit sharing (no copies of the actual data will be made)
const void *retainData(const QByteArray &data) {
dataRetainPool.append(data);
return dataRetainPool.constLast().constData();
}
const void *retainImage(const QImage &image) {
imageRetainPool.append(image);
return imageRetainPool.constLast().constBits();
}
void resetCommands() {
commands.clear();
dataRetainPool.clear();
imageRetainPool.clear();
passResTrackers.clear();
currentPassResTrackerIndex = -1;
}
void resetState() {
recordingPass = NoPass;
currentTarget = nullptr;
resetCommands();
resetCachedState();
}
void resetCachedState() {
currentGraphicsPipeline = nullptr;
currentComputePipeline = nullptr;
currentPipelineGeneration = 0;
currentGraphicsSrb = nullptr;
currentComputeSrb = nullptr;
currentSrbGeneration = 0;
graphicsPassState.reset();
computePassState.reset();
}
};
Q_DECLARE_TYPEINFO(QGles2CommandBuffer::Command, Q_MOVABLE_TYPE);
inline bool operator==(const QGles2CommandBuffer::GraphicsPassState::StencilFace &a,
const QGles2CommandBuffer::GraphicsPassState::StencilFace &b)
{
return a.func == b.func
&& a.failOp == b.failOp
&& a.zfailOp == b.zfailOp
&& a.zpassOp == b.zpassOp;
}
inline bool operator!=(const QGles2CommandBuffer::GraphicsPassState::StencilFace &a,
const QGles2CommandBuffer::GraphicsPassState::StencilFace &b)
{
return !(a == b);
}
inline bool operator==(const QGles2CommandBuffer::GraphicsPassState::ColorMask &a,
const QGles2CommandBuffer::GraphicsPassState::ColorMask &b)
{
return a.r == b.r && a.g == b.g && a.b == b.b && a.a == b.a;
}
inline bool operator!=(const QGles2CommandBuffer::GraphicsPassState::ColorMask &a,
const QGles2CommandBuffer::GraphicsPassState::ColorMask &b)
{
return !(a == b);
}
inline bool operator==(const QGles2CommandBuffer::GraphicsPassState::Blend &a,
const QGles2CommandBuffer::GraphicsPassState::Blend &b)
{
return a.srcColor == b.srcColor
&& a.dstColor == b.dstColor
&& a.srcAlpha == b.srcAlpha
&& a.dstAlpha == b.dstAlpha
&& a.opColor == b.opColor
&& a.opAlpha == b.opAlpha;
}
inline bool operator!=(const QGles2CommandBuffer::GraphicsPassState::Blend &a,
const QGles2CommandBuffer::GraphicsPassState::Blend &b)
{
return !(a == b);
}
struct QGles2SwapChain : public QRhiSwapChain
{
QGles2SwapChain(QRhiImplementation *rhi);
~QGles2SwapChain();
void release() override;
QRhiCommandBuffer *currentFrameCommandBuffer() override;
QRhiRenderTarget *currentFrameRenderTarget() override;
QSize surfacePixelSize() override;
QRhiRenderPassDescriptor *newCompatibleRenderPassDescriptor() override;
bool buildOrResize() override;
QSurface *surface = nullptr;
QSize pixelSize;
QGles2ReferenceRenderTarget rt;
QGles2CommandBuffer cb;
int frameCount = 0;
};
class QRhiGles2 : public QRhiImplementation
{
public:
QRhiGles2(QRhiGles2InitParams *params, QRhiGles2NativeHandles *importDevice = nullptr);
bool create(QRhi::Flags flags) override;
void destroy() override;
QRhiGraphicsPipeline *createGraphicsPipeline() override;
QRhiComputePipeline *createComputePipeline() override;
QRhiShaderResourceBindings *createShaderResourceBindings() override;
QRhiBuffer *createBuffer(QRhiBuffer::Type type,
QRhiBuffer::UsageFlags usage,
int size) override;
QRhiRenderBuffer *createRenderBuffer(QRhiRenderBuffer::Type type,
const QSize &pixelSize,
int sampleCount,
QRhiRenderBuffer::Flags flags) override;
QRhiTexture *createTexture(QRhiTexture::Format format,
const QSize &pixelSize,
int sampleCount,
QRhiTexture::Flags flags) override;
QRhiSampler *createSampler(QRhiSampler::Filter magFilter,
QRhiSampler::Filter minFilter,
QRhiSampler::Filter mipmapMode,
QRhiSampler:: AddressMode u,
QRhiSampler::AddressMode v,
QRhiSampler::AddressMode w) override;
QRhiTextureRenderTarget *createTextureRenderTarget(const QRhiTextureRenderTargetDescription &desc,
QRhiTextureRenderTarget::Flags flags) override;
QRhiSwapChain *createSwapChain() override;
QRhi::FrameOpResult beginFrame(QRhiSwapChain *swapChain, QRhi::BeginFrameFlags flags) override;
QRhi::FrameOpResult endFrame(QRhiSwapChain *swapChain, QRhi::EndFrameFlags flags) override;
QRhi::FrameOpResult beginOffscreenFrame(QRhiCommandBuffer **cb, QRhi::BeginFrameFlags flags) override;
QRhi::FrameOpResult endOffscreenFrame(QRhi::EndFrameFlags flags) override;
QRhi::FrameOpResult finish() override;
void resourceUpdate(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates) override;
void beginPass(QRhiCommandBuffer *cb,
QRhiRenderTarget *rt,
const QColor &colorClearValue,
const QRhiDepthStencilClearValue &depthStencilClearValue,
QRhiResourceUpdateBatch *resourceUpdates) override;
void endPass(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates) override;
void setGraphicsPipeline(QRhiCommandBuffer *cb,
QRhiGraphicsPipeline *ps) override;
void setShaderResources(QRhiCommandBuffer *cb,
QRhiShaderResourceBindings *srb,
int dynamicOffsetCount,
const QRhiCommandBuffer::DynamicOffset *dynamicOffsets) override;
void setVertexInput(QRhiCommandBuffer *cb,
int startBinding, int bindingCount, const QRhiCommandBuffer::VertexInput *bindings,
QRhiBuffer *indexBuf, quint32 indexOffset,
QRhiCommandBuffer::IndexFormat indexFormat) override;
void setViewport(QRhiCommandBuffer *cb, const QRhiViewport &viewport) override;
void setScissor(QRhiCommandBuffer *cb, const QRhiScissor &scissor) override;
void setBlendConstants(QRhiCommandBuffer *cb, const QColor &c) override;
void setStencilRef(QRhiCommandBuffer *cb, quint32 refValue) override;
void draw(QRhiCommandBuffer *cb, quint32 vertexCount,
quint32 instanceCount, quint32 firstVertex, quint32 firstInstance) override;
void drawIndexed(QRhiCommandBuffer *cb, quint32 indexCount,
quint32 instanceCount, quint32 firstIndex,
qint32 vertexOffset, quint32 firstInstance) override;
void debugMarkBegin(QRhiCommandBuffer *cb, const QByteArray &name) override;
void debugMarkEnd(QRhiCommandBuffer *cb) override;
void debugMarkMsg(QRhiCommandBuffer *cb, const QByteArray &msg) override;
void beginComputePass(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates) override;
void endComputePass(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates) override;
void setComputePipeline(QRhiCommandBuffer *cb, QRhiComputePipeline *ps) override;
void dispatch(QRhiCommandBuffer *cb, int x, int y, int z) override;
const QRhiNativeHandles *nativeHandles(QRhiCommandBuffer *cb) override;
void beginExternal(QRhiCommandBuffer *cb) override;
void endExternal(QRhiCommandBuffer *cb) override;
QVector<int> supportedSampleCounts() const override;
int ubufAlignment() const override;
bool isYUpInFramebuffer() const override;
bool isYUpInNDC() const override;
bool isClipDepthZeroToOne() const override;
QMatrix4x4 clipSpaceCorrMatrix() const override;
bool isTextureFormatSupported(QRhiTexture::Format format, QRhiTexture::Flags flags) const override;
bool isFeatureSupported(QRhi::Feature feature) const override;
int resourceLimit(QRhi::ResourceLimit limit) const override;
const QRhiNativeHandles *nativeHandles() override;
void sendVMemStatsToProfiler() override;
bool makeThreadLocalNativeContextCurrent() override;
void releaseCachedResources() override;
bool isDeviceLost() const override;
bool ensureContext(QSurface *surface = nullptr) const;
void executeDeferredReleases();
void trackedBufferBarrier(QGles2CommandBuffer *cbD, QGles2Buffer *bufD, QGles2Buffer::Access access);
void trackedImageBarrier(QGles2CommandBuffer *cbD, QGles2Texture *texD, QGles2Texture::Access access);
void enqueueSubresUpload(QGles2Texture *texD, QGles2CommandBuffer *cbD,
int layer, int level, const QRhiTextureSubresourceUploadDescription &subresDesc);
void enqueueResourceUpdates(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates);
void trackedRegisterBuffer(QRhiPassResourceTracker *passResTracker,
QGles2Buffer *bufD,
QRhiPassResourceTracker::BufferAccess access,
QRhiPassResourceTracker::BufferStage stage);
void trackedRegisterTexture(QRhiPassResourceTracker *passResTracker,
QGles2Texture *texD,
QRhiPassResourceTracker::TextureAccess access,
QRhiPassResourceTracker::TextureStage stage);
void executeCommandBuffer(QRhiCommandBuffer *cb);
void executeBindGraphicsPipeline(QGles2CommandBuffer *cbD, QGles2GraphicsPipeline *psD);
void bindShaderResources(QRhiGraphicsPipeline *maybeGraphicsPs, QRhiComputePipeline *maybeComputePs,
QRhiShaderResourceBindings *srb,
const uint *dynOfsPairs, int dynOfsCount);
QGles2RenderTargetData *enqueueBindFramebuffer(QRhiRenderTarget *rt, QGles2CommandBuffer *cbD,
bool *wantsColorClear = nullptr, bool *wantsDsClear = nullptr);
void enqueueBarriersForPass(QGles2CommandBuffer *cbD);
int effectiveSampleCount(int sampleCount) const;
QByteArray shaderSource(const QRhiShaderStage &shaderStage, int *glslVersion);
bool compileShader(GLuint program, const QRhiShaderStage &shaderStage, int *glslVersion);
bool linkProgram(GLuint program);
void registerUniformIfActive(const QShaderDescription::BlockVariable &var,
const QByteArray &namePrefix,
int binding,
int baseOffset,
GLuint program,
QVector<QGles2UniformDescription> *dst);
void gatherUniforms(GLuint program,
const QShaderDescription::UniformBlock &ub,
QVector<QGles2UniformDescription> *dst);
void gatherSamplers(GLuint program, const QShaderDescription::InOutVariable &v,
QVector<QGles2SamplerDescription> *dst);
bool isProgramBinaryDiskCacheEnabled() const;
enum DiskCacheResult {
DiskCacheHit,
DiskCacheMiss,
DiskCacheError
};
DiskCacheResult tryLoadFromDiskCache(const QRhiShaderStage *stages, int stageCount,
GLuint program, QByteArray *cacheKey);
void trySaveToDiskCache(GLuint program, const QByteArray &cacheKey);
QOpenGLContext *ctx = nullptr;
bool importedContext = false;
QSurfaceFormat requestedFormat;
QSurface *fallbackSurface = nullptr;
QWindow *maybeWindow = nullptr;
mutable bool needsMakeCurrent = false;
QOpenGLExtensions *f = nullptr;
uint vao = 0;
struct Caps {
Caps()
: ctxMajor(2),
ctxMinor(0),
maxTextureSize(2048),
maxDrawBuffers(4),
msaaRenderBuffer(false),
npotTextureFull(true),
gles(false),
fixedIndexPrimitiveRestart(false),
bgraExternalFormat(false),
bgraInternalFormat(false),
r8Format(false),
r16Format(false),
floatFormats(false),
depthTexture(false),
packedDepthStencil(false),
needsDepthStencilCombinedAttach(false),
srgbCapableDefaultFramebuffer(false),
coreProfile(false),
uniformBuffers(false),
elementIndexUint(false),
depth24(false),
rgba8Format(false),
instancing(false),
baseVertex(false),
compute(false),
textureCompareMode(false),
properMapBuffer(false),
nonBaseLevelFramebufferTexture(false),
texelFetch(false)
{ }
int ctxMajor;
int ctxMinor;
int maxTextureSize;
int maxDrawBuffers;
int maxSamples;
// Multisample fb and blit are supported (GLES 3.0 or OpenGL 3.x). Not
// the same as multisample textures!
uint msaaRenderBuffer : 1;
uint npotTextureFull : 1;
uint gles : 1;
uint fixedIndexPrimitiveRestart : 1;
uint bgraExternalFormat : 1;
uint bgraInternalFormat : 1;
uint r8Format : 1;
uint r16Format : 1;
uint floatFormats : 1;
uint depthTexture : 1;
uint packedDepthStencil : 1;
uint needsDepthStencilCombinedAttach : 1;
uint srgbCapableDefaultFramebuffer : 1;
uint coreProfile : 1;
uint uniformBuffers : 1;
uint elementIndexUint : 1;
uint depth24 : 1;
uint rgba8Format : 1;
uint instancing : 1;
uint baseVertex : 1;
uint compute : 1;
uint textureCompareMode : 1;
uint properMapBuffer : 1;
uint nonBaseLevelFramebufferTexture : 1;
uint texelFetch : 1;
} caps;
QGles2SwapChain *currentSwapChain = nullptr;
QVector<GLint> supportedCompressedFormats;
mutable QVector<int> supportedSampleCountList;
QRhiGles2NativeHandles nativeHandlesStruct;
mutable bool contextLost = false;
struct DeferredReleaseEntry {
enum Type {
Buffer,
Pipeline,
Texture,
RenderBuffer,
TextureRenderTarget
};
Type type;
union {
struct {
GLuint buffer;
} buffer;
struct {
GLuint program;
} pipeline;
struct {
GLuint texture;
} texture;
struct {
GLuint renderbuffer;
GLuint renderbuffer2;
} renderbuffer;
struct {
GLuint framebuffer;
} textureRenderTarget;
};
};
QVector<DeferredReleaseEntry> releaseQueue;
struct OffscreenFrame {
OffscreenFrame(QRhiImplementation *rhi) : cbWrapper(rhi) { }
bool active = false;
QGles2CommandBuffer cbWrapper;
} ofr;
QHash<QRhiShaderStage, uint> m_shaderCache;
};
Q_DECLARE_TYPEINFO(QRhiGles2::DeferredReleaseEntry, Q_MOVABLE_TYPE);
QT_END_NAMESPACE
#endif