mirror of
https://github.com/love2d/love-android.git
synced 2026-08-20 04:31:26 +02:00
using latest love-android @ changeset 8659be0e75a3
This commit is contained in:
@@ -176,6 +176,8 @@ StringMap<Graphics::Support, Graphics::SUPPORT_MAX_ENUM>::Entry Graphics::suppor
|
||||
{ "mipmap", Graphics::SUPPORT_MIPMAP },
|
||||
{ "dxt", Graphics::SUPPORT_DXT },
|
||||
{ "bc5", Graphics::SUPPORT_BC5 },
|
||||
{ "etc1", Graphics::SUPPORT_ETC1 },
|
||||
{ "pvrtc1", Graphics::SUPPORT_PVRTC1 },
|
||||
{ "instancing", Graphics::SUPPORT_INSTANCING },
|
||||
{ "srgb", Graphics::SUPPORT_SRGB },
|
||||
};
|
||||
|
||||
@@ -95,6 +95,8 @@ public:
|
||||
SUPPORT_MIPMAP,
|
||||
SUPPORT_DXT,
|
||||
SUPPORT_BC5,
|
||||
SUPPORT_ETC1,
|
||||
SUPPORT_PVRTC1,
|
||||
SUPPORT_INSTANCING,
|
||||
SUPPORT_SRGB,
|
||||
SUPPORT_MAX_ENUM
|
||||
@@ -145,6 +147,20 @@ public:
|
||||
**/
|
||||
virtual void unSetMode() = 0;
|
||||
|
||||
/**
|
||||
* Sets whether the module is active (internal use only.)
|
||||
**/
|
||||
virtual void setActive(bool active) = 0;
|
||||
|
||||
/**
|
||||
* Gets whether the module is active. Graphics module methods are only
|
||||
* guaranteed to work when it is active. Calling them otherwise may cause
|
||||
* the program to crash (or worse.)
|
||||
* Normally the module will always be active as long as a window exists, it
|
||||
* may be different on some platforms (especially mobile ones.)
|
||||
**/
|
||||
virtual bool isActive() const = 0;
|
||||
|
||||
static bool getConstant(const char *in, DrawMode &out);
|
||||
static bool getConstant(DrawMode in, const char *&out);
|
||||
|
||||
|
||||
@@ -109,16 +109,6 @@ bool Texture::getConstant(WrapMode in, const char *&out)
|
||||
return wrapModes.find(in, out);
|
||||
}
|
||||
|
||||
bool Texture::getConstant(const char *in, Format &out)
|
||||
{
|
||||
return formats.find(in, out);
|
||||
}
|
||||
|
||||
bool Texture::getConstant(Format in, const char *&out)
|
||||
{
|
||||
return formats.find(in, out);
|
||||
}
|
||||
|
||||
StringMap<Texture::FilterMode, Texture::FILTER_MAX_ENUM>::Entry Texture::filterModeEntries[] =
|
||||
{
|
||||
{ "linear", Texture::FILTER_LINEAR },
|
||||
@@ -135,15 +125,5 @@ StringMap<Texture::WrapMode, Texture::WRAP_MAX_ENUM>::Entry Texture::wrapModeEnt
|
||||
|
||||
StringMap<Texture::WrapMode, Texture::WRAP_MAX_ENUM> Texture::wrapModes(Texture::wrapModeEntries, sizeof(Texture::wrapModeEntries));
|
||||
|
||||
StringMap<Texture::Format, Texture::FORMAT_MAX_ENUM>::Entry Texture::formatEntries[] =
|
||||
{
|
||||
{"normal", Texture::FORMAT_NORMAL},
|
||||
{"hdr", Texture::FORMAT_HDR},
|
||||
{"srgb", Texture::FORMAT_SRGB},
|
||||
};
|
||||
|
||||
StringMap<Texture::Format, Texture::FORMAT_MAX_ENUM> Texture::formats(Texture::formatEntries, sizeof(Texture::formatEntries));
|
||||
|
||||
|
||||
} // graphics
|
||||
} // love
|
||||
|
||||
@@ -55,14 +55,6 @@ public:
|
||||
FILTER_MAX_ENUM
|
||||
};
|
||||
|
||||
enum Format
|
||||
{
|
||||
FORMAT_NORMAL,
|
||||
FORMAT_HDR,
|
||||
FORMAT_SRGB,
|
||||
FORMAT_MAX_ENUM
|
||||
};
|
||||
|
||||
struct Filter
|
||||
{
|
||||
Filter();
|
||||
@@ -119,9 +111,6 @@ public:
|
||||
static bool getConstant(const char *in, WrapMode &out);
|
||||
static bool getConstant(WrapMode in, const char *&out);
|
||||
|
||||
static bool getConstant(const char *in, Format &out);
|
||||
static bool getConstant(Format in, const char *&out);
|
||||
|
||||
protected:
|
||||
|
||||
int width;
|
||||
@@ -143,9 +132,6 @@ private:
|
||||
static StringMap<WrapMode, WRAP_MAX_ENUM>::Entry wrapModeEntries[];
|
||||
static StringMap<WrapMode, WRAP_MAX_ENUM> wrapModes;
|
||||
|
||||
static StringMap<Format, FORMAT_MAX_ENUM>::Entry formatEntries[];
|
||||
static StringMap<Format, FORMAT_MAX_ENUM> formats;
|
||||
|
||||
}; // Texture
|
||||
|
||||
} // graphics
|
||||
|
||||
@@ -451,7 +451,7 @@ static void getStrategy()
|
||||
}
|
||||
}
|
||||
|
||||
Canvas::Canvas(int width, int height, Texture::Format format, int fsaa)
|
||||
Canvas::Canvas(int width, int height, Format format, int fsaa)
|
||||
: fbo(0)
|
||||
, resolve_fbo(0)
|
||||
, texture(0)
|
||||
@@ -556,36 +556,31 @@ bool Canvas::loadVolatile()
|
||||
glGenTextures(1, &texture);
|
||||
gl.bindTexture(texture);
|
||||
|
||||
if (GLAD_ANGLE_texture_usage)
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_USAGE_ANGLE, GL_FRAMEBUFFER_ATTACHMENT_ANGLE);
|
||||
|
||||
setFilter(filter);
|
||||
setWrap(wrap);
|
||||
|
||||
GLint internalformat;
|
||||
GLenum textype;
|
||||
switch (format)
|
||||
{
|
||||
case Texture::FORMAT_HDR:
|
||||
internalformat = GL_RGBA16F;
|
||||
textype = GL_FLOAT;
|
||||
break;
|
||||
case Texture::FORMAT_SRGB:
|
||||
internalformat = GL_SRGB_ALPHA;
|
||||
textype = GL_UNSIGNED_BYTE;
|
||||
break;
|
||||
case Texture::FORMAT_NORMAL:
|
||||
default:
|
||||
internalformat = GL_RGBA;
|
||||
textype = GL_UNSIGNED_BYTE;
|
||||
}
|
||||
GLenum internalformat = GL_RGBA;
|
||||
GLenum externalformat = GL_RGBA;
|
||||
GLenum textype = GL_UNSIGNED_BYTE;
|
||||
|
||||
convertFormat(format, internalformat, externalformat, textype);
|
||||
|
||||
// in ES2, the internalformat and format params of TexImage have to match.
|
||||
if (GLAD_ES_VERSION_2_0 && !GLAD_ES_VERSION_3_0)
|
||||
internalformat = externalformat;
|
||||
|
||||
while (glGetError() != GL_NO_ERROR)
|
||||
/* Clear the error buffer. */;
|
||||
|
||||
glTexImage2D(GL_TEXTURE_2D,
|
||||
0,
|
||||
internalformat,
|
||||
(GLint) internalformat,
|
||||
width, height,
|
||||
0,
|
||||
GL_RGBA,
|
||||
externalformat,
|
||||
textype,
|
||||
nullptr);
|
||||
|
||||
@@ -736,10 +731,13 @@ void Canvas::setupGrab()
|
||||
gl.matrices.projection.push(Matrix::ortho(0.0, width, 0.0, height));
|
||||
|
||||
// Make sure the correct sRGB setting is used when drawing to the canvas.
|
||||
if (format == FORMAT_SRGB)
|
||||
glEnable(GL_FRAMEBUFFER_SRGB);
|
||||
else if (screenHasSRGB)
|
||||
glDisable(GL_FRAMEBUFFER_SRGB);
|
||||
if (GLAD_VERSION_1_1 || GLAD_EXT_sRGB_write_control)
|
||||
{
|
||||
if (format == FORMAT_SRGB)
|
||||
glEnable(GL_FRAMEBUFFER_SRGB);
|
||||
else if (screenHasSRGB)
|
||||
glDisable(GL_FRAMEBUFFER_SRGB);
|
||||
}
|
||||
|
||||
if (fsaa_buffer != 0)
|
||||
fsaa_dirty = true;
|
||||
@@ -828,8 +826,11 @@ void Canvas::stopGrab(bool switchingToOtherCanvas)
|
||||
|
||||
if (switchingToOtherCanvas)
|
||||
{
|
||||
if (format == FORMAT_SRGB)
|
||||
glDisable(GL_FRAMEBUFFER_SRGB);
|
||||
if (GLAD_VERSION_1_1 || GLAD_EXT_sRGB_write_control)
|
||||
{
|
||||
if (format == FORMAT_SRGB)
|
||||
glDisable(GL_FRAMEBUFFER_SRGB);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -838,10 +839,13 @@ void Canvas::stopGrab(bool switchingToOtherCanvas)
|
||||
current = nullptr;
|
||||
gl.setViewport(systemViewport);
|
||||
|
||||
if (format == FORMAT_SRGB && !screenHasSRGB)
|
||||
glDisable(GL_FRAMEBUFFER_SRGB);
|
||||
else if (format != FORMAT_SRGB && screenHasSRGB)
|
||||
glEnable(GL_FRAMEBUFFER_SRGB);
|
||||
if (GLAD_VERSION_1_1 || GLAD_EXT_sRGB_write_control)
|
||||
{
|
||||
if (format == FORMAT_SRGB && !screenHasSRGB)
|
||||
glDisable(GL_FRAMEBUFFER_SRGB);
|
||||
else if (format != FORMAT_SRGB && screenHasSRGB)
|
||||
glEnable(GL_FRAMEBUFFER_SRGB);
|
||||
}
|
||||
}
|
||||
|
||||
gl.matrices.projection.pop();
|
||||
@@ -1007,41 +1011,231 @@ bool Canvas::resolveMSAA()
|
||||
return true;
|
||||
}
|
||||
|
||||
Canvas::Format Canvas::getSizedFormat(Canvas::Format format)
|
||||
{
|
||||
switch (format)
|
||||
{
|
||||
case FORMAT_NORMAL:
|
||||
// 32-bit render targets don't have guaranteed support on OpenGL ES 2.
|
||||
if (GLAD_ES_VERSION_2_0 && !(GLAD_ES_VERSION_3_0 || GLAD_OES_rgb8_rgba8 || GLAD_ARM_rgba8))
|
||||
return FORMAT_RGBA4;
|
||||
else
|
||||
return FORMAT_RGBA8;
|
||||
case FORMAT_HDR:
|
||||
return FORMAT_RGBA16F;
|
||||
default:
|
||||
return format;
|
||||
}
|
||||
}
|
||||
|
||||
void Canvas::convertFormat(Canvas::Format format, GLenum &internalformat, GLenum &externalformat, GLenum &type)
|
||||
{
|
||||
format = getSizedFormat(format);
|
||||
externalformat = GL_RGBA;
|
||||
|
||||
switch (format)
|
||||
{
|
||||
case FORMAT_RGBA8:
|
||||
default:
|
||||
internalformat = GL_RGBA8;
|
||||
type = GL_UNSIGNED_BYTE;
|
||||
break;
|
||||
case FORMAT_RGBA4:
|
||||
internalformat = GL_RGBA4;
|
||||
type = GL_UNSIGNED_SHORT_4_4_4_4;
|
||||
break;
|
||||
case FORMAT_RGB5A1:
|
||||
internalformat = GL_RGB5_A1;
|
||||
type = GL_UNSIGNED_SHORT_5_5_5_1;
|
||||
break;
|
||||
case FORMAT_RGB565:
|
||||
internalformat = GL_RGB565;
|
||||
externalformat = GL_RGB;
|
||||
type = GL_UNSIGNED_SHORT_5_6_5;
|
||||
break;
|
||||
case FORMAT_RGB10A2:
|
||||
internalformat = GL_RGB10_A2;
|
||||
type = GL_UNSIGNED_INT_2_10_10_10_REV;
|
||||
break;
|
||||
case FORMAT_RG11B10F:
|
||||
internalformat = GL_R11F_G11F_B10F;
|
||||
externalformat = GL_RGB;
|
||||
type = GL_UNSIGNED_INT_10F_11F_11F_REV;
|
||||
break;
|
||||
case FORMAT_RGBA16F:
|
||||
internalformat = GL_RGBA16F;
|
||||
if (GLAD_OES_texture_float)
|
||||
type = GL_HALF_FLOAT_OES;
|
||||
else if (GLAD_VERSION_1_1)
|
||||
type = GL_FLOAT;
|
||||
else
|
||||
type = GL_HALF_FLOAT;
|
||||
break;
|
||||
case FORMAT_RGBA32F:
|
||||
internalformat = GL_RGBA32F;
|
||||
type = GL_FLOAT;
|
||||
break;
|
||||
case FORMAT_SRGB:
|
||||
internalformat = GL_SRGB8_ALPHA8;
|
||||
type = GL_UNSIGNED_BYTE;
|
||||
if (GLAD_ES_VERSION_2_0)
|
||||
externalformat = GL_SRGB_ALPHA;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
bool Canvas::isSupported()
|
||||
{
|
||||
getStrategy();
|
||||
return (strategy != &strategyNone);
|
||||
}
|
||||
|
||||
bool Canvas::isHDRSupported()
|
||||
{
|
||||
return GLAD_VERSION_3_0 || (isSupported() && GLAD_ARB_texture_float);
|
||||
}
|
||||
|
||||
bool Canvas::isSRGBSupported()
|
||||
{
|
||||
if (GLAD_VERSION_3_0)
|
||||
return true;
|
||||
|
||||
if (!isSupported())
|
||||
return false;
|
||||
|
||||
return (GLAD_ARB_framebuffer_sRGB || GLAD_EXT_framebuffer_sRGB)
|
||||
&& GLAD_EXT_texture_sRGB;
|
||||
}
|
||||
|
||||
bool Canvas::isMultiCanvasSupported()
|
||||
{
|
||||
// system must support at least 4 simultanious active canvases.
|
||||
return gl.getMaxRenderTargets() >= 4;
|
||||
}
|
||||
|
||||
bool Canvas::supportedFormats[] = {false};
|
||||
bool Canvas::checkedFormats[] = {false};
|
||||
|
||||
bool Canvas::isFormatSupported(Canvas::Format format)
|
||||
{
|
||||
if (!isSupported())
|
||||
return false;
|
||||
|
||||
bool supported = true;
|
||||
format = getSizedFormat(format);
|
||||
|
||||
switch (format)
|
||||
{
|
||||
case FORMAT_RGBA8:
|
||||
if (GLAD_VERSION_1_1)
|
||||
supported = true;
|
||||
else
|
||||
supported = GLAD_ES_VERSION_3_0 || GLAD_OES_rgb8_rgba8 || GLAD_ARM_rgba8;
|
||||
break;
|
||||
case FORMAT_RGBA4:
|
||||
case FORMAT_RGB5A1:
|
||||
supported = true;
|
||||
break;
|
||||
case FORMAT_RGB565:
|
||||
supported = GLAD_ES_VERSION_2_0 || GLAD_VERSION_4_2 || GLAD_ARB_ES2_compatibility;
|
||||
break;
|
||||
case FORMAT_RGB10A2:
|
||||
if (GLAD_VERSION_1_1)
|
||||
supported = true;
|
||||
else
|
||||
supported = GLAD_ES_VERSION_3_0;
|
||||
break;
|
||||
case FORMAT_RG11B10F:
|
||||
if (GLAD_VERSION_1_1)
|
||||
supported = GLAD_VERSION_3_0 || GLAD_EXT_packed_float;
|
||||
else
|
||||
supported = GLAD_ES_VERSION_3_0 /*|| GLAD_NV_packed_float*/;
|
||||
break;
|
||||
case FORMAT_RGBA16F:
|
||||
if (GLAD_VERSION_1_1)
|
||||
supported = GLAD_VERSION_3_0 || GLAD_ARB_texture_float;
|
||||
else
|
||||
supported = GLAD_EXT_color_buffer_half_float && (GLAD_ES_VERSION_3_0 || GLAD_OES_texture_half_float);
|
||||
break;
|
||||
case FORMAT_RGBA32F:
|
||||
if (GLAD_VERSION_1_1)
|
||||
supported = GLAD_VERSION_3_0 || GLAD_ARB_texture_float;
|
||||
else
|
||||
supported = false; // GLAD_EXT_color_buffer_float && GLAD_ES_VERSION_3_0;
|
||||
break;
|
||||
case FORMAT_SRGB:
|
||||
if (GLAD_VERSION_1_1)
|
||||
supported = GLAD_VERSION_3_0 || ((GLAD_ARB_framebuffer_sRGB || GLAD_EXT_framebuffer_sRGB)
|
||||
&& (GLAD_VERSION_2_1 || GLAD_EXT_texture_sRGB));
|
||||
else
|
||||
supported = GLAD_ES_VERSION_3_0 || GLAD_EXT_sRGB;
|
||||
break;
|
||||
default:
|
||||
supported = false;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!supported)
|
||||
return false;
|
||||
|
||||
if (checkedFormats[format])
|
||||
return supportedFormats[format];
|
||||
|
||||
// Even though we might have the necessary OpenGL version or extension,
|
||||
// drivers are still allowed to throw FRAMEBUFFER_UNSUPPORTED when attaching
|
||||
// a texture to a FBO whose format the driver doesn't like. So we should
|
||||
// test with an actual FBO.
|
||||
|
||||
GLenum internalformat = GL_RGBA;
|
||||
GLenum externalformat = GL_RGBA;
|
||||
GLenum textype = GL_UNSIGNED_BYTE;
|
||||
convertFormat(format, internalformat, externalformat, textype);
|
||||
|
||||
if (GLAD_ES_VERSION_2_0 && !GLAD_ES_VERSION_3_0)
|
||||
internalformat = externalformat;
|
||||
|
||||
GLuint texture = 0;
|
||||
glGenTextures(1, &texture);
|
||||
gl.bindTexture(texture);
|
||||
|
||||
Texture::Filter f;
|
||||
f.min = f.mag = Texture::FILTER_NEAREST;
|
||||
gl.setTextureFilter(f);
|
||||
|
||||
Texture::Wrap w;
|
||||
gl.setTextureWrap(w);
|
||||
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, internalformat, 2, 2, 0, externalformat, textype, nullptr);
|
||||
|
||||
GLuint fbo = 0;
|
||||
supported = (strategy->createFBO(fbo, texture) == GL_FRAMEBUFFER_COMPLETE);
|
||||
strategy->deleteFBO(fbo, 0, 0);
|
||||
|
||||
gl.deleteTexture(texture);
|
||||
|
||||
// Cache the result so we don't do this for every isFormatSupported call.
|
||||
checkedFormats[format] = true;
|
||||
supportedFormats[format] = supported;
|
||||
|
||||
return supported;
|
||||
}
|
||||
|
||||
void Canvas::bindDefaultCanvas()
|
||||
{
|
||||
if (current != nullptr)
|
||||
current->stopGrab();
|
||||
}
|
||||
|
||||
bool Canvas::getConstant(const char *in, Format &out)
|
||||
{
|
||||
return formats.find(in, out);
|
||||
}
|
||||
|
||||
bool Canvas::getConstant(Format in, const char *&out)
|
||||
{
|
||||
return formats.find(in, out);
|
||||
}
|
||||
|
||||
StringMap<Canvas::Format, Canvas::FORMAT_MAX_ENUM>::Entry Canvas::formatEntries[] =
|
||||
{
|
||||
{"normal", Canvas::FORMAT_NORMAL},
|
||||
{"hdr", Canvas::FORMAT_HDR},
|
||||
{"rgba8", Canvas::FORMAT_RGBA8},
|
||||
{"rgba4", Canvas::FORMAT_RGBA4},
|
||||
{"rgb5a1", Canvas::FORMAT_RGB5A1},
|
||||
{"rgb565", Canvas::FORMAT_RGB565},
|
||||
{"rgb10a2", Canvas::FORMAT_RGB10A2},
|
||||
{"rg11b10f", Canvas::FORMAT_RG11B10F},
|
||||
{"rgba16f", Canvas::FORMAT_RGBA16F},
|
||||
{"rgba32f", Canvas::FORMAT_RGBA32F},
|
||||
{"srgb", Canvas::FORMAT_SRGB},
|
||||
};
|
||||
|
||||
StringMap<Canvas::Format, Canvas::FORMAT_MAX_ENUM> Canvas::formats(Canvas::formatEntries, sizeof(Canvas::formatEntries));
|
||||
|
||||
} // opengl
|
||||
} // graphics
|
||||
} // love
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
#include "image/Image.h"
|
||||
#include "image/ImageData.h"
|
||||
#include "common/Matrix.h"
|
||||
#include "common/StringMap.h"
|
||||
#include "Texture.h"
|
||||
#include "OpenGL.h"
|
||||
|
||||
@@ -39,7 +40,24 @@ class Canvas : public Texture
|
||||
{
|
||||
public:
|
||||
|
||||
Canvas(int width, int height, Texture::Format format = Texture::FORMAT_NORMAL, int fsaa = 0);
|
||||
// Different Canvas render target formats.
|
||||
enum Format
|
||||
{
|
||||
FORMAT_NORMAL, // Usually RGBA8 or a similar fallback. Always supported.
|
||||
FORMAT_HDR, // Usually RGBA16F. Not always supported.
|
||||
FORMAT_RGBA8, // RGBA with 8 bits per component.
|
||||
FORMAT_RGBA4, // RGBA with 4 bits per component.
|
||||
FORMAT_RGB5A1, // RGB with 5 bits per component, and A with 1 bit.
|
||||
FORMAT_RGB565, // RGB with 5, 6, and 5 bits each, respectively.
|
||||
FORMAT_RGB10A2, // RGB with 10 bits each, and A with 2 bits.
|
||||
FORMAT_RG11B10F, // Floating point [0, +inf]. RG with 11 FP bits each, and B with 10 FP bits.
|
||||
FORMAT_RGBA16F, // Floating point [-inf, +inf]. RGBA with 16 FP bits per component.
|
||||
FORMAT_RGBA32F, // Floating point [-inf, +inf]. RGBA with 32 FP bits per component.
|
||||
FORMAT_SRGB, // sRGB with 8 bits per component, plus 8 bit linear A.
|
||||
FORMAT_MAX_ENUM
|
||||
};
|
||||
|
||||
Canvas(int width, int height, Format format = FORMAT_NORMAL, int fsaa = 0);
|
||||
virtual ~Canvas();
|
||||
|
||||
// Implements Volatile.
|
||||
@@ -85,7 +103,7 @@ public:
|
||||
return status;
|
||||
}
|
||||
|
||||
inline Texture::Format getTextureFormat() const
|
||||
inline Format getTextureFormat() const
|
||||
{
|
||||
return format;
|
||||
}
|
||||
@@ -98,9 +116,8 @@ public:
|
||||
bool resolveMSAA();
|
||||
|
||||
static bool isSupported();
|
||||
static bool isHDRSupported();
|
||||
static bool isSRGBSupported();
|
||||
static bool isMultiCanvasSupported();
|
||||
static bool isFormatSupported(Format format);
|
||||
|
||||
static Canvas *current;
|
||||
static void bindDefaultCanvas();
|
||||
@@ -111,10 +128,16 @@ public:
|
||||
// Whether the main screen should have linear -> sRGB conversions enabled.
|
||||
static bool screenHasSRGB;
|
||||
|
||||
static bool getConstant(const char *in, Format &out);
|
||||
static bool getConstant(Format in, const char *&out);
|
||||
|
||||
private:
|
||||
|
||||
bool createFSAAFBO(GLenum internalformat);
|
||||
|
||||
static Format getSizedFormat(Format format);
|
||||
static void convertFormat(Format format, GLenum &internalformat, GLenum &externalformat, GLenum &type);
|
||||
|
||||
GLuint fbo;
|
||||
GLuint resolve_fbo;
|
||||
|
||||
@@ -134,6 +157,12 @@ private:
|
||||
void setupGrab();
|
||||
void drawv(const Matrix &t, const Vertex *v);
|
||||
|
||||
static bool supportedFormats[FORMAT_MAX_ENUM];
|
||||
static bool checkedFormats[FORMAT_MAX_ENUM];
|
||||
|
||||
static StringMap<Format, FORMAT_MAX_ENUM>::Entry formatEntries[];
|
||||
static StringMap<Format, FORMAT_MAX_ENUM> formats;
|
||||
|
||||
}; // Canvas
|
||||
|
||||
} // opengl
|
||||
|
||||
@@ -42,6 +42,7 @@ const int Font::TEXTURE_HEIGHTS[] = {128, 128, 256, 256, 512, 512, 1024};
|
||||
|
||||
Font::Font(love::font::Rasterizer *r, const Texture::Filter &filter)
|
||||
: rasterizer(r)
|
||||
, indexBuffer(nullptr)
|
||||
, height(r->getHeight())
|
||||
, lineHeight(1)
|
||||
, mSpacing(1)
|
||||
@@ -68,6 +69,8 @@ Font::Font(love::font::Rasterizer *r, const Texture::Filter &filter)
|
||||
textureWidth = TEXTURE_WIDTHS[textureSizeIndex];
|
||||
textureHeight = TEXTURE_HEIGHTS[textureSizeIndex];
|
||||
|
||||
indexBuffer = new VertexIndex(20);
|
||||
|
||||
love::font::GlyphData *gd = nullptr;
|
||||
|
||||
try
|
||||
@@ -93,6 +96,7 @@ Font::Font(love::font::Rasterizer *r, const Texture::Filter &filter)
|
||||
|
||||
Font::~Font()
|
||||
{
|
||||
delete indexBuffer;
|
||||
rasterizer->release();
|
||||
unloadVolatile();
|
||||
}
|
||||
@@ -368,28 +372,17 @@ void Font::print(const std::string &text, float x, float y, float extra_spacing,
|
||||
// second (using the struct's < operator).
|
||||
std::sort(glyphinfolist.begin(), glyphinfolist.end());
|
||||
|
||||
std::vector<uint16> indices;
|
||||
|
||||
int indicescount = 0;
|
||||
int maxvertices = 0;
|
||||
for (auto it = glyphinfolist.begin(); it != glyphinfolist.end(); ++it)
|
||||
maxvertices = std::max(maxvertices, it->vertexcount);
|
||||
|
||||
// If the index buffer is too small for the number of glyphs we're going to
|
||||
// draw, we need to make a new one that has the correct size.
|
||||
if ((size_t) maxvertices / 4 > indexBuffer->getSize())
|
||||
{
|
||||
if ((it->vertexcount / 4) * 6 > indicescount)
|
||||
indicescount = (it->vertexcount / 4) * 6;
|
||||
}
|
||||
|
||||
indices.reserve(indicescount);
|
||||
|
||||
for (int i = 0; i < indicescount / 6; i++)
|
||||
{
|
||||
// First triangle.
|
||||
indices.push_back(i * 4 + 0);
|
||||
indices.push_back(i * 4 + 1);
|
||||
indices.push_back(i * 4 + 2);
|
||||
|
||||
// Second triangle.
|
||||
indices.push_back(i * 4 + 0);
|
||||
indices.push_back(i * 4 + 2);
|
||||
indices.push_back(i * 4 + 3);
|
||||
VertexIndex *newIndexBuffer = new VertexIndex(maxvertices / 4);
|
||||
delete indexBuffer;
|
||||
indexBuffer = newIndexBuffer;
|
||||
}
|
||||
|
||||
gl.matrices.transform.push(gl.matrices.transform.top());
|
||||
@@ -403,16 +396,36 @@ void Font::print(const std::string &text, float x, float y, float extra_spacing,
|
||||
|
||||
gl.prepareDraw();
|
||||
|
||||
VertexBuffer::Bind index_bind(*indexBuffer->getVertexBuffer());
|
||||
GLenum elemtype = indexBuffer->getType();
|
||||
const GLvoid *elemoffset = indexBuffer->getPointer(0);
|
||||
|
||||
// Optimization: we can take these calls out of the loop if we have support.
|
||||
if (GLAD_VERSION_3_2 || GLAD_ARB_draw_elements_base_vertex)
|
||||
{
|
||||
gl.setVertexAttribArray(OpenGL::ATTRIB_POS, 2, GL_FLOAT, sizeof(GlyphVertex), &glyphverts[0].x);
|
||||
gl.setVertexAttribArray(OpenGL::ATTRIB_TEXCOORD, 2, GL_FLOAT, sizeof(GlyphVertex), &glyphverts[0].s);
|
||||
}
|
||||
|
||||
// We need to draw a new vertex array for every section of the string which
|
||||
// uses a different texture than the previous section.
|
||||
for (auto it = glyphinfolist.begin(); it != glyphinfolist.end(); ++it)
|
||||
{
|
||||
gl.bindTexture(it->texture);
|
||||
|
||||
gl.setVertexAttribArray(OpenGL::ATTRIB_POS, 2, GL_FLOAT, sizeof(GlyphVertex), (GLvoid *)&glyphverts[it->startvertex].x);
|
||||
gl.setVertexAttribArray(OpenGL::ATTRIB_TEXCOORD, 2, GL_FLOAT, sizeof(GlyphVertex), (GLvoid *)&glyphverts[it->startvertex].s);
|
||||
if (GLAD_VERSION_3_2 || GLAD_ARB_draw_elements_base_vertex)
|
||||
{
|
||||
// Optimization: setting a base vertex is faster than redoing the
|
||||
// setVertexAttribArray calls before each draw.
|
||||
glDrawElementsBaseVertex(GL_TRIANGLES, (it->vertexcount / 4) * 6, elemtype, elemoffset, it->startvertex);
|
||||
}
|
||||
else
|
||||
{
|
||||
gl.setVertexAttribArray(OpenGL::ATTRIB_POS, 2, GL_FLOAT, sizeof(GlyphVertex), &glyphverts[it->startvertex].x);
|
||||
gl.setVertexAttribArray(OpenGL::ATTRIB_TEXCOORD, 2, GL_FLOAT, sizeof(GlyphVertex), &glyphverts[it->startvertex].s);
|
||||
|
||||
glDrawElements(GL_TRIANGLES, (it->vertexcount / 4) * 6, GL_UNSIGNED_SHORT, &indices[0]);
|
||||
glDrawElements(GL_TRIANGLES, (it->vertexcount / 4) * 6, elemtype, elemoffset);
|
||||
}
|
||||
}
|
||||
|
||||
gl.disableVertexAttribArray(OpenGL::ATTRIB_POS);
|
||||
|
||||
@@ -31,6 +31,7 @@
|
||||
#include "font/Rasterizer.h"
|
||||
#include "graphics/Texture.h"
|
||||
#include "graphics/Volatile.h"
|
||||
#include "VertexBuffer.h"
|
||||
|
||||
#include "OpenGL.h"
|
||||
|
||||
@@ -185,6 +186,8 @@ private:
|
||||
|
||||
love::font::Rasterizer *rasterizer;
|
||||
|
||||
VertexIndex *indexBuffer;
|
||||
|
||||
int height;
|
||||
float lineHeight;
|
||||
float mSpacing; // modifies the spacing by multiplying it with this value
|
||||
|
||||
@@ -52,6 +52,7 @@ Graphics::Graphics()
|
||||
, width(0)
|
||||
, height(0)
|
||||
, created(false)
|
||||
, active(true)
|
||||
, activeStencil(false)
|
||||
, savedState()
|
||||
{
|
||||
@@ -72,7 +73,10 @@ Graphics::~Graphics()
|
||||
currentFont->release();
|
||||
|
||||
if (Shader::defaultShader)
|
||||
{
|
||||
Shader::defaultShader->release();
|
||||
Shader::defaultShader = nullptr;
|
||||
}
|
||||
|
||||
currentWindow->release();
|
||||
}
|
||||
@@ -235,12 +239,16 @@ bool Graphics::setMode(int width, int height, bool &sRGB)
|
||||
}
|
||||
|
||||
// Set whether drawing converts input from linear -> sRGB colorspace.
|
||||
if (GLAD_VERSION_3_0 || GLAD_ARB_framebuffer_sRGB || GLAD_EXT_framebuffer_sRGB)
|
||||
if (GLAD_VERSION_3_0 || GLAD_ARB_framebuffer_sRGB || GLAD_EXT_framebuffer_sRGB
|
||||
|| (GLAD_ES_VERSION_3_0 || GLAD_EXT_sRGB))
|
||||
{
|
||||
if (sRGB)
|
||||
glEnable(GL_FRAMEBUFFER_SRGB);
|
||||
else
|
||||
glDisable(GL_FRAMEBUFFER_SRGB);
|
||||
if (GLAD_VERSION_1_1 || GLAD_EXT_sRGB_write_control)
|
||||
{
|
||||
if (sRGB)
|
||||
glEnable(GL_FRAMEBUFFER_SRGB);
|
||||
else
|
||||
glDisable(GL_FRAMEBUFFER_SRGB);
|
||||
}
|
||||
}
|
||||
else
|
||||
sRGB = false;
|
||||
@@ -282,6 +290,23 @@ void Graphics::unSetMode()
|
||||
created = false;
|
||||
}
|
||||
|
||||
void Graphics::setActive(bool active)
|
||||
{
|
||||
// Make sure all pending OpenGL commands have fully executed before
|
||||
// returning, if we're going from active to inactive.
|
||||
if (isCreated() && this->active && !active)
|
||||
glFinish();
|
||||
|
||||
this->active = active;
|
||||
}
|
||||
|
||||
bool Graphics::isActive() const
|
||||
{
|
||||
// The graphics module is only completely 'active' if there's a window, a
|
||||
// context, and the active variable is set.
|
||||
return active && isCreated() && currentWindow && currentWindow->isCreated();
|
||||
}
|
||||
|
||||
static void APIENTRY debugCB(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei /*len*/, const GLchar *msg, const GLvoid* /*usr*/)
|
||||
{
|
||||
// Human-readable strings for the debug info.
|
||||
@@ -364,6 +389,9 @@ void Graphics::clear()
|
||||
|
||||
void Graphics::present()
|
||||
{
|
||||
if (!isActive())
|
||||
return;
|
||||
|
||||
// Make sure we don't have a canvas active.
|
||||
Canvas *c = Canvas::current;
|
||||
Canvas::bindDefaultCanvas();
|
||||
@@ -463,7 +491,7 @@ void Graphics::discardStencil()
|
||||
activeStencil = false;
|
||||
}
|
||||
|
||||
Image *Graphics::newImage(love::image::ImageData *data, Texture::Format format)
|
||||
Image *Graphics::newImage(love::image::ImageData *data, Image::Format format)
|
||||
{
|
||||
// Create the image.
|
||||
Image *image = new Image(data, format);
|
||||
@@ -490,7 +518,7 @@ Image *Graphics::newImage(love::image::ImageData *data, Texture::Format format)
|
||||
return image;
|
||||
}
|
||||
|
||||
Image *Graphics::newImage(love::image::CompressedData *cdata, Texture::Format format)
|
||||
Image *Graphics::newImage(love::image::CompressedData *cdata, Image::Format format)
|
||||
{
|
||||
// Create the image.
|
||||
Image *image = new Image(cdata, format);
|
||||
@@ -537,13 +565,14 @@ ParticleSystem *Graphics::newParticleSystem(Texture *texture, int size)
|
||||
return new ParticleSystem(texture, size);
|
||||
}
|
||||
|
||||
Canvas *Graphics::newCanvas(int width, int height, Texture::Format format, int fsaa)
|
||||
Canvas *Graphics::newCanvas(int width, int height, Canvas::Format format, int fsaa)
|
||||
{
|
||||
if (format == Texture::FORMAT_HDR && !Canvas::isHDRSupported())
|
||||
throw Exception("HDR Canvases are not supported by your OpenGL implementation");
|
||||
|
||||
if (format == Texture::FORMAT_SRGB && !Canvas::isSRGBSupported())
|
||||
throw Exception("sRGB Canvases are not supported by your OpenGL implementation");
|
||||
if (!Canvas::isFormatSupported(format))
|
||||
{
|
||||
const char *fstr = "rgba8";
|
||||
Canvas::getConstant(format, fstr);
|
||||
throw love::Exception("The %s canvas format is not supported by your OpenGL implementation.", fstr);
|
||||
}
|
||||
|
||||
if (width > gl.getMaxTextureSize())
|
||||
throw Exception("Cannot create canvas: width of %d pixels is too large for this system.", width);
|
||||
@@ -594,8 +623,8 @@ Canvas *Graphics::newCanvas(int width, int height, Texture::Format format, int f
|
||||
}
|
||||
|
||||
canvas->release();
|
||||
throw Exception(error_string.str().c_str());
|
||||
return NULL; // never reached
|
||||
throw Exception("%s", error_string.str().c_str());
|
||||
return nullptr; // never reached
|
||||
}
|
||||
|
||||
Shader *Graphics::newShader(const Shader::ShaderSources &sources)
|
||||
@@ -972,7 +1001,24 @@ void Graphics::circle(DrawMode mode, float x, float y, float radius, int points)
|
||||
float angle_shift = (two_pi / points);
|
||||
float phi = .0f;
|
||||
|
||||
float *coords = new float[2 * (points + 1)];
|
||||
float *coords = nullptr;
|
||||
int extrapoints = 1;
|
||||
|
||||
// Fill mode will use a triangle fan internally, so we want the "hub" of the
|
||||
// fan (its first vertex) to be the midpoint of the circle.
|
||||
if (mode == DRAW_FILL)
|
||||
{
|
||||
extrapoints = 2;
|
||||
coords = new float[2 * (points + extrapoints)];
|
||||
|
||||
coords[0] = x;
|
||||
coords[1] = y;
|
||||
|
||||
coords += 2;
|
||||
}
|
||||
else
|
||||
coords = new float[2 * (points + extrapoints)];
|
||||
|
||||
for (int i = 0; i < points; ++i, phi += angle_shift)
|
||||
{
|
||||
coords[2*i] = x + radius * cosf(phi);
|
||||
@@ -982,7 +1028,10 @@ void Graphics::circle(DrawMode mode, float x, float y, float radius, int points)
|
||||
coords[2*points] = coords[0];
|
||||
coords[2*points+1] = coords[1];
|
||||
|
||||
polygon(mode, coords, (points + 1) * 2);
|
||||
if (mode == DRAW_FILL)
|
||||
coords -= 2;
|
||||
|
||||
polygon(mode, coords, 2 * (points + extrapoints));
|
||||
|
||||
delete[] coords;
|
||||
}
|
||||
@@ -1059,7 +1108,7 @@ void Graphics::polygon(DrawMode mode, const float *coords, size_t count)
|
||||
gl.enableVertexAttribArray(OpenGL::ATTRIB_POS);
|
||||
gl.setVertexAttribArray(OpenGL::ATTRIB_POS, 2, GL_FLOAT, 0, (GLvoid *) coords);
|
||||
|
||||
glDrawArrays(GL_TRIANGLE_FAN, 0, count/2-1); // opengl will close the polygon for us
|
||||
glDrawArrays(GL_TRIANGLE_FAN, 0, count / 2);
|
||||
|
||||
gl.disableVertexAttribArray(OpenGL::ATTRIB_POS);
|
||||
}
|
||||
|
||||
@@ -118,6 +118,9 @@ public:
|
||||
virtual bool setMode(int width, int height, bool &sRGB);
|
||||
virtual void unSetMode();
|
||||
|
||||
virtual void setActive(bool active);
|
||||
virtual bool isActive() const;
|
||||
|
||||
void setDebug(bool enable);
|
||||
|
||||
/**
|
||||
@@ -194,8 +197,8 @@ public:
|
||||
/**
|
||||
* Creates an Image object with padding and/or optimization.
|
||||
**/
|
||||
Image *newImage(love::image::ImageData *data, Texture::Format format = Texture::FORMAT_NORMAL);
|
||||
Image *newImage(love::image::CompressedData *cdata, Texture::Format format = Texture::FORMAT_NORMAL);
|
||||
Image *newImage(love::image::ImageData *data, Image::Format format = Image::FORMAT_NORMAL);
|
||||
Image *newImage(love::image::CompressedData *cdata, Image::Format format = Image::FORMAT_NORMAL);
|
||||
|
||||
Quad *newQuad(Quad::Viewport v, float sw, float sh);
|
||||
|
||||
@@ -208,7 +211,7 @@ public:
|
||||
|
||||
ParticleSystem *newParticleSystem(Texture *texture, int size);
|
||||
|
||||
Canvas *newCanvas(int width, int height, Texture::Format format = Texture::FORMAT_NORMAL, int fsaa = 0);
|
||||
Canvas *newCanvas(int width, int height, Canvas::Format format = Canvas::FORMAT_NORMAL, int fsaa = 0);
|
||||
|
||||
Shader *newShader(const Shader::ShaderSources &sources);
|
||||
|
||||
@@ -480,6 +483,7 @@ private:
|
||||
int width;
|
||||
int height;
|
||||
bool created;
|
||||
bool active;
|
||||
|
||||
bool activeStencil;
|
||||
|
||||
|
||||
@@ -36,7 +36,7 @@ float Image::maxMipmapSharpness = 0.0f;
|
||||
Texture::FilterMode Image::defaultMipmapFilter = Texture::FILTER_NONE;
|
||||
float Image::defaultMipmapSharpness = 0.0f;
|
||||
|
||||
Image::Image(love::image::ImageData *data, Texture::Format format)
|
||||
Image::Image(love::image::ImageData *data, Format format)
|
||||
: data(data)
|
||||
, cdata(nullptr)
|
||||
, paddedWidth(width)
|
||||
@@ -55,7 +55,7 @@ Image::Image(love::image::ImageData *data, Texture::Format format)
|
||||
preload();
|
||||
}
|
||||
|
||||
Image::Image(love::image::CompressedData *cdata, Texture::Format format)
|
||||
Image::Image(love::image::CompressedData *cdata, Format format)
|
||||
: data(nullptr)
|
||||
, cdata(cdata)
|
||||
, paddedWidth(width)
|
||||
@@ -504,7 +504,7 @@ bool Image::refresh()
|
||||
return true;
|
||||
}
|
||||
|
||||
Texture::Format Image::getFormat() const
|
||||
Image::Format Image::getFormat() const
|
||||
{
|
||||
return format;
|
||||
}
|
||||
@@ -602,6 +602,20 @@ GLenum Image::getCompressedFormat(image::CompressedData::Format cformat) const
|
||||
return GL_COMPRESSED_RG_RGTC2;
|
||||
case image::CompressedData::FORMAT_BC5s:
|
||||
return GL_COMPRESSED_SIGNED_RG_RGTC2;
|
||||
case image::CompressedData::FORMAT_ETC1:
|
||||
// The ETC2 format can load ETC1 textures.
|
||||
if (GLAD_VERSION_4_3 || GLAD_ES_VERSION_3_0 || GLAD_ARB_ES3_compatibility)
|
||||
return GL_COMPRESSED_RGB8_ETC2;
|
||||
else
|
||||
return GL_ETC1_RGB8_OES;
|
||||
case image::CompressedData::FORMAT_PVR1_RGB2:
|
||||
return GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG;
|
||||
case image::CompressedData::FORMAT_PVR1_RGB4:
|
||||
return GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG;
|
||||
case image::CompressedData::FORMAT_PVR1_RGBA2:
|
||||
return GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG;
|
||||
case image::CompressedData::FORMAT_PVR1_RGBA4:
|
||||
return GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG;
|
||||
default:
|
||||
if (srgb)
|
||||
return GL_SRGB_ALPHA;
|
||||
@@ -635,14 +649,24 @@ bool Image::hasCompressedTextureSupport(image::CompressedData::Format format)
|
||||
switch (format)
|
||||
{
|
||||
case image::CompressedData::FORMAT_DXT1:
|
||||
return GLAD_EXT_texture_compression_s3tc || GLAD_EXT_texture_compression_dxt1;
|
||||
case image::CompressedData::FORMAT_DXT3:
|
||||
return GLAD_EXT_texture_compression_s3tc || GLAD_ANGLE_texture_compression_dxt3;
|
||||
case image::CompressedData::FORMAT_DXT5:
|
||||
return GLAD_EXT_texture_compression_s3tc;
|
||||
return GLAD_EXT_texture_compression_s3tc || GLAD_ANGLE_texture_compression_dxt5;
|
||||
case image::CompressedData::FORMAT_BC4:
|
||||
case image::CompressedData::FORMAT_BC4s:
|
||||
case image::CompressedData::FORMAT_BC5:
|
||||
case image::CompressedData::FORMAT_BC5s:
|
||||
return (GLAD_VERSION_3_0 || GLAD_ARB_texture_compression_rgtc || GLAD_EXT_texture_compression_rgtc);
|
||||
case image::CompressedData::FORMAT_ETC1:
|
||||
// ETC2 support guarantees ETC1 support as well.
|
||||
return GLAD_VERSION_4_3 || GLAD_ES_VERSION_3_0 || GLAD_ARB_ES3_compatibility || GLAD_OES_compressed_ETC1_RGB8_texture;
|
||||
case image::CompressedData::FORMAT_PVR1_RGB2:
|
||||
case image::CompressedData::FORMAT_PVR1_RGB4:
|
||||
case image::CompressedData::FORMAT_PVR1_RGBA2:
|
||||
case image::CompressedData::FORMAT_PVR1_RGBA4:
|
||||
return GLAD_IMG_texture_compression_pvrtc;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -655,6 +679,24 @@ bool Image::hasSRGBSupport()
|
||||
return GLAD_VERSION_2_1 || GLAD_EXT_texture_sRGB || GLAD_EXT_sRGB;
|
||||
}
|
||||
|
||||
bool Image::getConstant(const char *in, Format &out)
|
||||
{
|
||||
return formats.find(in, out);
|
||||
}
|
||||
|
||||
bool Image::getConstant(Format in, const char *&out)
|
||||
{
|
||||
return formats.find(in, out);
|
||||
}
|
||||
|
||||
StringMap<Image::Format, Image::FORMAT_MAX_ENUM>::Entry Image::formatEntries[] =
|
||||
{
|
||||
{"normal", Image::FORMAT_NORMAL},
|
||||
{"srgb", Image::FORMAT_SRGB},
|
||||
};
|
||||
|
||||
StringMap<Image::Format, Image::FORMAT_MAX_ENUM> Image::formats(Image::formatEntries, sizeof(Image::formatEntries));
|
||||
|
||||
} // opengl
|
||||
} // graphics
|
||||
} // love
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
#include "common/config.h"
|
||||
#include "common/Matrix.h"
|
||||
#include "common/Vector.h"
|
||||
#include "common/StringMap.h"
|
||||
#include "common/math.h"
|
||||
#include "image/ImageData.h"
|
||||
#include "image/CompressedData.h"
|
||||
@@ -50,20 +51,27 @@ class Image : public Texture
|
||||
{
|
||||
public:
|
||||
|
||||
enum Format
|
||||
{
|
||||
FORMAT_NORMAL,
|
||||
FORMAT_SRGB,
|
||||
FORMAT_MAX_ENUM
|
||||
};
|
||||
|
||||
/**
|
||||
* Creates a new Image. Not that anything is ready to use
|
||||
* before load is called.
|
||||
*
|
||||
* @param data The data from which to load the image.
|
||||
**/
|
||||
Image(love::image::ImageData *data, Texture::Format format = Texture::FORMAT_NORMAL);
|
||||
Image(love::image::ImageData *data, Format format = FORMAT_NORMAL);
|
||||
|
||||
/**
|
||||
* Creates a new Image with compressed image data.
|
||||
*
|
||||
* @param cdata The compressed data from which to load the image.
|
||||
**/
|
||||
Image(love::image::CompressedData *cdata, Texture::Format format = Texture::FORMAT_NORMAL);
|
||||
Image(love::image::CompressedData *cdata, Format format = FORMAT_NORMAL);
|
||||
|
||||
/**
|
||||
* Destructor. Deletes the hardware texture and other resources.
|
||||
@@ -120,7 +128,7 @@ public:
|
||||
**/
|
||||
bool refresh();
|
||||
|
||||
Texture::Format getFormat() const;
|
||||
Format getFormat() const;
|
||||
|
||||
static void setDefaultMipmapSharpness(float sharpness);
|
||||
static float getDefaultMipmapSharpness();
|
||||
@@ -136,6 +144,9 @@ public:
|
||||
|
||||
static bool hasSRGBSupport();
|
||||
|
||||
static bool getConstant(const char *in, Format &out);
|
||||
static bool getConstant(Format in, const char *&out);
|
||||
|
||||
private:
|
||||
|
||||
void uploadDefaultTexture();
|
||||
@@ -165,8 +176,8 @@ private:
|
||||
// Whether this Image is using a compressed texture.
|
||||
bool compressed;
|
||||
|
||||
// The format to interpret the texture's data as.
|
||||
Texture::Format format;
|
||||
// The format to interpret the image's data as.
|
||||
Format format;
|
||||
|
||||
// True if the image wasn't able to be properly created and it had to fall
|
||||
// back to a default texture.
|
||||
@@ -188,6 +199,9 @@ private:
|
||||
|
||||
GLenum getCompressedFormat(image::CompressedData::Format cformat) const;
|
||||
|
||||
static StringMap<Format, FORMAT_MAX_ENUM>::Entry formatEntries[];
|
||||
static StringMap<Format, FORMAT_MAX_ENUM> formats;
|
||||
|
||||
}; // Image
|
||||
|
||||
} // opengl
|
||||
|
||||
@@ -160,6 +160,7 @@ void OpenGL::initVendor()
|
||||
}
|
||||
|
||||
// http://feedback.wildfiregames.com/report/opengl/feature/GL_VENDOR
|
||||
// http://stackoverflow.com/questions/2093594/opengl-extensions-available-on-different-android-devices
|
||||
if (strstr(vstr, "ATI Technologies"))
|
||||
vendor = VENDOR_ATI_AMD;
|
||||
else if (strstr(vstr, "NVIDIA"))
|
||||
@@ -172,6 +173,16 @@ void OpenGL::initVendor()
|
||||
vendor = VENDOR_APPLE;
|
||||
else if (strstr(vstr, "Microsoft"))
|
||||
vendor = VENDOR_MICROSOFT;
|
||||
else if (strstr(vstr, "Imagination"))
|
||||
vendor = VENDOR_IMGTEC;
|
||||
else if (strstr(vstr, "ARM"))
|
||||
vendor = VENDOR_ARM;
|
||||
else if (strstr(vstr, "Qualcomm"))
|
||||
vendor = VENDOR_QUALCOMM;
|
||||
else if (strstr(vstr, "Broadcom"))
|
||||
vendor = VENDOR_BROADCOM;
|
||||
else if (strstr(vstr, "Vivante"))
|
||||
vendor = VENDOR_VIVANTE;
|
||||
else
|
||||
vendor = VENDOR_UNKNOWN;
|
||||
}
|
||||
|
||||
@@ -66,8 +66,13 @@ public:
|
||||
VENDOR_NVIDIA,
|
||||
VENDOR_INTEL,
|
||||
VENDOR_MESA_SOFT, // Software renderer.
|
||||
VENDOR_APPLE, // Software renderer.
|
||||
VENDOR_APPLE, // Software renderer (or Apple A7 chips and newer.)
|
||||
VENDOR_MICROSOFT, // Software renderer.
|
||||
VENDOR_IMGTEC,
|
||||
VENDOR_ARM,
|
||||
VENDOR_QUALCOMM,
|
||||
VENDOR_BROADCOM,
|
||||
VENDOR_VIVANTE,
|
||||
VENDOR_UNKNOWN
|
||||
};
|
||||
|
||||
|
||||
@@ -101,10 +101,9 @@ Shader::~Shader()
|
||||
detach();
|
||||
|
||||
for (auto it = boundRetainables.begin(); it != boundRetainables.end(); ++it)
|
||||
{
|
||||
it->second->release();
|
||||
boundRetainables.erase(it);
|
||||
}
|
||||
|
||||
boundRetainables.clear();
|
||||
|
||||
unloadVolatile();
|
||||
}
|
||||
|
||||
@@ -189,10 +189,18 @@ void VBO::unmap()
|
||||
is_bound = true;
|
||||
}
|
||||
|
||||
// "orphan" current buffer to avoid implicit synchronisation on the GPU:
|
||||
// http://www.seas.upenn.edu/~pcozzi/OpenGLInsights/OpenGLInsights-AsynchronousBufferTransfers.pdf
|
||||
glBufferData(getTarget(), (GLsizeiptr) getSize(), NULL, getUsage());
|
||||
glBufferData(getTarget(), (GLsizeiptr) getSize(), memory_map, getUsage());
|
||||
if (getUsage() == GL_STATIC_DRAW)
|
||||
{
|
||||
// Upload the mapped data to the buffer.
|
||||
glBufferSubData(getTarget(), 0, (GLsizeiptr) getSize(), memory_map);
|
||||
}
|
||||
else
|
||||
{
|
||||
// "orphan" current buffer to avoid implicit synchronisation on the GPU:
|
||||
// http://www.seas.upenn.edu/~pcozzi/OpenGLInsights/OpenGLInsights-AsynchronousBufferTransfers.pdf
|
||||
glBufferData(getTarget(), (GLsizeiptr) getSize(), NULL, getUsage());
|
||||
glBufferData(getTarget(), (GLsizeiptr) getSize(), memory_map, getUsage());
|
||||
}
|
||||
|
||||
is_mapped = false;
|
||||
}
|
||||
|
||||
@@ -113,10 +113,10 @@ int w_Canvas_clear(lua_State *L)
|
||||
int w_Canvas_getFormat(lua_State *L)
|
||||
{
|
||||
Canvas *canvas = luax_checkcanvas(L, 1);
|
||||
Texture::Format format = canvas->getTextureFormat();
|
||||
Canvas::Format format = canvas->getTextureFormat();
|
||||
const char *str;
|
||||
if (!Texture::getConstant(format, str))
|
||||
return luaL_error(L, "Unknown texture format.");
|
||||
if (!Canvas::getConstant(format, str))
|
||||
return luaL_error(L, "Unknown Canvas format.");
|
||||
|
||||
lua_pushstring(L, str);
|
||||
return 1;
|
||||
|
||||
@@ -60,6 +60,12 @@ int w_isCreated(lua_State *L)
|
||||
return 1;
|
||||
}
|
||||
|
||||
int w_isActive(lua_State *L)
|
||||
{
|
||||
luax_pushboolean(L, instance->isActive());
|
||||
return 1;
|
||||
}
|
||||
|
||||
int w_getWidth(lua_State *L)
|
||||
{
|
||||
lua_pushinteger(L, instance->getWidth());
|
||||
@@ -155,14 +161,11 @@ int w_newImage(lua_State *L)
|
||||
love::image::ImageData *data = nullptr;
|
||||
love::image::CompressedData *cdata = nullptr;
|
||||
|
||||
Texture::Format format = Texture::FORMAT_NORMAL;
|
||||
Image::Format format = Image::FORMAT_NORMAL;
|
||||
const char *fstr = lua_isnoneornil(L, 2) ? nullptr : luaL_checkstring(L, 2);
|
||||
|
||||
if (fstr != nullptr && !Texture::getConstant(fstr, format))
|
||||
return luaL_error(L, "Invalid texture format: %s", fstr);
|
||||
|
||||
if (format == Texture::FORMAT_HDR) // For now...
|
||||
return luaL_error(L, "HDR images are not supported.");
|
||||
if (fstr != nullptr && !Image::getConstant(fstr, format))
|
||||
return luaL_error(L, "Invalid Image format: %s", fstr);
|
||||
|
||||
// Convert to FileData, if necessary.
|
||||
if (lua_isstring(L, 1) || luax_istype(L, 1, FILESYSTEM_FILE_T))
|
||||
@@ -334,9 +337,9 @@ int w_newCanvas(lua_State *L)
|
||||
const char *str = luaL_optstring(L, 3, "normal");
|
||||
int fsaa = luaL_optint(L, 4, 0);
|
||||
|
||||
Texture::Format format;
|
||||
if (!Texture::getConstant(str, format))
|
||||
return luaL_error(L, "Invalid texture format: %s", str);
|
||||
Canvas::Format format;
|
||||
if (!Canvas::getConstant(str, format))
|
||||
return luaL_error(L, "Invalid Canvas format: %s", str);
|
||||
|
||||
Canvas *canvas = nullptr;
|
||||
EXCEPT_GUARD(canvas = instance->newCanvas(width, height, format, fsaa);)
|
||||
@@ -1015,7 +1018,7 @@ int w_isSupported(lua_State *L)
|
||||
supported = false;
|
||||
break;
|
||||
case Graphics::SUPPORT_HDR_CANVAS:
|
||||
if (!Canvas::isHDRSupported())
|
||||
if (!Canvas::isFormatSupported(Canvas::FORMAT_HDR))
|
||||
supported = false;
|
||||
break;
|
||||
case Graphics::SUPPORT_MULTI_CANVAS:
|
||||
@@ -1046,12 +1049,20 @@ int w_isSupported(lua_State *L)
|
||||
if (!Image::hasCompressedTextureSupport(image::CompressedData::FORMAT_BC5))
|
||||
supported = false;
|
||||
break;
|
||||
case Graphics::SUPPORT_ETC1:
|
||||
if (!Image::hasCompressedTextureSupport(image::CompressedData::FORMAT_ETC1))
|
||||
supported = false;
|
||||
break;
|
||||
case Graphics::SUPPORT_PVRTC1:
|
||||
if (!Image::hasCompressedTextureSupport(image::CompressedData::FORMAT_PVR1_RGBA4))
|
||||
supported = false;
|
||||
break;
|
||||
case Graphics::SUPPORT_INSTANCING:
|
||||
if (!(GLAD_ARB_draw_instanced || (GLAD_ES_VERSION_2_0 && GLAD_EXT_draw_instanced)))
|
||||
supported = false;
|
||||
break;
|
||||
case Graphics::SUPPORT_SRGB:
|
||||
if (!Canvas::isSRGBSupported())
|
||||
if (!Canvas::isFormatSupported(Canvas::FORMAT_SRGB))
|
||||
supported = false;
|
||||
break;
|
||||
default:
|
||||
@@ -1064,6 +1075,18 @@ int w_isSupported(lua_State *L)
|
||||
return 1;
|
||||
}
|
||||
|
||||
int w_hasCanvasFormat(lua_State *L)
|
||||
{
|
||||
const char *str = luaL_checkstring(L, 1);
|
||||
Canvas::Format format;
|
||||
|
||||
if (!Canvas::getConstant(str, format))
|
||||
return luaL_error(L, "Invalid canvas format: %s", str);
|
||||
|
||||
luax_pushboolean(L, Canvas::isFormatSupported(format));
|
||||
return 1;
|
||||
}
|
||||
|
||||
int w_getRendererInfo(lua_State *L)
|
||||
{
|
||||
std::string name, version, vendor, device;
|
||||
@@ -1441,6 +1464,7 @@ static const luaL_Reg functions[] =
|
||||
{ "_setDefaultShaderCode", w_setDefaultShaderCode },
|
||||
|
||||
{ "isSupported", w_isSupported },
|
||||
{ "hasCanvasFormat", w_hasCanvasFormat },
|
||||
{ "getRendererInfo", w_getRendererInfo },
|
||||
{ "getSystemLimit", w_getSystemLimit },
|
||||
|
||||
@@ -1450,6 +1474,7 @@ static const luaL_Reg functions[] =
|
||||
{ "printf", w_printf },
|
||||
|
||||
{ "isCreated", w_isCreated },
|
||||
{ "isActive", w_isActive },
|
||||
{ "getWidth", w_getWidth },
|
||||
{ "getHeight", w_getHeight },
|
||||
{ "getDimensions", w_getDimensions },
|
||||
|
||||
@@ -43,6 +43,7 @@ int w_reset(lua_State *L);
|
||||
int w_clear(lua_State *L);
|
||||
int w_present(lua_State *L);
|
||||
int w_isCreated(lua_State *L);
|
||||
int w_isActive(lua_State *L);
|
||||
int w_getWidth(lua_State *L);
|
||||
int w_getHeight(lua_State *L);
|
||||
int w_getDimensions(lua_State *L);
|
||||
@@ -94,6 +95,7 @@ int w_setShader(lua_State *L);
|
||||
int w_getShader(lua_State *L);
|
||||
int w_setDefaultShaderCode(lua_State *L);
|
||||
int w_isSupported(lua_State *L);
|
||||
int w_hasCanvasFormat(lua_State *L);
|
||||
int w_getRendererInfo(lua_State *L);
|
||||
int w_getSystemLimit(lua_State *L);
|
||||
int w_draw(lua_State *L);
|
||||
|
||||
Reference in New Issue
Block a user