mirror of
https://github.com/love2d/love.git
synced 2026-08-17 11:00:31 +02:00
Merge branch '12.0-development' into metal
This commit is contained in:
@@ -72,18 +72,22 @@ Buffer::Buffer(love::graphics::Graphics *gfx, const Settings &settings, const st
|
||||
size = getSize();
|
||||
arraylength = getArrayLength();
|
||||
|
||||
if (typeFlags & TYPEFLAG_TEXEL)
|
||||
mapType = BUFFERTYPE_TEXEL;
|
||||
else if (typeFlags & TYPEFLAG_VERTEX)
|
||||
mapType = BUFFERTYPE_VERTEX;
|
||||
else if (typeFlags & TYPEFLAG_INDEX)
|
||||
mapType = BUFFERTYPE_INDEX;
|
||||
else if (typeFlags & TYPEFLAG_SHADER_STORAGE)
|
||||
mapType = BUFFERTYPE_SHADER_STORAGE;
|
||||
if (usageFlags & BUFFERUSAGEFLAG_TEXEL)
|
||||
mapUsage = BUFFERUSAGE_TEXEL;
|
||||
else if (usageFlags & BUFFERUSAGEFLAG_VERTEX)
|
||||
mapUsage = BUFFERUSAGE_VERTEX;
|
||||
else if (usageFlags & BUFFERUSAGEFLAG_INDEX)
|
||||
mapUsage = BUFFERUSAGE_INDEX;
|
||||
else if (usageFlags & BUFFERUSAGEFLAG_SHADER_STORAGE)
|
||||
mapUsage = BUFFERUSAGE_SHADER_STORAGE;
|
||||
else if (usageFlags & BUFFERUSAGEFLAG_COPY_SOURCE)
|
||||
mapUsage = BUFFERUSAGE_COPY_SOURCE;
|
||||
else if (usageFlags & BUFFERUSAGEFLAG_COPY_DEST)
|
||||
mapUsage = BUFFERUSAGE_COPY_DEST;
|
||||
|
||||
target = OpenGL::getGLBufferType(mapType);
|
||||
target = OpenGL::getGLBufferType(mapUsage);
|
||||
|
||||
if (usage == BUFFERUSAGE_STREAM)
|
||||
if (dataUsage == BUFFERDATAUSAGE_STREAM)
|
||||
ownsMemoryMap = true;
|
||||
|
||||
std::vector<uint8> emptydata;
|
||||
@@ -139,12 +143,14 @@ bool Buffer::load(const void *initialdata)
|
||||
/* Clear the error buffer. */;
|
||||
|
||||
glGenBuffers(1, &buffer);
|
||||
gl.bindBuffer(mapType, buffer);
|
||||
gl.bindBuffer(mapUsage, buffer);
|
||||
|
||||
GLenum gldatausage = OpenGL::getGLBufferDataUsage(getDataUsage());
|
||||
|
||||
// initialdata can be null.
|
||||
glBufferData(target, (GLsizeiptr) getSize(), initialdata, OpenGL::getGLBufferUsage(getUsage()));
|
||||
glBufferData(target, (GLsizeiptr) getSize(), initialdata, gldatausage);
|
||||
|
||||
if (getTypeFlags() & TYPEFLAG_TEXEL)
|
||||
if (getUsageFlags() & BUFFERUSAGEFLAG_TEXEL)
|
||||
{
|
||||
glGenTextures(1, &texture);
|
||||
gl.bindBufferTextureToUnit(texture, 0, false, true);
|
||||
@@ -200,7 +206,7 @@ void Buffer::unmap(size_t usedoffset, size_t usedsize)
|
||||
mapped = false;
|
||||
|
||||
// Orphan optimization - see fill().
|
||||
if (usage != BUFFERUSAGE_STATIC && mappedRange.first == 0 && mappedRange.getSize() == getSize())
|
||||
if (dataUsage != BUFFERDATAUSAGE_STATIC && mappedRange.first == 0 && mappedRange.getSize() == getSize())
|
||||
{
|
||||
usedoffset = 0;
|
||||
usedsize = getSize();
|
||||
@@ -228,21 +234,21 @@ void Buffer::fill(size_t offset, size_t size, const void *data)
|
||||
if (!Range(0, buffersize).contains(Range(offset, size)))
|
||||
return;
|
||||
|
||||
GLenum glusage = OpenGL::getGLBufferUsage(usage);
|
||||
GLenum gldatausage = OpenGL::getGLBufferDataUsage(dataUsage);
|
||||
|
||||
gl.bindBuffer(mapType, buffer);
|
||||
gl.bindBuffer(mapUsage, buffer);
|
||||
|
||||
if (usage != BUFFERUSAGE_STATIC && size == buffersize)
|
||||
if (dataUsage != BUFFERDATAUSAGE_STATIC && size == buffersize)
|
||||
{
|
||||
// "orphan" current buffer to avoid implicit synchronisation on the GPU:
|
||||
// http://www.seas.upenn.edu/~pcozzi/OpenGLInsights/OpenGLInsights-AsynchronousBufferTransfers.pdf
|
||||
gl.bindBuffer(mapType, buffer);
|
||||
glBufferData(target, (GLsizeiptr) buffersize, nullptr, glusage);
|
||||
gl.bindBuffer(mapUsage, buffer);
|
||||
glBufferData(target, (GLsizeiptr) buffersize, nullptr, gldatausage);
|
||||
|
||||
#if LOVE_WINDOWS
|
||||
// TODO: Verify that this codepath is a useful optimization.
|
||||
if (gl.getVendor() == OpenGL::VENDOR_INTEL)
|
||||
glBufferData(target, (GLsizeiptr) buffersize, data, glusage);
|
||||
glBufferData(target, (GLsizeiptr) buffersize, data, gldatausage);
|
||||
else
|
||||
#endif
|
||||
glBufferSubData(target, 0, (GLsizeiptr) buffersize, data);
|
||||
@@ -253,6 +259,14 @@ void Buffer::fill(size_t offset, size_t size, const void *data)
|
||||
}
|
||||
}
|
||||
|
||||
void Buffer::copyTo(love::graphics::Buffer *dest, size_t sourceoffset, size_t destoffset, size_t size)
|
||||
{
|
||||
gl.bindBuffer(BUFFERUSAGE_COPY_SOURCE, buffer);
|
||||
gl.bindBuffer(BUFFERUSAGE_COPY_DEST, ((Buffer *) dest)->buffer);
|
||||
|
||||
glCopyBufferSubData(GL_COPY_READ_BUFFER, GL_COPY_WRITE_BUFFER, sourceoffset, destoffset, size);
|
||||
}
|
||||
|
||||
} // opengl
|
||||
} // graphics
|
||||
} // love
|
||||
|
||||
@@ -53,6 +53,7 @@ public:
|
||||
void *map(MapType map, size_t offset, size_t size) override;
|
||||
void unmap(size_t usedoffset, size_t usedsize) override;
|
||||
void fill(size_t offset, size_t size, const void *data) override;
|
||||
void copyTo(love::graphics::Buffer *dest, size_t sourceoffset, size_t destoffset, size_t size) override;
|
||||
|
||||
ptrdiff_t getHandle() const override { return buffer; };
|
||||
ptrdiff_t getTexelBufferHandle() const override { return texture; };
|
||||
@@ -64,7 +65,7 @@ private:
|
||||
void unmapStatic(size_t offset, size_t size);
|
||||
void unmapStream();
|
||||
|
||||
BufferType mapType = BUFFERTYPE_VERTEX;
|
||||
BufferUsage mapUsage = BUFFERUSAGE_VERTEX;
|
||||
GLenum target = 0;
|
||||
|
||||
// The buffer object identifier. Assigned by OpenGL.
|
||||
|
||||
@@ -157,7 +157,7 @@ const char *Graphics::getName() const
|
||||
return "love.graphics.opengl";
|
||||
}
|
||||
|
||||
love::graphics::StreamBuffer *Graphics::newStreamBuffer(BufferType type, size_t size)
|
||||
love::graphics::StreamBuffer *Graphics::newStreamBuffer(BufferUsage type, size_t size)
|
||||
{
|
||||
return CreateStreamBuffer(type, size);
|
||||
}
|
||||
@@ -321,6 +321,9 @@ bool Graphics::setMode(void */*context*/, int width, int height, int pixelwidth,
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
}
|
||||
|
||||
if (!GLAD_ES_VERSION_2_0)
|
||||
glEnable(GL_VERTEX_PROGRAM_POINT_SIZE);
|
||||
|
||||
gl.setTextureUnit(0);
|
||||
|
||||
// Set pixel row alignment - code that calls glTexSubImage and glReadPixels
|
||||
@@ -350,46 +353,46 @@ bool Graphics::setMode(void */*context*/, int width, int height, int pixelwidth,
|
||||
{
|
||||
// Initial sizes that should be good enough for most cases. It will
|
||||
// resize to fit if needed, later.
|
||||
batchedDrawState.vb[0] = CreateStreamBuffer(BUFFERTYPE_VERTEX, 1024 * 1024 * 1);
|
||||
batchedDrawState.vb[1] = CreateStreamBuffer(BUFFERTYPE_VERTEX, 256 * 1024 * 1);
|
||||
batchedDrawState.indexBuffer = CreateStreamBuffer(BUFFERTYPE_INDEX, sizeof(uint16) * LOVE_UINT16_MAX);
|
||||
batchedDrawState.vb[0] = CreateStreamBuffer(BUFFERUSAGE_VERTEX, 1024 * 1024 * 1);
|
||||
batchedDrawState.vb[1] = CreateStreamBuffer(BUFFERUSAGE_VERTEX, 256 * 1024 * 1);
|
||||
batchedDrawState.indexBuffer = CreateStreamBuffer(BUFFERUSAGE_INDEX, sizeof(uint16) * LOVE_UINT16_MAX);
|
||||
}
|
||||
|
||||
if (capabilities.features[FEATURE_TEXEL_BUFFER] && defaultBuffers[BUFFERTYPE_TEXEL].get() == nullptr)
|
||||
if (capabilities.features[FEATURE_TEXEL_BUFFER] && defaultBuffers[BUFFERUSAGE_TEXEL].get() == nullptr)
|
||||
{
|
||||
Buffer::Settings settings(Buffer::TYPEFLAG_TEXEL, BUFFERUSAGE_STATIC);
|
||||
Buffer::Settings settings(BUFFERUSAGEFLAG_TEXEL, BUFFERDATAUSAGE_STATIC);
|
||||
std::vector<Buffer::DataDeclaration> format = {{"", DATAFORMAT_FLOAT_VEC4, 0}};
|
||||
|
||||
const float texel[] = {0.0f, 0.0f, 0.0f, 1.0f};
|
||||
|
||||
auto buffer = newBuffer(settings, format, texel, sizeof(texel), 1);
|
||||
defaultBuffers[BUFFERTYPE_TEXEL].set(buffer, Acquire::NORETAIN);
|
||||
defaultBuffers[BUFFERUSAGE_TEXEL].set(buffer, Acquire::NORETAIN);
|
||||
}
|
||||
|
||||
if (capabilities.features[FEATURE_GLSL4] && defaultBuffers[BUFFERTYPE_SHADER_STORAGE].get() == nullptr)
|
||||
if (capabilities.features[FEATURE_GLSL4] && defaultBuffers[BUFFERUSAGE_SHADER_STORAGE].get() == nullptr)
|
||||
{
|
||||
Buffer::Settings settings(Buffer::TYPEFLAG_SHADER_STORAGE, BUFFERUSAGE_STATIC);
|
||||
Buffer::Settings settings(BUFFERUSAGEFLAG_SHADER_STORAGE, BUFFERDATAUSAGE_STATIC);
|
||||
std::vector<Buffer::DataDeclaration> format = {{"", DATAFORMAT_FLOAT, 0}};
|
||||
|
||||
std::vector<float> data;
|
||||
data.resize(Buffer::SHADER_STORAGE_BUFFER_MAX_STRIDE / 4);
|
||||
|
||||
auto buffer = newBuffer(settings, format, data.data(), data.size() * sizeof(float), data.size());
|
||||
defaultBuffers[BUFFERTYPE_TEXEL].set(buffer, Acquire::NORETAIN);
|
||||
defaultBuffers[BUFFERUSAGE_TEXEL].set(buffer, Acquire::NORETAIN);
|
||||
}
|
||||
|
||||
// Load default resources before other Volatile.
|
||||
for (int i = 0; i < BUFFERTYPE_MAX_ENUM; i++)
|
||||
for (int i = 0; i < BUFFERUSAGE_MAX_ENUM; i++)
|
||||
{
|
||||
if (defaultBuffers[i].get())
|
||||
((Buffer *) defaultBuffers[i].get())->loadVolatile();
|
||||
}
|
||||
|
||||
if (defaultBuffers[BUFFERTYPE_TEXEL].get())
|
||||
gl.setDefaultTexelBuffer((GLuint) defaultBuffers[BUFFERTYPE_TEXEL]->getTexelBufferHandle());
|
||||
if (defaultBuffers[BUFFERUSAGE_TEXEL].get())
|
||||
gl.setDefaultTexelBuffer((GLuint) defaultBuffers[BUFFERUSAGE_TEXEL]->getTexelBufferHandle());
|
||||
|
||||
if (defaultBuffers[BUFFERTYPE_SHADER_STORAGE].get())
|
||||
gl.setDefaultStorageBuffer((GLuint) defaultBuffers[BUFFERTYPE_SHADER_STORAGE]->getHandle());
|
||||
if (defaultBuffers[BUFFERUSAGE_SHADER_STORAGE].get())
|
||||
gl.setDefaultStorageBuffer((GLuint) defaultBuffers[BUFFERUSAGE_SHADER_STORAGE]->getHandle());
|
||||
|
||||
// Reload all volatile objects.
|
||||
if (!Volatile::loadAll())
|
||||
@@ -511,7 +514,7 @@ void Graphics::draw(const DrawIndexedCommand &cmd)
|
||||
GLenum glprimitivetype = OpenGL::getGLPrimitiveType(cmd.primitiveType);
|
||||
GLenum gldatatype = OpenGL::getGLIndexDataType(cmd.indexType);
|
||||
|
||||
gl.bindBuffer(BUFFERTYPE_INDEX, cmd.indexBuffer->getHandle());
|
||||
gl.bindBuffer(BUFFERUSAGE_INDEX, cmd.indexBuffer->getHandle());
|
||||
|
||||
if (cmd.instanceCount > 1)
|
||||
glDrawElementsInstanced(glprimitivetype, cmd.indexCount, gldatatype, gloffset, cmd.instanceCount);
|
||||
@@ -553,7 +556,7 @@ void Graphics::drawQuads(int start, int count, const VertexAttributes &attribute
|
||||
gl.bindTextureToUnit(texture, 0, false);
|
||||
gl.setCullMode(CULL_NONE);
|
||||
|
||||
gl.bindBuffer(BUFFERTYPE_INDEX, quadIndexBuffer->getHandle());
|
||||
gl.bindBuffer(BUFFERUSAGE_INDEX, quadIndexBuffer->getHandle());
|
||||
|
||||
if (gl.isBaseVertexSupported())
|
||||
{
|
||||
@@ -1462,10 +1465,9 @@ void Graphics::setBlendState(const BlendState &blend)
|
||||
|
||||
void Graphics::setPointSize(float size)
|
||||
{
|
||||
if (batchedDrawState.primitiveMode == PRIMITIVE_POINTS)
|
||||
if (size != states.back().pointSize)
|
||||
flushBatchedDraws();
|
||||
|
||||
gl.setPointSize(size * getCurrentDPIScale());
|
||||
states.back().pointSize = size;
|
||||
}
|
||||
|
||||
@@ -1553,8 +1555,9 @@ void Graphics::initCapabilities()
|
||||
capabilities.features[FEATURE_GLSL3] = GLAD_ES_VERSION_3_0 || gl.isCoreProfile();
|
||||
capabilities.features[FEATURE_GLSL4] = GLAD_ES_VERSION_3_1 || (gl.isCoreProfile() && GLAD_VERSION_4_3);
|
||||
capabilities.features[FEATURE_INSTANCING] = gl.isInstancingSupported();
|
||||
capabilities.features[FEATURE_TEXEL_BUFFER] = gl.isBufferTypeSupported(BUFFERTYPE_TEXEL);
|
||||
static_assert(FEATURE_MAX_ENUM == 11, "Graphics::initCapabilities must be updated when adding a new graphics feature!");
|
||||
capabilities.features[FEATURE_TEXEL_BUFFER] = gl.isBufferUsageSupported(BUFFERUSAGE_TEXEL);
|
||||
capabilities.features[FEATURE_COPY_BUFFER] = gl.isBufferUsageSupported(BUFFERUSAGE_COPY_SOURCE);
|
||||
static_assert(FEATURE_MAX_ENUM == 12, "Graphics::initCapabilities must be updated when adding a new graphics feature!");
|
||||
|
||||
capabilities.limits[LIMIT_POINT_SIZE] = gl.getMaxPointSize();
|
||||
capabilities.limits[LIMIT_TEXTURE_SIZE] = gl.getMax2DTextureSize();
|
||||
@@ -1572,14 +1575,20 @@ void Graphics::initCapabilities()
|
||||
capabilities.textureTypes[i] = gl.isTextureTypeSupported((TextureType) i);
|
||||
}
|
||||
|
||||
PixelFormat Graphics::getSizedFormat(PixelFormat format, bool rendertarget, bool readable, bool sRGB) const
|
||||
PixelFormat Graphics::getSizedFormat(PixelFormat format, bool rendertarget, bool readable) const
|
||||
{
|
||||
uint32 requiredflags = 0;
|
||||
if (rendertarget)
|
||||
requiredflags |= PIXELFORMATUSAGEFLAGS_RENDERTARGET;
|
||||
if (readable)
|
||||
requiredflags |= PIXELFORMATUSAGEFLAGS_SAMPLE;
|
||||
|
||||
switch (format)
|
||||
{
|
||||
case PIXELFORMAT_NORMAL:
|
||||
if (isGammaCorrect())
|
||||
return PIXELFORMAT_RGBA8_UNORM_sRGB;
|
||||
else if (!OpenGL::isPixelFormatSupported(PIXELFORMAT_RGBA8_UNORM, rendertarget, readable, sRGB))
|
||||
else if ((OpenGL::getPixelFormatUsageFlags(PIXELFORMAT_RGBA8_UNORM) & requiredflags) != requiredflags)
|
||||
// 32-bit render targets don't have guaranteed support on GLES2.
|
||||
return PIXELFORMAT_RGBA4_UNORM;
|
||||
else
|
||||
@@ -1595,18 +1604,26 @@ bool Graphics::isPixelFormatSupported(PixelFormat format, bool rendertarget, boo
|
||||
{
|
||||
if (sRGB && format == PIXELFORMAT_RGBA8_UNORM)
|
||||
{
|
||||
format = PIXELFORMAT_RGBA8_UNORM_sRGB;
|
||||
format = getSRGBPixelFormat(format);
|
||||
sRGB = false;
|
||||
}
|
||||
|
||||
format = getSizedFormat(format, rendertarget, readable, sRGB);
|
||||
uint32 requiredflags = 0;
|
||||
if (rendertarget)
|
||||
requiredflags |= PIXELFORMATUSAGEFLAGS_RENDERTARGET;
|
||||
if (readable)
|
||||
requiredflags |= PIXELFORMATUSAGEFLAGS_SAMPLE;
|
||||
|
||||
format = getSizedFormat(format, rendertarget, readable);
|
||||
|
||||
OptionalBool &supported = supportedFormats[format][rendertarget ? 1 : 0][readable ? 1 : 0][sRGB ? 1 : 0];
|
||||
|
||||
if (supported.hasValue)
|
||||
return supported.value;
|
||||
|
||||
if (!OpenGL::isPixelFormatSupported(format, rendertarget, readable, sRGB))
|
||||
auto supportedflags = OpenGL::getPixelFormatUsageFlags(format);
|
||||
|
||||
if ((requiredflags & supportedflags) != requiredflags)
|
||||
{
|
||||
supported.set(false);
|
||||
return supported.value;
|
||||
@@ -1636,7 +1653,7 @@ bool Graphics::isPixelFormatSupported(PixelFormat format, bool rendertarget, boo
|
||||
return true;
|
||||
}
|
||||
|
||||
OpenGL::TextureFormat fmt = OpenGL::convertPixelFormat(format, readable, sRGB);
|
||||
OpenGL::TextureFormat fmt = OpenGL::convertPixelFormat(format, !readable, sRGB);
|
||||
|
||||
GLuint current_fbo = gl.getFramebuffer(OpenGL::FRAMEBUFFER_ALL);
|
||||
|
||||
|
||||
@@ -104,7 +104,7 @@ public:
|
||||
|
||||
void setWireframe(bool enable) override;
|
||||
|
||||
PixelFormat getSizedFormat(PixelFormat format, bool rendertarget, bool readable, bool sRGB) const override;
|
||||
PixelFormat getSizedFormat(PixelFormat format, bool rendertarget, bool readable) const override;
|
||||
bool isPixelFormatSupported(PixelFormat format, bool rendertarget, bool readable, bool sRGB = false) override;
|
||||
Renderer getRenderer() const override;
|
||||
bool usesGLSLES() const override;
|
||||
@@ -139,7 +139,7 @@ private:
|
||||
|
||||
love::graphics::ShaderStage *newShaderStageInternal(ShaderStage::StageType stage, const std::string &cachekey, const std::string &source, bool gles) override;
|
||||
love::graphics::Shader *newShaderInternal(love::graphics::ShaderStage *vertex, love::graphics::ShaderStage *pixel) override;
|
||||
love::graphics::StreamBuffer *newStreamBuffer(BufferType type, size_t size) override;
|
||||
love::graphics::StreamBuffer *newStreamBuffer(BufferUsage type, size_t size) override;
|
||||
void setRenderTargetsInternal(const RenderTargets &rts, int w, int h, int pixelw, int pixelh, bool hasSRGBtexture) override;
|
||||
void initCapabilities() override;
|
||||
void getAPIStats(int &shaderswitches) const override;
|
||||
@@ -167,7 +167,7 @@ private:
|
||||
size_t bufferMapMemorySize;
|
||||
|
||||
// Only needed for buffer types that can be bound to shaders.
|
||||
StrongRef<love::graphics::Buffer> defaultBuffers[BUFFERTYPE_MAX_ENUM];
|
||||
StrongRef<love::graphics::Buffer> defaultBuffers[BUFFERUSAGE_MAX_ENUM];
|
||||
|
||||
// [rendertarget][readable][srgb]
|
||||
OptionalBool supportedFormats[PIXELFORMAT_MAX_ENUM][2][2][2];
|
||||
|
||||
@@ -235,15 +235,15 @@ void OpenGL::setupContext()
|
||||
glGetIntegerv(GL_CULL_FACE_MODE, &faceCull);
|
||||
state.faceCullMode = faceCull;
|
||||
|
||||
for (int i = 0; i < (int) BUFFERTYPE_MAX_ENUM; i++)
|
||||
for (int i = 0; i < (int) BUFFERUSAGE_MAX_ENUM; i++)
|
||||
{
|
||||
state.boundBuffers[i] = 0;
|
||||
if (isBufferTypeSupported((BufferType) i))
|
||||
glBindBuffer(getGLBufferType((BufferType) i), 0);
|
||||
if (isBufferUsageSupported((BufferUsage) i))
|
||||
glBindBuffer(getGLBufferType((BufferUsage) i), 0);
|
||||
}
|
||||
|
||||
if (isBufferTypeSupported(BUFFERTYPE_SHADER_STORAGE))
|
||||
state.boundIndexedBuffers[BUFFERTYPE_SHADER_STORAGE].resize(maxShaderStorageBufferBindings, 0);
|
||||
if (isBufferUsageSupported(BUFFERUSAGE_SHADER_STORAGE))
|
||||
state.boundIndexedBuffers[BUFFERUSAGE_SHADER_STORAGE].resize(maxShaderStorageBufferBindings, 0);
|
||||
|
||||
// Initialize multiple texture unit support for shaders.
|
||||
for (int i = 0; i < TEXTURE_MAX_ENUM + 1; i++)
|
||||
@@ -484,12 +484,12 @@ void OpenGL::initMaxValues()
|
||||
else
|
||||
maxTextureArrayLayers = 0;
|
||||
|
||||
if (isBufferTypeSupported(BUFFERTYPE_TEXEL))
|
||||
if (isBufferUsageSupported(BUFFERUSAGE_TEXEL))
|
||||
glGetIntegerv(GL_MAX_TEXTURE_BUFFER_SIZE, &maxTexelBufferSize);
|
||||
else
|
||||
maxTexelBufferSize = 0;
|
||||
|
||||
if (isBufferTypeSupported(BUFFERTYPE_SHADER_STORAGE))
|
||||
if (isBufferUsageSupported(BUFFERUSAGE_SHADER_STORAGE))
|
||||
{
|
||||
glGetIntegerv(GL_MAX_SHADER_STORAGE_BLOCK_SIZE, &maxShaderStorageBufferSize);
|
||||
glGetIntegerv(GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS, &maxShaderStorageBufferBindings);
|
||||
@@ -613,16 +613,18 @@ GLenum OpenGL::getGLPrimitiveType(PrimitiveType type)
|
||||
return GL_ZERO;
|
||||
}
|
||||
|
||||
GLenum OpenGL::getGLBufferType(BufferType type)
|
||||
GLenum OpenGL::getGLBufferType(BufferUsage usage)
|
||||
{
|
||||
switch (type)
|
||||
switch (usage)
|
||||
{
|
||||
case BUFFERTYPE_VERTEX: return GL_ARRAY_BUFFER;
|
||||
case BUFFERTYPE_INDEX: return GL_ELEMENT_ARRAY_BUFFER;
|
||||
case BUFFERTYPE_TEXEL: return GL_TEXTURE_BUFFER;
|
||||
case BUFFERTYPE_UNIFORM: return GL_UNIFORM_BUFFER;
|
||||
case BUFFERTYPE_SHADER_STORAGE: return GL_SHADER_STORAGE_BUFFER;
|
||||
case BUFFERTYPE_MAX_ENUM: return GL_ZERO;
|
||||
case BUFFERUSAGE_VERTEX: return GL_ARRAY_BUFFER;
|
||||
case BUFFERUSAGE_INDEX: return GL_ELEMENT_ARRAY_BUFFER;
|
||||
case BUFFERUSAGE_UNIFORM: return GL_UNIFORM_BUFFER;
|
||||
case BUFFERUSAGE_TEXEL: return GL_TEXTURE_BUFFER;
|
||||
case BUFFERUSAGE_SHADER_STORAGE: return GL_SHADER_STORAGE_BUFFER;
|
||||
case BUFFERUSAGE_COPY_SOURCE: return GL_COPY_READ_BUFFER;
|
||||
case BUFFERUSAGE_COPY_DEST: return GL_COPY_WRITE_BUFFER;
|
||||
case BUFFERUSAGE_MAX_ENUM: return GL_ZERO;
|
||||
}
|
||||
|
||||
return GL_ZERO;
|
||||
@@ -791,18 +793,18 @@ GLenum OpenGL::getGLVertexDataType(DataFormat format, int &components, GLboolean
|
||||
return GL_ZERO;
|
||||
}
|
||||
|
||||
GLenum OpenGL::getGLBufferUsage(BufferUsage usage)
|
||||
GLenum OpenGL::getGLBufferDataUsage(BufferDataUsage usage)
|
||||
{
|
||||
switch (usage)
|
||||
{
|
||||
case BUFFERUSAGE_STREAM: return GL_STREAM_DRAW;
|
||||
case BUFFERUSAGE_DYNAMIC: return GL_DYNAMIC_DRAW;
|
||||
case BUFFERUSAGE_STATIC: return GL_STATIC_DRAW;
|
||||
case BUFFERDATAUSAGE_STREAM: return GL_STREAM_DRAW;
|
||||
case BUFFERDATAUSAGE_DYNAMIC: return GL_DYNAMIC_DRAW;
|
||||
case BUFFERDATAUSAGE_STATIC: return GL_STATIC_DRAW;
|
||||
default: return 0;
|
||||
}
|
||||
}
|
||||
|
||||
void OpenGL::bindBuffer(BufferType type, GLuint buffer)
|
||||
void OpenGL::bindBuffer(BufferUsage type, GLuint buffer)
|
||||
{
|
||||
if (state.boundBuffers[type] != buffer)
|
||||
{
|
||||
@@ -815,7 +817,7 @@ void OpenGL::deleteBuffer(GLuint buffer)
|
||||
{
|
||||
glDeleteBuffers(1, &buffer);
|
||||
|
||||
for (int i = 0; i < (int) BUFFERTYPE_MAX_ENUM; i++)
|
||||
for (int i = 0; i < (int) BUFFERUSAGE_MAX_ENUM; i++)
|
||||
{
|
||||
if (state.boundBuffers[i] == buffer)
|
||||
state.boundBuffers[i] = 0;
|
||||
@@ -868,7 +870,7 @@ void OpenGL::setVertexAttributes(const VertexAttributes &attributes, const Buffe
|
||||
|
||||
const void *offsetpointer = reinterpret_cast<void*>(bufferinfo.offset + attrib.offsetFromVertex);
|
||||
|
||||
bindBuffer(BUFFERTYPE_VERTEX, (GLuint) bufferinfo.buffer->getHandle());
|
||||
bindBuffer(BUFFERUSAGE_VERTEX, (GLuint) bufferinfo.buffer->getHandle());
|
||||
|
||||
if (intformat)
|
||||
glVertexAttribIPointer(i, components, gltype, layout.stride, offsetpointer);
|
||||
@@ -942,19 +944,6 @@ void OpenGL::setScissor(const Rect &v, bool rtActive)
|
||||
state.scissor = v;
|
||||
}
|
||||
|
||||
void OpenGL::setPointSize(float size)
|
||||
{
|
||||
if (GLAD_VERSION_1_0)
|
||||
glPointSize(size);
|
||||
|
||||
state.pointSize = size;
|
||||
}
|
||||
|
||||
float OpenGL::getPointSize() const
|
||||
{
|
||||
return state.pointSize;
|
||||
}
|
||||
|
||||
void OpenGL::setEnableState(EnableState enablestate, bool enable)
|
||||
{
|
||||
GLenum glstate = GL_NONE;
|
||||
@@ -1164,7 +1153,7 @@ void OpenGL::bindTextureToUnit(Texture *texture, int textureunit, bool restorepr
|
||||
bindTextureToUnit(textype, handle, textureunit, restoreprev, bindforedit);
|
||||
}
|
||||
|
||||
void OpenGL::bindIndexedBuffer(GLuint buffer, BufferType type, int index)
|
||||
void OpenGL::bindIndexedBuffer(GLuint buffer, BufferUsage type, int index)
|
||||
{
|
||||
auto &bindings = state.boundIndexedBuffers[type];
|
||||
if (bindings.size() > (size_t) index && buffer != bindings[index])
|
||||
@@ -1433,19 +1422,22 @@ bool OpenGL::isTextureTypeSupported(TextureType type) const
|
||||
return false;
|
||||
}
|
||||
|
||||
bool OpenGL::isBufferTypeSupported(BufferType type) const
|
||||
bool OpenGL::isBufferUsageSupported(BufferUsage usage) const
|
||||
{
|
||||
switch (type)
|
||||
switch (usage)
|
||||
{
|
||||
case BUFFERTYPE_VERTEX:
|
||||
case BUFFERTYPE_INDEX:
|
||||
case BUFFERUSAGE_VERTEX:
|
||||
case BUFFERUSAGE_INDEX:
|
||||
return true;
|
||||
case BUFFERTYPE_TEXEL:
|
||||
case BUFFERUSAGE_TEXEL:
|
||||
// Not supported in ES until 3.2, which we don't support shaders for...
|
||||
return GLAD_VERSION_3_1;
|
||||
case BUFFERTYPE_SHADER_STORAGE:
|
||||
case BUFFERUSAGE_SHADER_STORAGE:
|
||||
return (GLAD_VERSION_4_3 && isCoreProfile()) || GLAD_ES_VERSION_3_1;
|
||||
case BUFFERTYPE_MAX_ENUM:
|
||||
case BUFFERUSAGE_COPY_SOURCE:
|
||||
case BUFFERUSAGE_COPY_DEST:
|
||||
return GLAD_VERSION_3_1 || GLAD_ES_VERSION_3_0;
|
||||
case BUFFERUSAGE_MAX_ENUM:
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
@@ -1933,152 +1925,178 @@ OpenGL::TextureFormat OpenGL::convertPixelFormat(PixelFormat pixelformat, bool r
|
||||
return f;
|
||||
}
|
||||
|
||||
bool OpenGL::isPixelFormatSupported(PixelFormat pixelformat, bool rendertarget, bool readable, bool isSRGB)
|
||||
uint32 OpenGL::getPixelFormatUsageFlags(PixelFormat pixelformat)
|
||||
{
|
||||
if (rendertarget && isPixelFormatCompressed(pixelformat))
|
||||
return false;
|
||||
const uint32 commonsample = PIXELFORMATUSAGEFLAGS_SAMPLE | PIXELFORMATUSAGEFLAGS_LINEAR;
|
||||
const uint32 commonrender = PIXELFORMATUSAGEFLAGS_RENDERTARGET | PIXELFORMATUSAGEFLAGS_BLEND | PIXELFORMATUSAGEFLAGS_MSAA;
|
||||
|
||||
if (isSRGB)
|
||||
pixelformat = getSRGBPixelFormat(pixelformat);
|
||||
uint32 flags = PIXELFORMATUSAGEFLAGS_NONE;
|
||||
|
||||
switch (pixelformat)
|
||||
{
|
||||
case PIXELFORMAT_R8_UNORM:
|
||||
case PIXELFORMAT_RG8_UNORM:
|
||||
if (GLAD_VERSION_3_0 || GLAD_ES_VERSION_3_0 || GLAD_ARB_texture_rg || GLAD_EXT_texture_rg)
|
||||
return true;
|
||||
else if (pixelformat == PIXELFORMAT_R8_UNORM && !rendertarget && (GLAD_ES_VERSION_2_0 || GLAD_VERSION_1_1))
|
||||
return true; // We'll use OpenGL's luminance format internally.
|
||||
else
|
||||
return false;
|
||||
flags |= commonsample | commonrender;
|
||||
else if (pixelformat == PIXELFORMAT_R8_UNORM && (GLAD_ES_VERSION_2_0 || GLAD_VERSION_1_1))
|
||||
flags |= commonsample; // We'll use OpenGL's luminance format internally.
|
||||
break;
|
||||
case PIXELFORMAT_RGBA8_UNORM:
|
||||
if (rendertarget)
|
||||
return GLAD_VERSION_1_0 || GLAD_ES_VERSION_3_0 || GLAD_OES_rgb8_rgba8 || GLAD_ARM_rgba8;
|
||||
else
|
||||
return true;
|
||||
flags |= commonsample;
|
||||
if (GLAD_VERSION_1_0 || GLAD_ES_VERSION_3_0 || GLAD_OES_rgb8_rgba8 || GLAD_ARM_rgba8)
|
||||
flags |= commonrender;
|
||||
break;
|
||||
case PIXELFORMAT_RGBA8_UNORM_sRGB:
|
||||
if (gl.bugs.brokenSRGB)
|
||||
return false;
|
||||
if (rendertarget)
|
||||
{
|
||||
if (GLAD_VERSION_1_0)
|
||||
{
|
||||
return GLAD_VERSION_3_0 || ((GLAD_ARB_framebuffer_sRGB || GLAD_EXT_framebuffer_sRGB)
|
||||
&& (GLAD_VERSION_2_1 || GLAD_EXT_texture_sRGB));
|
||||
}
|
||||
else
|
||||
return GLAD_ES_VERSION_3_0;
|
||||
}
|
||||
else
|
||||
return GLAD_ES_VERSION_3_0 || GLAD_VERSION_2_1 || GLAD_EXT_texture_sRGB;
|
||||
break;
|
||||
if (GLAD_ES_VERSION_3_0 || GLAD_VERSION_2_1 || GLAD_EXT_texture_sRGB)
|
||||
flags |= commonsample;
|
||||
if (GLAD_ES_VERSION_3_0 || GLAD_VERSION_3_0
|
||||
|| ((GLAD_ARB_framebuffer_sRGB || GLAD_EXT_framebuffer_sRGB) && (GLAD_VERSION_2_1 || GLAD_EXT_texture_sRGB)))
|
||||
flags |= commonrender;
|
||||
break;
|
||||
case PIXELFORMAT_R16_UNORM:
|
||||
case PIXELFORMAT_RG16_UNORM:
|
||||
return GLAD_VERSION_3_0
|
||||
if (GLAD_VERSION_3_0
|
||||
|| (GLAD_VERSION_1_1 && GLAD_ARB_texture_rg)
|
||||
|| (GLAD_EXT_texture_norm16 && (GLAD_ES_VERSION_3_0 || GLAD_EXT_texture_rg));
|
||||
|| (GLAD_EXT_texture_norm16 && (GLAD_ES_VERSION_3_0 || GLAD_EXT_texture_rg)))
|
||||
flags |= commonsample | commonrender;
|
||||
break;
|
||||
case PIXELFORMAT_RGBA16_UNORM:
|
||||
return GLAD_VERSION_1_1 || GLAD_EXT_texture_norm16;
|
||||
if (GLAD_VERSION_1_1 || GLAD_EXT_texture_norm16)
|
||||
flags |= commonsample | commonrender;
|
||||
break;
|
||||
case PIXELFORMAT_R16_FLOAT:
|
||||
case PIXELFORMAT_RG16_FLOAT:
|
||||
if (GLAD_VERSION_1_0)
|
||||
return GLAD_VERSION_3_0 || (GLAD_ARB_texture_float && GLAD_ARB_half_float_pixel && GLAD_ARB_texture_rg);
|
||||
else if (rendertarget && !GLAD_EXT_color_buffer_half_float)
|
||||
return false;
|
||||
else
|
||||
return GLAD_ES_VERSION_3_0 || (GLAD_OES_texture_half_float && GLAD_EXT_texture_rg);
|
||||
if (GLAD_VERSION_1_0 && (GLAD_VERSION_3_0 || (GLAD_ARB_texture_float && GLAD_ARB_half_float_pixel && GLAD_ARB_texture_rg)))
|
||||
flags |= commonsample | commonrender;
|
||||
if (GLAD_ES_VERSION_3_0 || (GLAD_OES_texture_half_float && GLAD_EXT_texture_rg))
|
||||
flags |= commonsample;
|
||||
if (GLAD_EXT_color_buffer_half_float && (GLAD_ES_VERSION_3_0 || GLAD_EXT_texture_rg))
|
||||
flags |= commonrender;
|
||||
if (!(GLAD_VERSION_1_1 || GLAD_ES_VERSION_3_0 || GLAD_OES_texture_half_float_linear))
|
||||
flags &= ~PIXELFORMATUSAGEFLAGS_LINEAR;
|
||||
break;
|
||||
case PIXELFORMAT_RGBA16_FLOAT:
|
||||
if (GLAD_VERSION_1_0)
|
||||
return GLAD_VERSION_3_0 || (GLAD_ARB_texture_float && GLAD_ARB_half_float_pixel);
|
||||
else if (rendertarget && !GLAD_EXT_color_buffer_half_float)
|
||||
return false;
|
||||
else
|
||||
return GLAD_ES_VERSION_3_0 || GLAD_OES_texture_half_float;
|
||||
if (GLAD_VERSION_3_0 || (GLAD_VERSION_1_0 && GLAD_ARB_texture_float && GLAD_ARB_half_float_pixel))
|
||||
flags |= commonsample | commonrender;
|
||||
if (GLAD_ES_VERSION_3_0 || GLAD_OES_texture_half_float)
|
||||
flags |= commonsample;
|
||||
if (GLAD_EXT_color_buffer_half_float)
|
||||
flags |= commonrender;
|
||||
if (!(GLAD_VERSION_1_1 || GLAD_ES_VERSION_3_0 || GLAD_OES_texture_half_float_linear))
|
||||
flags &= ~PIXELFORMATUSAGEFLAGS_LINEAR;
|
||||
break;
|
||||
case PIXELFORMAT_R32_FLOAT:
|
||||
case PIXELFORMAT_RG32_FLOAT:
|
||||
if (GLAD_VERSION_1_0)
|
||||
return GLAD_VERSION_3_0 || (GLAD_ARB_texture_float && GLAD_ARB_texture_rg);
|
||||
else if (!rendertarget)
|
||||
return GLAD_ES_VERSION_3_0 || (GLAD_OES_texture_float && GLAD_EXT_texture_rg);
|
||||
else
|
||||
return false;
|
||||
if (GLAD_VERSION_3_0 || (GLAD_VERSION_1_0 && GLAD_ARB_texture_float && GLAD_ARB_texture_rg))
|
||||
flags |= commonsample | commonrender;
|
||||
if (GLAD_ES_VERSION_3_0 || (GLAD_OES_texture_float && GLAD_EXT_texture_rg))
|
||||
flags |= commonsample;
|
||||
if (!(GLAD_VERSION_1_1 || GLAD_ES_VERSION_3_0 || GLAD_OES_texture_half_float_linear))
|
||||
flags &= ~PIXELFORMATUSAGEFLAGS_LINEAR;
|
||||
break;
|
||||
case PIXELFORMAT_RGBA32_FLOAT:
|
||||
if (GLAD_VERSION_1_0)
|
||||
return GLAD_VERSION_3_0 || GLAD_ARB_texture_float;
|
||||
else if (!rendertarget)
|
||||
return GLAD_ES_VERSION_3_0 || GLAD_OES_texture_float;
|
||||
else
|
||||
return false;
|
||||
if (GLAD_VERSION_3_0 || (GLAD_VERSION_1_0 && GLAD_ARB_texture_float))
|
||||
flags |= commonsample | commonrender;
|
||||
if (GLAD_ES_VERSION_3_0 || GLAD_OES_texture_float)
|
||||
flags |= commonsample;
|
||||
if (!(GLAD_VERSION_1_1 || GLAD_OES_texture_float_linear))
|
||||
flags &= ~PIXELFORMATUSAGEFLAGS_LINEAR;
|
||||
break;
|
||||
|
||||
case PIXELFORMAT_LA8_UNORM:
|
||||
return !rendertarget;
|
||||
flags |= commonsample;
|
||||
break;
|
||||
|
||||
case PIXELFORMAT_RGBA4_UNORM:
|
||||
case PIXELFORMAT_RGB5A1_UNORM:
|
||||
return true;
|
||||
flags |= commonsample | commonrender;
|
||||
break;
|
||||
case PIXELFORMAT_RGB565_UNORM:
|
||||
return GLAD_ES_VERSION_2_0 || GLAD_VERSION_4_2 || GLAD_ARB_ES2_compatibility;
|
||||
if (GLAD_ES_VERSION_2_0 || GLAD_VERSION_4_2 || GLAD_ARB_ES2_compatibility)
|
||||
flags |= commonsample | commonrender;
|
||||
break;
|
||||
case PIXELFORMAT_RGB10A2_UNORM:
|
||||
return GLAD_ES_VERSION_3_0 || GLAD_VERSION_1_0;
|
||||
if (GLAD_ES_VERSION_3_0 || GLAD_VERSION_1_0)
|
||||
flags |= commonsample | commonrender;
|
||||
break;
|
||||
case PIXELFORMAT_RG11B10_FLOAT:
|
||||
if (rendertarget)
|
||||
return GLAD_VERSION_3_0 || GLAD_EXT_packed_float || GLAD_APPLE_color_buffer_packed_float;
|
||||
else
|
||||
return GLAD_VERSION_3_0 || GLAD_EXT_packed_float || GLAD_APPLE_texture_packed_float;
|
||||
if (GLAD_VERSION_3_0 || GLAD_EXT_packed_float || GLAD_APPLE_texture_packed_float)
|
||||
flags |= commonsample;
|
||||
if (GLAD_VERSION_3_0 || GLAD_EXT_packed_float || GLAD_APPLE_color_buffer_packed_float)
|
||||
flags |= commonrender;
|
||||
break;
|
||||
|
||||
case PIXELFORMAT_STENCIL8:
|
||||
return rendertarget && !readable;
|
||||
flags |= PIXELFORMATUSAGEFLAGS_RENDERTARGET | PIXELFORMATUSAGEFLAGS_MSAA;
|
||||
break;
|
||||
|
||||
case PIXELFORMAT_DEPTH16_UNORM:
|
||||
if (!rendertarget)
|
||||
return false;
|
||||
else if (readable)
|
||||
return GLAD_VERSION_2_0 || GLAD_ES_VERSION_3_0 || GLAD_OES_depth_texture;
|
||||
else
|
||||
return true;
|
||||
flags |= PIXELFORMATUSAGEFLAGS_RENDERTARGET | PIXELFORMATUSAGEFLAGS_MSAA;
|
||||
if (GLAD_VERSION_2_0 || GLAD_ES_VERSION_3_0 || GLAD_OES_depth_texture)
|
||||
flags |= commonsample;
|
||||
break;
|
||||
|
||||
case PIXELFORMAT_DEPTH24_UNORM:
|
||||
if (!rendertarget)
|
||||
return false;
|
||||
else if (readable)
|
||||
return GLAD_VERSION_2_0 || GLAD_ES_VERSION_3_0 || (GLAD_OES_depth_texture && (GLAD_OES_depth24 || GLAD_OES_depth_texture));
|
||||
else
|
||||
return GLAD_VERSION_2_0 || GLAD_ES_VERSION_3_0 || GLAD_OES_depth24 || GLAD_OES_depth_texture;
|
||||
if (GLAD_VERSION_2_0 || GLAD_ES_VERSION_3_0 || GLAD_OES_depth24 || GLAD_OES_depth_texture)
|
||||
flags |= PIXELFORMATUSAGEFLAGS_RENDERTARGET | PIXELFORMATUSAGEFLAGS_MSAA;
|
||||
|
||||
if (GLAD_VERSION_2_0 || GLAD_ES_VERSION_3_0 || (GLAD_OES_depth_texture && (GLAD_OES_depth24 || GLAD_OES_depth_texture)))
|
||||
flags |= commonsample;
|
||||
break;
|
||||
|
||||
case PIXELFORMAT_DEPTH24_UNORM_STENCIL8:
|
||||
if (!rendertarget)
|
||||
return false;
|
||||
else if (readable)
|
||||
return GLAD_VERSION_3_0 || GLAD_ES_VERSION_3_0 || GLAD_EXT_packed_depth_stencil || (GLAD_OES_depth_texture && GLAD_OES_packed_depth_stencil);
|
||||
else
|
||||
return GLAD_VERSION_3_0 || GLAD_ES_VERSION_3_0 || GLAD_EXT_packed_depth_stencil || GLAD_OES_packed_depth_stencil;
|
||||
if (GLAD_VERSION_3_0 || GLAD_ES_VERSION_3_0 || GLAD_EXT_packed_depth_stencil || GLAD_OES_packed_depth_stencil)
|
||||
flags |= PIXELFORMATUSAGEFLAGS_RENDERTARGET | PIXELFORMATUSAGEFLAGS_MSAA;
|
||||
|
||||
if (GLAD_VERSION_3_0 || GLAD_ES_VERSION_3_0 || GLAD_EXT_packed_depth_stencil || (GLAD_OES_depth_texture && GLAD_OES_packed_depth_stencil))
|
||||
flags |= commonsample;
|
||||
break;
|
||||
|
||||
case PIXELFORMAT_DEPTH32_FLOAT:
|
||||
case PIXELFORMAT_DEPTH32_FLOAT_STENCIL8:
|
||||
return rendertarget && (GLAD_VERSION_3_0 || GLAD_ES_VERSION_3_0 || GLAD_ARB_depth_buffer_float);
|
||||
if (GLAD_VERSION_3_0 || GLAD_ES_VERSION_3_0 || GLAD_ARB_depth_buffer_float)
|
||||
flags |= commonsample | PIXELFORMATUSAGEFLAGS_RENDERTARGET | PIXELFORMATUSAGEFLAGS_MSAA;
|
||||
break;
|
||||
|
||||
case PIXELFORMAT_DXT1_UNORM:
|
||||
return GLAD_EXT_texture_compression_s3tc || GLAD_EXT_texture_compression_dxt1;
|
||||
if (GLAD_EXT_texture_compression_s3tc || GLAD_EXT_texture_compression_dxt1)
|
||||
flags |= commonsample;
|
||||
break;
|
||||
case PIXELFORMAT_DXT3_UNORM:
|
||||
return GLAD_EXT_texture_compression_s3tc || GLAD_ANGLE_texture_compression_dxt3;
|
||||
if (GLAD_EXT_texture_compression_s3tc || GLAD_ANGLE_texture_compression_dxt3)
|
||||
flags |= commonsample;
|
||||
break;
|
||||
case PIXELFORMAT_DXT5_UNORM:
|
||||
return GLAD_EXT_texture_compression_s3tc || GLAD_ANGLE_texture_compression_dxt5;
|
||||
if (GLAD_EXT_texture_compression_s3tc || GLAD_ANGLE_texture_compression_dxt5)
|
||||
flags |= commonsample;
|
||||
break;
|
||||
case PIXELFORMAT_BC4_UNORM:
|
||||
case PIXELFORMAT_BC4_SNORM:
|
||||
case PIXELFORMAT_BC5_UNORM:
|
||||
case PIXELFORMAT_BC5_SNORM:
|
||||
return (GLAD_VERSION_3_0 || GLAD_ARB_texture_compression_rgtc || GLAD_EXT_texture_compression_rgtc);
|
||||
if (GLAD_VERSION_3_0 || GLAD_ARB_texture_compression_rgtc || GLAD_EXT_texture_compression_rgtc)
|
||||
flags |= commonsample;
|
||||
break;
|
||||
case PIXELFORMAT_BC6H_UFLOAT:
|
||||
case PIXELFORMAT_BC6H_FLOAT:
|
||||
case PIXELFORMAT_BC7_UNORM:
|
||||
return GLAD_VERSION_4_2 || GLAD_ARB_texture_compression_bptc;
|
||||
if (GLAD_VERSION_4_2 || GLAD_ARB_texture_compression_bptc)
|
||||
flags |= commonsample;
|
||||
break;
|
||||
case PIXELFORMAT_PVR1_RGB2_UNORM:
|
||||
case PIXELFORMAT_PVR1_RGB4_UNORM:
|
||||
case PIXELFORMAT_PVR1_RGBA2_UNORM:
|
||||
case PIXELFORMAT_PVR1_RGBA4_UNORM:
|
||||
return isSRGB ? GLAD_EXT_pvrtc_sRGB : GLAD_IMG_texture_compression_pvrtc;
|
||||
if (GLAD_IMG_texture_compression_pvrtc)
|
||||
flags |= commonsample;
|
||||
break;
|
||||
case PIXELFORMAT_ETC1_UNORM:
|
||||
// ETC2 support guarantees ETC1 support as well.
|
||||
return GLAD_ES_VERSION_3_0 || GLAD_VERSION_4_3 || GLAD_ARB_ES3_compatibility || GLAD_OES_compressed_ETC1_RGB8_texture;
|
||||
if (GLAD_ES_VERSION_3_0 || GLAD_VERSION_4_3 || GLAD_ARB_ES3_compatibility || GLAD_OES_compressed_ETC1_RGB8_texture)
|
||||
flags |= commonsample;
|
||||
break;
|
||||
case PIXELFORMAT_ETC2_RGB_UNORM:
|
||||
case PIXELFORMAT_ETC2_RGBA_UNORM:
|
||||
case PIXELFORMAT_ETC2_RGBA1_UNORM:
|
||||
@@ -2086,7 +2104,9 @@ bool OpenGL::isPixelFormatSupported(PixelFormat pixelformat, bool rendertarget,
|
||||
case PIXELFORMAT_EAC_R_SNORM:
|
||||
case PIXELFORMAT_EAC_RG_UNORM:
|
||||
case PIXELFORMAT_EAC_RG_SNORM:
|
||||
return GLAD_ES_VERSION_3_0 || GLAD_VERSION_4_3 || GLAD_ARB_ES3_compatibility;
|
||||
if (GLAD_ES_VERSION_3_0 || GLAD_VERSION_4_3 || GLAD_ARB_ES3_compatibility)
|
||||
flags |= commonsample;
|
||||
break;
|
||||
case PIXELFORMAT_ASTC_4x4:
|
||||
case PIXELFORMAT_ASTC_5x4:
|
||||
case PIXELFORMAT_ASTC_5x5:
|
||||
@@ -2101,28 +2121,18 @@ bool OpenGL::isPixelFormatSupported(PixelFormat pixelformat, bool rendertarget,
|
||||
case PIXELFORMAT_ASTC_10x10:
|
||||
case PIXELFORMAT_ASTC_12x10:
|
||||
case PIXELFORMAT_ASTC_12x12:
|
||||
return GLAD_ES_VERSION_3_2 || GLAD_KHR_texture_compression_astc_ldr;
|
||||
if (GLAD_ES_VERSION_3_2 || GLAD_KHR_texture_compression_astc_ldr)
|
||||
flags |= commonsample;
|
||||
break;
|
||||
|
||||
default:
|
||||
return false;
|
||||
case PIXELFORMAT_UNKNOWN:
|
||||
case PIXELFORMAT_NORMAL:
|
||||
case PIXELFORMAT_HDR:
|
||||
case PIXELFORMAT_MAX_ENUM:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
bool OpenGL::hasTextureFilteringSupport(PixelFormat pixelformat)
|
||||
{
|
||||
switch (pixelformat)
|
||||
{
|
||||
case PIXELFORMAT_R16_FLOAT:
|
||||
case PIXELFORMAT_RG16_FLOAT:
|
||||
case PIXELFORMAT_RGBA16_FLOAT:
|
||||
return GLAD_VERSION_1_1 || GLAD_ES_VERSION_3_0 || GLAD_OES_texture_half_float_linear;
|
||||
case PIXELFORMAT_R32_FLOAT:
|
||||
case PIXELFORMAT_RG32_FLOAT:
|
||||
case PIXELFORMAT_RGBA32_FLOAT:
|
||||
return GLAD_VERSION_1_1 || GLAD_OES_texture_float_linear;
|
||||
default:
|
||||
return true;
|
||||
}
|
||||
return flags;
|
||||
}
|
||||
|
||||
const char *OpenGL::errorString(GLenum errorcode)
|
||||
|
||||
@@ -235,7 +235,7 @@ public:
|
||||
* NOTE: This does not account for multiple VAOs being used! Index buffer
|
||||
* bindings are per-VAO in OpenGL, but this doesn't know about that.
|
||||
**/
|
||||
void bindBuffer(BufferType type, GLuint buffer);
|
||||
void bindBuffer(BufferUsage type, GLuint buffer);
|
||||
|
||||
/**
|
||||
* glDeleteBuffers which updates our shadowed state.
|
||||
@@ -270,12 +270,6 @@ public:
|
||||
**/
|
||||
void setScissor(const Rect &v, bool rtActive);
|
||||
|
||||
/**
|
||||
* Sets the global point size.
|
||||
**/
|
||||
void setPointSize(float size);
|
||||
float getPointSize() const;
|
||||
|
||||
/**
|
||||
* State-tracked version of glEnable.
|
||||
**/
|
||||
@@ -341,7 +335,7 @@ public:
|
||||
|
||||
void bindBufferTextureToUnit(GLuint texture, int textureunit, bool restoreprev, bool bindforedit);
|
||||
|
||||
void bindIndexedBuffer(GLuint buffer, BufferType type, int index);
|
||||
void bindIndexedBuffer(GLuint buffer, BufferUsage type, int index);
|
||||
|
||||
/**
|
||||
* Helper for deleting an OpenGL texture.
|
||||
@@ -362,7 +356,7 @@ public:
|
||||
bool rawTexStorage(TextureType target, int levels, PixelFormat pixelformat, bool &isSRGB, int width, int height, int depth = 1);
|
||||
|
||||
bool isTextureTypeSupported(TextureType type) const;
|
||||
bool isBufferTypeSupported(BufferType type) const;
|
||||
bool isBufferUsageSupported(BufferUsage usage) const;
|
||||
bool isClampZeroOneTextureWrapSupported() const;
|
||||
bool isPixelShaderHighpSupported() const;
|
||||
bool isInstancingSupported() const;
|
||||
@@ -433,18 +427,17 @@ public:
|
||||
Vendor getVendor() const;
|
||||
|
||||
static GLenum getGLPrimitiveType(PrimitiveType type);
|
||||
static GLenum getGLBufferType(BufferType type);
|
||||
static GLenum getGLBufferType(BufferUsage usage);
|
||||
static GLenum getGLIndexDataType(IndexDataType type);
|
||||
static GLenum getGLVertexDataType(DataFormat format, int &components, GLboolean &normalized, bool &intformat);
|
||||
static GLenum getGLBufferUsage(BufferUsage usage);
|
||||
static GLenum getGLBufferDataUsage(BufferDataUsage usage);
|
||||
static GLenum getGLTextureType(TextureType type);
|
||||
static GLint getGLWrapMode(SamplerState::WrapMode wmode);
|
||||
static GLint getGLCompareMode(CompareMode mode);
|
||||
|
||||
static TextureFormat convertPixelFormat(PixelFormat pixelformat, bool renderbuffer, bool &isSRGB);
|
||||
static bool isTexStorageSupported();
|
||||
static bool isPixelFormatSupported(PixelFormat pixelformat, bool rendertarget, bool readable, bool isSRGB);
|
||||
static bool hasTextureFilteringSupport(PixelFormat pixelformat);
|
||||
static uint32 getPixelFormatUsageFlags(PixelFormat pixelformat);
|
||||
|
||||
static const char *errorString(GLenum errorcode);
|
||||
static const char *framebufferStatusString(GLenum status);
|
||||
@@ -487,12 +480,12 @@ private:
|
||||
// Tracked OpenGL state.
|
||||
struct
|
||||
{
|
||||
GLuint boundBuffers[BUFFERTYPE_MAX_ENUM];
|
||||
GLuint boundBuffers[BUFFERUSAGE_MAX_ENUM];
|
||||
|
||||
// Texture unit state (currently bound texture for each texture unit.)
|
||||
std::vector<GLuint> boundTextures[TEXTURE_MAX_ENUM + 1];
|
||||
|
||||
std::vector<GLuint> boundIndexedBuffers[BUFFERTYPE_MAX_ENUM];
|
||||
std::vector<GLuint> boundIndexedBuffers[BUFFERUSAGE_MAX_ENUM];
|
||||
|
||||
bool enableState[ENABLE_MAX_ENUM];
|
||||
|
||||
|
||||
@@ -48,7 +48,6 @@ Shader::Shader(love::graphics::ShaderStage *vertex, love::graphics::ShaderStage
|
||||
, program(0)
|
||||
, builtinUniforms()
|
||||
, builtinUniformInfo()
|
||||
, lastPointSize(0.0f)
|
||||
{
|
||||
// load shader source and create program object
|
||||
loadVolatile();
|
||||
@@ -315,7 +314,7 @@ void Shader::mapActiveUniforms()
|
||||
}
|
||||
}
|
||||
|
||||
if (gl.isBufferTypeSupported(BUFFERTYPE_SHADER_STORAGE))
|
||||
if (gl.isBufferUsageSupported(BUFFERUSAGE_SHADER_STORAGE))
|
||||
{
|
||||
GLint numstoragebuffers = 0;
|
||||
glGetProgramInterfaceiv(program, GL_SHADER_STORAGE_BLOCK, GL_ACTIVE_RESOURCES, &numstoragebuffers);
|
||||
@@ -430,8 +429,6 @@ bool Shader::loadVolatile()
|
||||
{
|
||||
OpenGL::TempDebugGroup debuggroup("Shader load");
|
||||
|
||||
lastPointSize = -1.0f;
|
||||
|
||||
// zero out active texture list
|
||||
textureUnits.clear();
|
||||
textureUnits.push_back(TextureUnit());
|
||||
@@ -577,7 +574,7 @@ void Shader::attach()
|
||||
}
|
||||
|
||||
for (auto bufferbinding : activeStorageBufferBindings)
|
||||
gl.bindIndexedBuffer(bufferbinding.buffer, BUFFERTYPE_SHADER_STORAGE, bufferbinding.bindingindex);
|
||||
gl.bindIndexedBuffer(bufferbinding.buffer, BUFFERUSAGE_SHADER_STORAGE, bufferbinding.bindingindex);
|
||||
|
||||
// send any pending uniforms to the shader program.
|
||||
for (const auto &p : pendingUniformUpdates)
|
||||
@@ -807,9 +804,9 @@ void Shader::sendBuffers(const UniformInfo *info, love::graphics::Buffer **buffe
|
||||
bool storagebinding = info->baseType == UNIFORM_STORAGEBUFFER;
|
||||
|
||||
if (texelbinding)
|
||||
requiredtypeflags = Buffer::TYPEFLAG_TEXEL;
|
||||
requiredtypeflags = BUFFERUSAGEFLAG_TEXEL;
|
||||
else if (storagebinding)
|
||||
requiredtypeflags = Buffer::TYPEFLAG_SHADER_STORAGE;
|
||||
requiredtypeflags = BUFFERUSAGEFLAG_SHADER_STORAGE;
|
||||
|
||||
if (requiredtypeflags == 0)
|
||||
return;
|
||||
@@ -828,7 +825,7 @@ void Shader::sendBuffers(const UniformInfo *info, love::graphics::Buffer **buffe
|
||||
|
||||
if (buffer != nullptr)
|
||||
{
|
||||
if ((buffer->getTypeFlags() & requiredtypeflags) == 0)
|
||||
if ((buffer->getUsageFlags() & requiredtypeflags) == 0)
|
||||
{
|
||||
if (internalUpdate)
|
||||
continue;
|
||||
@@ -906,7 +903,7 @@ void Shader::sendBuffers(const UniformInfo *info, love::graphics::Buffer **buffe
|
||||
glbuffer = gl.getDefaultStorageBuffer();
|
||||
|
||||
if (shaderactive)
|
||||
gl.bindIndexedBuffer(glbuffer, BUFFERTYPE_SHADER_STORAGE, bindingindex);
|
||||
gl.bindIndexedBuffer(glbuffer, BUFFERUSAGE_SHADER_STORAGE, bindingindex);
|
||||
|
||||
int activeindex = storageBufferBindingIndexToActiveBinding[bindingindex];
|
||||
if (activeindex >= 0)
|
||||
@@ -962,26 +959,11 @@ void Shader::setVideoTextures(love::graphics::Texture *ytexture, love::graphics:
|
||||
}
|
||||
}
|
||||
|
||||
void Shader::updatePointSize(float size)
|
||||
{
|
||||
if (size == lastPointSize || current != this)
|
||||
return;
|
||||
|
||||
GLint location = builtinUniforms[BUILTIN_POINT_SIZE];
|
||||
if (location >= 0)
|
||||
glUniform1f(location, size);
|
||||
|
||||
lastPointSize = size;
|
||||
}
|
||||
|
||||
void Shader::updateBuiltinUniforms(love::graphics::Graphics *gfx, int viewportW, int viewportH)
|
||||
{
|
||||
if (current != this)
|
||||
return;
|
||||
|
||||
if (GLAD_ES_VERSION_2_0)
|
||||
updatePointSize(gl.getPointSize());
|
||||
|
||||
BuiltinUniformData data;
|
||||
|
||||
data.transformMatrix = gfx->getTransform();
|
||||
@@ -1001,6 +983,12 @@ void Shader::updateBuiltinUniforms(love::graphics::Graphics *gfx, int viewportW,
|
||||
}
|
||||
}
|
||||
|
||||
// Store DPI scale in an unused component of another vector.
|
||||
data.normalMatrix[0].w = (float) gfx->getCurrentDPIScale();
|
||||
|
||||
// Same with point size.
|
||||
data.normalMatrix[1].w = gfx->getPointSize();
|
||||
|
||||
data.screenSizeParams.x = viewportW;
|
||||
data.screenSizeParams.y = viewportH;
|
||||
|
||||
|
||||
@@ -43,10 +43,6 @@ class Shader final : public love::graphics::Shader, public Volatile
|
||||
{
|
||||
public:
|
||||
|
||||
/**
|
||||
* Creates a new Shader using a list of source codes.
|
||||
* Source must contain either vertex or pixel shader code, or both.
|
||||
**/
|
||||
Shader(love::graphics::ShaderStage *vertex, love::graphics::ShaderStage *pixel);
|
||||
virtual ~Shader();
|
||||
|
||||
@@ -67,7 +63,6 @@ public:
|
||||
ptrdiff_t getHandle() const override;
|
||||
void setVideoTextures(love::graphics::Texture *ytexture, love::graphics::Texture *cbtexture, love::graphics::Texture *crtexture) override;
|
||||
|
||||
void updatePointSize(float size);
|
||||
void updateBuiltinUniforms(love::graphics::Graphics *gfx, int viewportW, int viewportH);
|
||||
|
||||
private:
|
||||
@@ -125,8 +120,6 @@ private:
|
||||
|
||||
std::vector<std::pair<const UniformInfo *, int>> pendingUniformUpdates;
|
||||
|
||||
float lastPointSize;
|
||||
|
||||
}; // Shader
|
||||
|
||||
} // opengl
|
||||
|
||||
@@ -44,7 +44,7 @@ class StreamBufferClientMemory final : public love::graphics::StreamBuffer
|
||||
{
|
||||
public:
|
||||
|
||||
StreamBufferClientMemory(BufferType mode, size_t size)
|
||||
StreamBufferClientMemory(BufferUsage mode, size_t size)
|
||||
: love::graphics::StreamBuffer(mode, size)
|
||||
, data(nullptr)
|
||||
{
|
||||
@@ -86,7 +86,7 @@ class StreamBufferSubDataOrphan final : public love::graphics::StreamBuffer, pub
|
||||
{
|
||||
public:
|
||||
|
||||
StreamBufferSubDataOrphan(BufferType mode, size_t size)
|
||||
StreamBufferSubDataOrphan(BufferUsage mode, size_t size)
|
||||
: love::graphics::StreamBuffer(mode, size)
|
||||
, vbo(0)
|
||||
, glMode(OpenGL::getGLBufferType(mode))
|
||||
@@ -184,7 +184,7 @@ class StreamBufferSync : public love::graphics::StreamBuffer
|
||||
{
|
||||
public:
|
||||
|
||||
StreamBufferSync(BufferType type, size_t size)
|
||||
StreamBufferSync(BufferUsage type, size_t size)
|
||||
: love::graphics::StreamBuffer(type, size)
|
||||
, frameIndex(0)
|
||||
, syncs()
|
||||
@@ -220,7 +220,7 @@ class StreamBufferMapSync final : public StreamBufferSync, public Volatile
|
||||
{
|
||||
public:
|
||||
|
||||
StreamBufferMapSync(BufferType type, size_t size)
|
||||
StreamBufferMapSync(BufferUsage type, size_t size)
|
||||
: StreamBufferSync(type, size)
|
||||
, vbo(0)
|
||||
, glMode(OpenGL::getGLBufferType(mode))
|
||||
@@ -302,7 +302,7 @@ public:
|
||||
|
||||
// Coherent mapping is supposedly faster on intel/nvidia aside from a couple
|
||||
// old nvidia GPUs.
|
||||
StreamBufferPersistentMapSync(BufferType type, size_t size, bool coherent = true)
|
||||
StreamBufferPersistentMapSync(BufferUsage type, size_t size, bool coherent = true)
|
||||
: StreamBufferSync(type, size)
|
||||
, vbo(0)
|
||||
, glMode(OpenGL::getGLBufferType(mode))
|
||||
@@ -393,7 +393,7 @@ class StreamBufferPinnedMemory final : public StreamBufferSync, public Volatile
|
||||
{
|
||||
public:
|
||||
|
||||
StreamBufferPinnedMemory(BufferType type, size_t size)
|
||||
StreamBufferPinnedMemory(BufferUsage type, size_t size)
|
||||
: StreamBufferSync(type, size)
|
||||
, vbo(0)
|
||||
, glMode(OpenGL::getGLBufferType(mode))
|
||||
@@ -491,7 +491,7 @@ private:
|
||||
|
||||
}; // StreamBufferPinnedMemory
|
||||
|
||||
love::graphics::StreamBuffer *CreateStreamBuffer(BufferType mode, size_t size)
|
||||
love::graphics::StreamBuffer *CreateStreamBuffer(BufferUsage mode, size_t size)
|
||||
{
|
||||
if (gl.isCoreProfile())
|
||||
{
|
||||
|
||||
@@ -29,7 +29,7 @@ namespace graphics
|
||||
namespace opengl
|
||||
{
|
||||
|
||||
love::graphics::StreamBuffer *CreateStreamBuffer(BufferType mode, size_t size);
|
||||
love::graphics::StreamBuffer *CreateStreamBuffer(BufferUsage mode, size_t size);
|
||||
|
||||
} // opengl
|
||||
} // graphics
|
||||
|
||||
@@ -251,7 +251,7 @@ void Texture::createTexture()
|
||||
int slices = texType == TEXTURE_CUBE ? 6 : 1;
|
||||
Rect rect = {0, 0, 2, 2};
|
||||
for (int slice = 0; slice < slices; slice++)
|
||||
uploadByteData(PIXELFORMAT_RGBA8_UNORM, px, sizeof(px), 0, slice, rect, nullptr);
|
||||
uploadByteData(PIXELFORMAT_RGBA8_UNORM, px, sizeof(px), 0, slice, rect);
|
||||
|
||||
return;
|
||||
}
|
||||
@@ -452,18 +452,8 @@ void Texture::unloadVolatile()
|
||||
setGraphicsMemorySize(0);
|
||||
}
|
||||
|
||||
void Texture::uploadByteData(PixelFormat pixelformat, const void *data, size_t size, int level, int slice, const Rect &r, love::image::ImageDataBase *imgd)
|
||||
void Texture::uploadByteData(PixelFormat pixelformat, const void *data, size_t size, int level, int slice, const Rect &r)
|
||||
{
|
||||
love::image::ImageDataBase *oldd = slices.get(slice, level);
|
||||
|
||||
// We can only replace the internal Data (used when reloading due to setMode)
|
||||
// if the dimensions match.
|
||||
if (imgd != nullptr && oldd != nullptr && oldd->getWidth() == imgd->getWidth()
|
||||
&& oldd->getHeight() == imgd->getHeight())
|
||||
{
|
||||
slices.set(slice, level, imgd);
|
||||
}
|
||||
|
||||
OpenGL::TempDebugGroup debuggroup("Texture data upload");
|
||||
|
||||
gl.bindTextureToUnit(this, 0, false);
|
||||
@@ -539,7 +529,9 @@ void Texture::setSamplerState(const SamplerState &s)
|
||||
// Base class does common validation and assigns samplerState.
|
||||
love::graphics::Texture::setSamplerState(s);
|
||||
|
||||
if (!OpenGL::hasTextureFilteringSupport(getPixelFormat()))
|
||||
auto supportedflags = OpenGL::getPixelFormatUsageFlags(getPixelFormat());
|
||||
|
||||
if ((supportedflags & PIXELFORMATUSAGEFLAGS_LINEAR) == 0)
|
||||
{
|
||||
samplerState.magFilter = samplerState.minFilter = SamplerState::FILTER_NEAREST;
|
||||
|
||||
|
||||
@@ -58,7 +58,7 @@ private:
|
||||
|
||||
void createTexture();
|
||||
|
||||
void uploadByteData(PixelFormat pixelformat, const void *data, size_t size, int level, int slice, const Rect &r, love::image::ImageDataBase *imgd = nullptr) override;
|
||||
void uploadByteData(PixelFormat pixelformat, const void *data, size_t size, int level, int slice, const Rect &r) override;
|
||||
|
||||
void generateMipmapsInternal() override;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user