Some work towards OpenGL ES 2+ support for love 0.10.

--HG--
branch : minor
This commit is contained in:
Alex Szpakowski
2015-01-19 23:32:16 -04:00
parent 1253e3aae1
commit 1124612c1f
12 changed files with 181 additions and 43 deletions
+53 -11
View File
@@ -96,7 +96,7 @@ struct FramebufferStrategy
virtual void setAttachments() {}
};
struct FramebufferStrategyGL3 : public FramebufferStrategy
struct FramebufferStrategyCorePacked : public FramebufferStrategy
{
virtual GLenum createFBO(GLuint &framebuffer, GLuint texture)
{
@@ -218,6 +218,37 @@ struct FramebufferStrategyGL3 : public FramebufferStrategy
}
};
struct FramebufferStrategyCore : public FramebufferStrategyCorePacked
{
virtual bool createStencil(int width, int height, int samples, GLuint &stencil)
{
// create stencil buffer
glDeleteRenderbuffers(1, &stencil);
glGenRenderbuffers(1, &stencil);
glBindRenderbuffer(GL_RENDERBUFFER, stencil);
if (samples > 1)
glRenderbufferStorageMultisample(GL_RENDERBUFFER, samples, GL_STENCIL_INDEX8, width, height);
else
glRenderbufferStorage(GL_RENDERBUFFER, GL_STENCIL_INDEX8, width, height);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT,
GL_RENDERBUFFER, stencil);
glBindRenderbuffer(GL_RENDERBUFFER, 0);
// check status
if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
{
glDeleteRenderbuffers(1, &stencil);
stencil = 0;
return false;
}
return true;
}
};
struct FramebufferStrategyPackedEXT : public FramebufferStrategy
{
virtual GLenum createFBO(GLuint &framebuffer, GLuint texture)
@@ -393,11 +424,9 @@ struct FramebufferStrategyEXT : public FramebufferStrategyPackedEXT
FramebufferStrategy *strategy = nullptr;
FramebufferStrategy strategyNone;
FramebufferStrategyGL3 strategyGL3;
FramebufferStrategyCorePacked strategyCorePacked;
FramebufferStrategyCore strategyCore;
FramebufferStrategyPackedEXT strategyPackedEXT;
FramebufferStrategyEXT strategyEXT;
Canvas *Canvas::current = nullptr;
@@ -411,7 +440,9 @@ static void getStrategy()
if (!strategy)
{
if (GLAD_VERSION_3_0 || GLAD_ARB_framebuffer_object)
strategy = &strategyGL3;
strategy = &strategyCorePacked;
else if (GLAD_ES_VERSION_2_0)
strategy = &strategyCore;
else if (GLAD_EXT_framebuffer_object && GLAD_EXT_packed_depth_stencil)
strategy = &strategyPackedEXT;
else if (GLAD_EXT_framebuffer_object && strategyEXT.isSupported())
@@ -783,6 +814,17 @@ void Canvas::stopGrab(bool switchingToOtherCanvas)
if (current != this)
return;
if (depth_stencil != 0)
{
GLenum attachments[] = {GL_STENCIL_ATTACHMENT, GL_DEPTH_ATTACHMENT};
// Hint for the driver that it doesn't need to save these buffers.
if (GLAD_ES_VERSION_3_0)
glInvalidateFramebuffer(GL_FRAMEBUFFER, 2, attachments);
else if (GLAD_EXT_discard_framebuffer)
glDiscardFramebufferEXT(GL_FRAMEBUFFER, 2, attachments);
}
gl.matrices.projection.pop_back();
if (switchingToOtherCanvas)
@@ -793,7 +835,7 @@ void Canvas::stopGrab(bool switchingToOtherCanvas)
else
{
// bind system framebuffer.
strategy->bindFBO(0);
strategy->bindFBO(gl.getDefaultFBO());
current = nullptr;
gl.setViewport(systemViewport);
@@ -879,7 +921,7 @@ bool Canvas::checkCreateStencil()
if (current && current != this)
strategy->bindFBO(current->fbo);
else if (!current)
strategy->bindFBO(0);
strategy->bindFBO(gl.getDefaultFBO());
return success;
}
@@ -905,7 +947,7 @@ love::image::ImageData *Canvas::getImageData(love::image::Image *image)
if (current)
strategy->bindFBO(current->fbo);
else
strategy->bindFBO(0);
strategy->bindFBO(gl.getDefaultFBO());
// The new ImageData now owns the pixel data, so we don't delete it here.
love::image::ImageData *img = image->newImageData(width, height, (void *)pixels, true);
@@ -932,7 +974,7 @@ void Canvas::getPixel(unsigned char* pixel_rgba, int x, int y)
if (current && current != this)
strategy->bindFBO(current->fbo);
else if (!current)
strategy->bindFBO(0);
strategy->bindFBO(gl.getDefaultFBO());
}
bool Canvas::resolveMSAA()
@@ -1088,7 +1130,7 @@ bool Canvas::isFormatSupported(Canvas::Format format)
supported = true;
break;
case FORMAT_RGB565:
supported = GLAD_VERSION_4_2 || GLAD_ARB_ES2_compatibility;
supported = GLAD_ES_VERSION_2_0 || GLAD_VERSION_4_2 || GLAD_ARB_ES2_compatibility;
break;
case FORMAT_RG11B10F:
supported = GLAD_VERSION_3_0 || GLAD_EXT_packed_float;
+1 -1
View File
@@ -158,7 +158,7 @@ void Font::createTexture()
{
// Clean up before throwing.
gl.deleteTexture(t);
gl.bindTexture(0);
gl.bindTexture(gl.getDefaultTexture());
textures.pop_back();
throw love::Exception("Could not create font texture!");
+42 -5
View File
@@ -210,7 +210,7 @@ bool Graphics::setMode(int width, int height, bool &sRGB)
gl.initContext();
// Does the system meet LOVE's minimum requirements for graphics?
if (!(GLAD_VERSION_2_0 && Shader::isSupported() && Canvas::isSupported())
if (!(GLAD_ES_VERSION_2_0 || (GLAD_VERSION_2_0 && Shader::isSupported() && Canvas::isSupported()))
&& !displayedMinReqWarning)
{
love::window::Window::MessageBoxType type = love::window::Window::MESSAGEBOX_ERROR;
@@ -331,6 +331,10 @@ void Graphics::setDebug(bool enable)
if (!(GLAD_VERSION_4_3 || GLAD_KHR_debug || GLAD_ARB_debug_output))
return;
// TODO: We don't support GL_KHR_debug in GLES yet.
if (GLAD_ES_VERSION_2_0)
return;
// Ugly hack to reduce code duplication.
if (GLAD_ARB_debug_output && !(GLAD_VERSION_4_3 || GLAD_KHR_debug))
{
@@ -396,8 +400,33 @@ void Graphics::clear(ClearType type)
void Graphics::present()
{
// Make sure we don't have a canvas active.
std::vector<Object::StrongRef<Canvas>> canvases = states.back().canvases;
setCanvas();
if (GLAD_ES_VERSION_3_0 || GLAD_EXT_discard_framebuffer)
{
GLenum attachments[] = {GL_STENCIL, GL_DEPTH};
if (gl.getDefaultFBO() != 0)
{
// A non-zero FBO needs different attachment enums.
attachments[0] = GL_STENCIL_ATTACHMENT;
attachments[1] = GL_DEPTH_ATTACHMENT;
}
// Hint for the driver that it doesn't need to save these buffers.
if (GLAD_ES_VERSION_3_0)
glInvalidateFramebuffer(GL_FRAMEBUFFER, 2, attachments);
else if (GLAD_EXT_discard_framebuffer)
glDiscardFramebufferEXT(GL_FRAMEBUFFER, 2, attachments);
}
currentWindow->swapBuffers();
// Restore the currently active canvas, if there is one.
setCanvas(canvases);
// Reset the per-frame stat counts.
gl.stats.drawCalls = 0;
Canvas::switchCount = 0;
@@ -922,6 +951,10 @@ float Graphics::getPointSize() const
void Graphics::setWireframe(bool enable)
{
// Not supported in OpenGL ES.
if (GLAD_ES_VERSION_2_0)
return;
glPolygonMode(GL_FRONT_AND_BACK, enable ? GL_LINE : GL_FILL);
states.back().wireframe = enable;
}
@@ -1007,7 +1040,7 @@ void Graphics::printf(const std::string &str, float x, float y, float wrap, Alig
void Graphics::point(float x, float y)
{
gl.prepareDraw();
gl.bindTexture(0);
gl.bindTexture(gl.getDefaultTexture());
glBegin(GL_POINTS);
glVertex2f(x, y);
glEnd();
@@ -1105,7 +1138,7 @@ void Graphics::arc(DrawMode mode, float x, float y, float radius, float angle1,
else
{
gl.prepareDraw();
gl.bindTexture(0);
gl.bindTexture(gl.getDefaultTexture());
glEnableVertexAttribArray(ATTRIB_POS);
glVertexAttribPointer(ATTRIB_POS, 2, GL_FLOAT, GL_FALSE, 0, coords);
gl.drawArrays(GL_TRIANGLE_FAN, 0, points + 2);
@@ -1129,7 +1162,7 @@ void Graphics::polygon(DrawMode mode, const float *coords, size_t count)
else
{
gl.prepareDraw();
gl.bindTexture(0);
gl.bindTexture(gl.getDefaultTexture());
glEnableVertexAttribArray(ATTRIB_POS);
glVertexAttribPointer(ATTRIB_POS, 2, GL_FLOAT, GL_FALSE, 0, coords);
gl.drawArrays(GL_POLYGON, 0, count/2-1); // opengl will close the polygon for us
@@ -1207,7 +1240,11 @@ love::image::ImageData *Graphics::newScreenshot(love::image::Image *image, bool
Graphics::RendererInfo Graphics::getRendererInfo() const
{
RendererInfo info;
info.name = "OpenGL";
if (GLAD_ES_VERSION_2_0)
info.name = "OpenGL ES";
else
info.name = "OpenGL";
const char *str = (const char *) glGetString(GL_VERSION);
if (str)
+11 -6
View File
@@ -163,6 +163,10 @@ void Image::setWrap(const Texture::Wrap &w)
void Image::setMipmapSharpness(float sharpness)
{
// OpenGL ES doesn't support LOD bias via glTexParameter.
if (!GLAD_VERSION_1_4)
return;
// LOD bias has the range (-maxbias, maxbias)
mipmapSharpness = std::min(std::max(sharpness, -maxMipmapSharpness + 0.01f), maxMipmapSharpness - 0.01f);
@@ -225,7 +229,7 @@ void Image::generateMipmaps()
// The GL_GENERATE_MIPMAP texparameter is set in loadVolatile if we don't
// have support for glGenerateMipmap.
if (flags.mipmaps && !isCompressed() &&
(GLAD_VERSION_3_0 || GLAD_ARB_framebuffer_object))
(GLAD_ES_VERSION_2_0 || GLAD_VERSION_3_0 || GLAD_ARB_framebuffer_object))
{
// Driver bug: http://www.opengl.org/wiki/Common_Mistakes#Automatic_mipmap_generation
#if defined(LOVE_WINDOWS) || defined(LOVE_LINUX)
@@ -243,7 +247,8 @@ void Image::loadTextureFromCompressedData()
int count = flags.mipmaps ? cdata->getMipmapCount() : 1;
// We have to inform OpenGL if the image doesn't have all mipmap levels.
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, count - 1);
if (GLAD_ES_VERSION_3_0 || GLAD_VERSION_1_0)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, count - 1);
for (int i = 0; i < count; i++)
{
@@ -283,7 +288,7 @@ bool Image::loadVolatile()
throw love::Exception("cannot create image: format is not supported on this system.");
}
if (maxMipmapSharpness == 0.0f)
if (maxMipmapSharpness == 0.0f && GLAD_VERSION_1_4)
glGetFloatv(GL_MAX_TEXTURE_LOD_BIAS, &maxMipmapSharpness);
glGenTextures(1, &texture);
@@ -300,11 +305,11 @@ bool Image::loadVolatile()
return true;
}
if (!flags.mipmaps)
if (!flags.mipmaps && (GLAD_ES_VERSION_3_0 || GLAD_VERSION_1_0))
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
if (flags.mipmaps && !isCompressed() &&
!(GLAD_VERSION_3_0 || GLAD_ARB_framebuffer_object))
!(GLAD_ES_VERSION_2_0 || GLAD_VERSION_3_0 || GLAD_ARB_framebuffer_object))
{
// Auto-generate mipmaps every time the texture is modified, if
// glGenerateMipmap isn't supported.
@@ -414,7 +419,7 @@ void Image::loadDefaultTexture()
GLubyte px[] = {0xFF,0xFF,0xFF,0xFF, 0xC0,0xC0,0xC0,0xFF,
0xC0,0xC0,0xC0,0xFF, 0xFF,0xFF,0xFF,0xFF};
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, px);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, px);
}
void Image::drawv(const Matrix &t, const Vertex *v)
+1 -1
View File
@@ -320,7 +320,7 @@ void Mesh::draw(float x, float y, float angle, float sx, float sy, float ox, flo
if (texture.get())
texture->predraw();
else
gl.bindTexture(0);
gl.bindTexture(gl.getDefaultTexture());
Matrix m;
m.setTransformation(x, y, angle, sx, sy, ox, oy, kx, ky);
+37 -6
View File
@@ -119,6 +119,8 @@ void OpenGL::setupContext()
glActiveTexture(curgltextureunit);
glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, (GLint *) &state.defaultFBO);
BlendState blend = {GL_ONE, GL_ONE, GL_ZERO, GL_ZERO, GL_FUNC_ADD};
setBlendState(blend);
@@ -142,6 +144,9 @@ void OpenGL::deInitContext()
if (!contextInitialized)
return;
glDeleteTextures(1, &state.defaultTexture);
state.defaultTexture = 0;
contextInitialized = false;
}
@@ -155,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"))
@@ -167,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;
}
@@ -185,11 +201,14 @@ void OpenGL::initMaxValues()
glGetIntegerv(GL_MAX_TEXTURE_SIZE, &maxTextureSize);
int maxattachments = 0;
glGetIntegerv(GL_MAX_COLOR_ATTACHMENTS, &maxattachments);
int maxattachments = 1;
int maxdrawbuffers = 1;
int maxdrawbuffers = 0;
glGetIntegerv(GL_MAX_DRAW_BUFFERS, &maxdrawbuffers);
if (GLAD_ES_VERSION_3_0 || GLAD_VERSION_2_0)
{
glGetIntegerv(GL_MAX_COLOR_ATTACHMENTS, &maxattachments);
glGetIntegerv(GL_MAX_DRAW_BUFFERS, &maxdrawbuffers);
}
maxRenderTargets = std::min(maxattachments, maxdrawbuffers);
}
@@ -211,7 +230,9 @@ void OpenGL::createDefaultTexture()
// shaders for untextured primitives vs images.
GLuint curtexture = state.textureUnits[state.curTextureUnit];
bindTexture(0);
glGenTextures(1, &state.defaultTexture);
bindTexture(state.defaultTexture);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
@@ -220,7 +241,7 @@ void OpenGL::createDefaultTexture()
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
GLubyte pix = 255;
glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE8, 1, 1, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, &pix);
glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, 1, 1, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, &pix);
bindTexture(curtexture);
}
@@ -429,6 +450,16 @@ OpenGL::BlendState OpenGL::getBlendState() const
return state.blend;
}
GLuint OpenGL::getDefaultFBO() const
{
return state.defaultFBO;
}
GLuint OpenGL::getDefaultTexture() const
{
return state.defaultTexture;
}
void OpenGL::setTextureUnit(int textureunit)
{
if (textureunit < 0 || (size_t) textureunit >= state.textureUnits.size())
+21 -1
View File
@@ -27,7 +27,8 @@
#include "common/Matrix.h"
// GLAD
#include "libraries/glad/gladfuncs.hpp"
//#include "libraries/glad/gladfuncs.hpp"
#include <gladf/gladfuncs.hpp>
// C++
#include <vector>
@@ -79,6 +80,11 @@ public:
VENDOR_MESA_SOFT, // Software renderer.
VENDOR_APPLE, // Software renderer.
VENDOR_MICROSOFT, // Software renderer.
VENDOR_IMGTEC,
VENDOR_ARM,
VENDOR_QUALCOMM,
VENDOR_BROADCOM,
VENDOR_VIVANTE,
VENDOR_UNKNOWN
};
@@ -242,6 +248,17 @@ public:
**/
BlendState getBlendState() const;
/**
* This will usually be 0 (system drawable), but some platforms require a
* non-zero FBO for rendering.
**/
GLuint getDefaultFBO() const;
/**
* Gets the ID for love's default texture (used for "untextured" primitives.)
**/
GLuint getDefaultTexture() const;
/**
* Helper for setting the active texture unit.
*
@@ -336,6 +353,9 @@ private:
Viewport viewport;
Viewport scissor;
GLuint defaultFBO;
GLuint defaultTexture;
BlendState blend;
// The last ID value used for pseudo-instancing.
@@ -64,6 +64,7 @@ ParticleSystem::ParticleSystem(Texture *texture, uint32 size)
, pHead(nullptr)
, pTail(nullptr)
, particleVerts(nullptr)
, ibo(1)
, texture(texture)
, active(true)
, insertMode(INSERT_MODE_TOP)
@@ -112,6 +113,7 @@ ParticleSystem::ParticleSystem(const ParticleSystem &p)
, pHead(nullptr)
, pTail(nullptr)
, particleVerts(nullptr)
, ibo(p.ibo)
, texture(p.texture)
, active(p.active)
, insertMode(p.insertMode)
@@ -196,6 +198,7 @@ void ParticleSystem::setBufferSize(uint32 size)
{
if (size == 0 || size > MAX_PARTICLES)
throw love::Exception("Invalid buffer size");
ibo = VertexIndex(size);
deleteBuffers();
createBuffers(size);
reset();
@@ -874,6 +877,7 @@ void ParticleSystem::draw(float x, float y, float angle, float sx, float sy, flo
}
texture->predraw();
gl.prepareDraw();
glEnableVertexAttribArray(ATTRIB_COLOR);
glEnableVertexAttribArray(ATTRIB_POS);
@@ -883,8 +887,10 @@ void ParticleSystem::draw(float x, float y, float angle, float sx, float sy, flo
glVertexAttribPointer(ATTRIB_POS, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), &particleVerts[0].x);
glVertexAttribPointer(ATTRIB_TEXCOORD, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), &particleVerts[0].s);
gl.prepareDraw();
gl.drawArrays(GL_QUADS, 0, pCount * 4);
{
VertexBuffer::Bind ibo_bind(*ibo.getVertexBuffer());
gl.drawElements(GL_TRIANGLES, ibo.getIndexCount(pCount), ibo.getType(), ibo.getPointer(0));
}
glDisableVertexAttribArray(ATTRIB_TEXCOORD);
glDisableVertexAttribArray(ATTRIB_POS);
@@ -29,6 +29,7 @@
#include "graphics/Color.h"
#include "graphics/Quad.h"
#include "Texture.h"
#include "VertexBuffer.h"
// STL
#include <vector>
@@ -575,6 +576,9 @@ protected:
// array of transformed vertex data for all particles, for drawing
Vertex *particleVerts;
// Vertex index buffer.
VertexIndex ibo;
// The texture to be drawn.
Object::StrongRef<Texture> texture;
+1 -1
View File
@@ -330,7 +330,7 @@ void Polyline::draw()
gl.prepareDraw();
// draw the core line
gl.bindTexture(0);
gl.bindTexture(gl.getDefaultTexture());
glEnableVertexAttribArray(ATTRIB_POS);
glVertexAttribPointer(ATTRIB_POS, 2, GL_FLOAT, GL_FALSE, 0, vertices);
gl.drawArrays(draw_mode, 0, vertex_count);
+1 -4
View File
@@ -129,9 +129,6 @@ GLuint Shader::compileCode(ShaderStage stage, const std::string &code)
break;
}
// clear existing errors
while (glGetError() != GL_NO_ERROR);
GLuint shaderid = glCreateShader(glstage);
if (shaderid == 0)
@@ -719,7 +716,7 @@ std::string Shader::getGLSLVersion()
bool Shader::isSupported()
{
return getGLSLVersion() >= "1.2";
return GLAD_ES_VERSION_2_0 || (getGLSLVersion() >= "1.2");
}
int Shader::getUniformTypeSize(GLenum type) const
+1 -5
View File
@@ -187,14 +187,10 @@ bool VertexBuffer::load(bool restore)
// Copy the old buffer only if 'restore' was requested.
const GLvoid *src = restore ? memory_map : nullptr;
while (GL_NO_ERROR != glGetError())
/* clear error messages */;
// Note that if 'src' is '0', no data will be copied.
glBufferData(getTarget(), (GLsizeiptr) getSize(), src, getUsage());
GLenum err = glGetError();
return (GL_NO_ERROR == err);
return true;
}
void VertexBuffer::unload()