diff --git a/changes.txt b/changes.txt index 322b55a06..7b188a8bc 100644 --- a/changes.txt +++ b/changes.txt @@ -9,6 +9,7 @@ LOVE 0.9.2 [Baby Inspector] * Added love.graphics.getCompressedImageFormats. * Added ParticleSystem:setQuads. * Added SpriteBatch:flush. + * Added love.graphics.getStats. * Added optional duration argument to Joystick:setVibration. * Added love.joystick.loadGamepadMappings and love.joystick.saveGamepadMappings. * Added Joint:setUserData and Joint:getUserData. @@ -18,6 +19,7 @@ LOVE 0.9.2 [Baby Inspector] * Added love.window.minimize. * Added love.window.showMessageBox. * Added love.filesystem.isSymlink, love.filesystem.setSymlinksEnabled, and love.filesystem.areSymlinksEnabled. + * Added 'refreshrate' field to the table returned by love.window.getMode. * Deprecated SpriteBatch:bind and SpriteBatch:unbind. * Deprecated all uses of the name 'FSAA' in favor of 'MSAA'. @@ -38,6 +40,8 @@ LOVE 0.9.2 [Baby Inspector] * Fixed the default error handler text size when highdpi mode is enabled on a Retina monitor. * Fixed love.window.setMode to fall back to the largest available mode if a width or height greater than the largest supported is specified and fullscreen=true. * Fixed the state of wireframe mode when love.window.setMode is called. + * Fixed Canvas:getPixel to error if the coordinates are not within the Canvas' size. + * Fixed detection of compressed textures to work regardless of the file's extension. * Renamed all cases of FSAA to MSAA. The FSAA names still exist for backward-compatibility. diff --git a/src/modules/graphics/Graphics.cpp b/src/modules/graphics/Graphics.cpp index 412838c52..1216be632 100644 --- a/src/modules/graphics/Graphics.cpp +++ b/src/modules/graphics/Graphics.cpp @@ -119,6 +119,16 @@ bool Graphics::getConstant(ClearType in, const char *&out) return clearTypes.find(in, out); } +bool Graphics::getConstant(const char *in, StatType &out) +{ + return statTypes.find(in, out); +} + +bool Graphics::getConstant(StatType in, const char *&out) +{ + return statTypes.find(in, out); +} + StringMap::Entry Graphics::drawModeEntries[] = { { "line", Graphics::DRAW_LINE }, @@ -201,5 +211,17 @@ StringMap::Entry Graphics::clearT StringMap Graphics::clearTypes(Graphics::clearTypeEntries, sizeof(Graphics::clearTypeEntries)); +StringMap::Entry Graphics::statTypeEntries[] = +{ + {"drawcalls", Graphics::STAT_DRAW_CALLS}, + {"canvasswitches", Graphics::STAT_CANVAS_SWITCHES}, + {"canvases", Graphics::STAT_CANVASES}, + {"images", Graphics::STAT_IMAGES}, + {"fonts", Graphics::STAT_FONTS}, + {"texturememory", Graphics::STAT_TEXTURE_MEMORY}, +}; + +StringMap Graphics::statTypes(Graphics::statTypeEntries, sizeof(Graphics::statTypeEntries)); + } // graphics } // love diff --git a/src/modules/graphics/Graphics.h b/src/modules/graphics/Graphics.h index 038190f38..bf9d7a20a 100644 --- a/src/modules/graphics/Graphics.h +++ b/src/modules/graphics/Graphics.h @@ -110,6 +110,17 @@ public: CLEAR_MAX_ENUM }; + enum StatType + { + STAT_DRAW_CALLS, + STAT_CANVAS_SWITCHES, + STAT_CANVASES, + STAT_IMAGES, + STAT_FONTS, + STAT_TEXTURE_MEMORY, + STAT_MAX_ENUM + }; + struct RendererInfo { std::string name; @@ -118,6 +129,16 @@ public: std::string device; }; + struct Stats + { + int drawCalls; + int canvasSwitches; + int canvases; + int images; + int fonts; + size_t textureMemory; + }; + virtual ~Graphics(); // Implements Module. @@ -168,6 +189,9 @@ public: static bool getConstant(const char *in, ClearType &out); static bool getConstant(ClearType in, const char *&out); + static bool getConstant(const char *in, StatType &out); + static bool getConstant(StatType in, const char *&out); + private: static StringMap::Entry drawModeEntries[]; @@ -197,6 +221,9 @@ private: static StringMap::Entry clearTypeEntries[]; static StringMap clearTypes; + static StringMap::Entry statTypeEntries[]; + static StringMap statTypes; + }; // Graphics } // graphics diff --git a/src/modules/graphics/opengl/Canvas.cpp b/src/modules/graphics/opengl/Canvas.cpp index 29cee90fe..d857f7e82 100644 --- a/src/modules/graphics/opengl/Canvas.cpp +++ b/src/modules/graphics/opengl/Canvas.cpp @@ -185,6 +185,7 @@ struct FramebufferStrategyGL3 : public FramebufferStrategy virtual void bindFBO(GLuint framebuffer) { glBindFramebuffer(GL_FRAMEBUFFER, framebuffer); + ++Canvas::switchCount; } virtual void setAttachments() @@ -311,6 +312,7 @@ struct FramebufferStrategyPackedEXT : public FramebufferStrategy virtual void bindFBO(GLuint framebuffer) { glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, framebuffer); + ++Canvas::switchCount; } virtual void setAttachments() @@ -401,6 +403,8 @@ FramebufferStrategyEXT strategyEXT; Canvas *Canvas::current = nullptr; OpenGL::Viewport Canvas::systemViewport = OpenGL::Viewport(); bool Canvas::screenHasSRGB = false; +int Canvas::switchCount = 0; +int Canvas::canvasCount = 0; static void getStrategy() { @@ -426,6 +430,7 @@ Canvas::Canvas(int width, int height, Format format, int msaa) , format(format) , msaa_samples(msaa) , msaa_dirty(false) + , texture_memory(0) { this->width = width; this->height = height; @@ -456,10 +461,14 @@ Canvas::Canvas(int width, int height, Format format, int msaa) getStrategy(); loadVolatile(); + + ++canvasCount; } Canvas::~Canvas() { + --canvasCount; + // reset framebuffer if still using this one if (current == this) stopGrab(); @@ -575,6 +584,14 @@ bool Canvas::loadVolatile() msaa_dirty = (msaa_buffer != 0); + size_t prevmemsize = texture_memory; + + texture_memory = (getFormatBitsPerPixel(format) * width * height) / 8; + if (msaa_buffer != 0) + texture_memory += (texture_memory * msaa_samples); + + gl.updateTextureMemorySize(prevmemsize, texture_memory); + return true; } @@ -589,6 +606,9 @@ void Canvas::unloadVolatile() resolve_fbo = msaa_buffer = 0; attachedCanvases.clear(); + + gl.updateTextureMemorySize(texture_memory, 0); + texture_memory = 0; } void Canvas::drawv(const Matrix &t, const Vertex *v) @@ -605,7 +625,7 @@ void Canvas::drawv(const Matrix &t, const Vertex *v) glTexCoordPointer(2, GL_FLOAT, sizeof(Vertex), (GLvoid *)&v[0].s); gl.prepareDraw(); - glDrawArrays(GL_QUADS, 0, 4); + gl.drawArrays(GL_QUADS, 0, 4); glDisableClientState(GL_TEXTURE_COORD_ARRAY); glDisableClientState(GL_VERTEX_ARRAY); @@ -1015,6 +1035,27 @@ void Canvas::convertFormat(Canvas::Format format, GLenum &internalformat, GLenum } } +size_t Canvas::getFormatBitsPerPixel(Format format) +{ + switch (getSizedFormat(format)) + { + case FORMAT_RGBA8: + case FORMAT_RGB10A2: + case FORMAT_RG11B10F: + case FORMAT_SRGB: + default: + return 32; + case FORMAT_RGBA4: + case FORMAT_RGB5A1: + case FORMAT_RGB565: + return 16; + case FORMAT_RGBA16F: + return 64; + case FORMAT_RGBA32F: + return 128; + } +} + bool Canvas::isSupported() { getStrategy(); diff --git a/src/modules/graphics/opengl/Canvas.h b/src/modules/graphics/opengl/Canvas.h index a0fd6f1a1..ac2000560 100644 --- a/src/modules/graphics/opengl/Canvas.h +++ b/src/modules/graphics/opengl/Canvas.h @@ -26,6 +26,7 @@ #include "image/ImageData.h" #include "common/Matrix.h" #include "common/StringMap.h" +#include "common/int.h" #include "Texture.h" #include "OpenGL.h" @@ -127,6 +128,9 @@ public: // Whether the main screen should have linear -> sRGB conversions enabled. static bool screenHasSRGB; + static int switchCount; + static int canvasCount; + static bool getConstant(const char *in, Format &out); static bool getConstant(Format in, const char *&out); @@ -136,6 +140,7 @@ private: static Format getSizedFormat(Format format); static void convertFormat(Format format, GLenum &internalformat, GLenum &externalformat, GLenum &type); + static size_t getFormatBitsPerPixel(Format format); GLuint fbo; GLuint resolve_fbo; @@ -153,6 +158,8 @@ private: int msaa_samples; bool msaa_dirty; + size_t texture_memory; + void setupGrab(); void drawv(const Matrix &t, const Vertex *v); diff --git a/src/modules/graphics/opengl/Font.cpp b/src/modules/graphics/opengl/Font.cpp index a0a62571d..159d523b1 100644 --- a/src/modules/graphics/opengl/Font.cpp +++ b/src/modules/graphics/opengl/Font.cpp @@ -37,6 +37,8 @@ namespace graphics namespace opengl { +int Font::fontCount = 0; + const int Font::TEXTURE_WIDTHS[] = {128, 256, 256, 512, 512, 1024, 1024}; const int Font::TEXTURE_HEIGHTS[] = {128, 128, 256, 256, 512, 512, 1024}; @@ -47,6 +49,7 @@ Font::Font(love::font::Rasterizer *r, const Texture::Filter &filter) , mSpacing(1) , filter(filter) , useSpacesAsTab(false) + , textureMemorySize(0) { this->filter.mipmap = Texture::FILTER_NONE; @@ -87,11 +90,15 @@ Font::Font(love::font::Rasterizer *r, const Texture::Filter &filter) } delete gd; + + ++fontCount; } Font::~Font() { unloadVolatile(); + + --fontCount; } bool Font::initializeTexture(GLenum format) @@ -169,6 +176,11 @@ void Font::createTexture() &emptyData[0]); setFilter(filter); + + size_t prevmemsize = textureMemorySize; + + textureMemorySize += emptyData.size(); + gl.updateTextureMemorySize(prevmemsize, textureMemorySize); } Font::Glyph *Font::addGlyph(uint32 glyph) @@ -385,7 +397,7 @@ void Font::print(const std::string &text, float x, float y, float extra_spacing, for (it = glyphinfolist.begin(); it != glyphinfolist.end(); ++it) { gl.bindTexture(it->texture); - glDrawArrays(GL_QUADS, it->startvertex, it->vertexcount); + gl.drawArrays(GL_QUADS, it->startvertex, it->vertexcount); } glDisableClientState(GL_TEXTURE_COORD_ARRAY); @@ -564,6 +576,9 @@ void Font::unloadVolatile() iter++; } textures.clear(); + + gl.updateTextureMemorySize(textureMemorySize, 0); + textureMemorySize = 0; } int Font::getAscent() const diff --git a/src/modules/graphics/opengl/Font.h b/src/modules/graphics/opengl/Font.h index 2ed3b931a..cbdd8d418 100644 --- a/src/modules/graphics/opengl/Font.h +++ b/src/modules/graphics/opengl/Font.h @@ -138,6 +138,8 @@ public: bool hasGlyph(uint32 glyph) const; bool hasGlyphs(const std::string &text) const; + static int fontCount; + private: enum FontType @@ -207,6 +209,8 @@ private: bool useSpacesAsTab; + size_t textureMemorySize; + static const int NUM_TEXTURE_SIZES = 7; static const int TEXTURE_WIDTHS[NUM_TEXTURE_SIZES]; static const int TEXTURE_HEIGHTS[NUM_TEXTURE_SIZES]; diff --git a/src/modules/graphics/opengl/Graphics.cpp b/src/modules/graphics/opengl/Graphics.cpp index e414fe783..6d023b443 100644 --- a/src/modules/graphics/opengl/Graphics.cpp +++ b/src/modules/graphics/opengl/Graphics.cpp @@ -381,6 +381,10 @@ void Graphics::clear(ClearType type) void Graphics::present() { currentWindow->swapBuffers(); + + // Reset the per-frame stat counts. + gl.stats.drawCalls = 0; + Canvas::switchCount = 0; } int Graphics::getWidth() const @@ -981,6 +985,8 @@ void Graphics::point(float x, float y) glBegin(GL_POINTS); glVertex2f(x, y); glEnd(); + + ++gl.stats.drawCalls; } void Graphics::polyline(const float *coords, size_t count) @@ -1076,7 +1082,7 @@ void Graphics::arc(DrawMode mode, float x, float y, float radius, float angle1, gl.bindTexture(0); glEnableClientState(GL_VERTEX_ARRAY); glVertexPointer(2, GL_FLOAT, 0, (const GLvoid *) coords); - glDrawArrays(GL_TRIANGLE_FAN, 0, points + 2); + gl.drawArrays(GL_TRIANGLE_FAN, 0, points + 2); glDisableClientState(GL_VERTEX_ARRAY); } @@ -1100,7 +1106,7 @@ void Graphics::polygon(DrawMode mode, const float *coords, size_t count) gl.bindTexture(0); glEnableClientState(GL_VERTEX_ARRAY); glVertexPointer(2, GL_FLOAT, 0, (const GLvoid *)coords); - glDrawArrays(GL_POLYGON, 0, count/2-1); // opengl will close the polygon for us + gl.drawArrays(GL_POLYGON, 0, count/2-1); // opengl will close the polygon for us glDisableClientState(GL_VERTEX_ARRAY); } } @@ -1199,6 +1205,20 @@ Graphics::RendererInfo Graphics::getRendererInfo() const return info; } +Graphics::Stats Graphics::getStats() const +{ + Stats stats; + + stats.drawCalls = gl.stats.drawCalls; + stats.canvasSwitches = Canvas::switchCount; + stats.canvases = Canvas::canvasCount; + stats.images = Image::imageCount; + stats.fonts = Font::fontCount; + stats.textureMemory = gl.stats.textureMemory; + + return stats; +} + double Graphics::getSystemLimit(SystemLimit limittype) const { double limit = 0.0; diff --git a/src/modules/graphics/opengl/Graphics.h b/src/modules/graphics/opengl/Graphics.h index 5e73cf24c..3d9cc07a1 100644 --- a/src/modules/graphics/opengl/Graphics.h +++ b/src/modules/graphics/opengl/Graphics.h @@ -390,11 +390,16 @@ public: /** * Returns system-dependent renderer information. - * Returned string s can vary greatly between systems! Do not rely on it for + * Returned strings can vary greatly between systems! Do not rely on it for * anything! **/ RendererInfo getRendererInfo() const; + /** + * Returns performance-related statistics. + **/ + Stats getStats() const; + /** * Gets the system-dependent numeric limit for the specified parameter. **/ diff --git a/src/modules/graphics/opengl/Image.cpp b/src/modules/graphics/opengl/Image.cpp index a81734721..db9c69635 100644 --- a/src/modules/graphics/opengl/Image.cpp +++ b/src/modules/graphics/opengl/Image.cpp @@ -31,6 +31,8 @@ namespace graphics namespace opengl { +int Image::imageCount = 0; + float Image::maxMipmapSharpness = 0.0f; Texture::FilterMode Image::defaultMipmapFilter = Texture::FILTER_NEAREST; @@ -44,10 +46,13 @@ Image::Image(love::image::ImageData *data, const Flags &flags) , compressed(false) , flags(flags) , usingDefaultTexture(false) + , textureMemorySize(0) { width = data->getWidth(); height = data->getHeight(); preload(); + + ++imageCount; } Image::Image(love::image::CompressedData *cdata, const Flags &flags) @@ -58,15 +63,20 @@ Image::Image(love::image::CompressedData *cdata, const Flags &flags) , compressed(true) , flags(flags) , usingDefaultTexture(false) + , textureMemorySize(0) { width = cdata->getWidth(0); height = cdata->getHeight(0); preload(); + + ++imageCount; } Image::~Image() { unload(); + + --imageCount; } love::image::ImageData *Image::getImageData() const @@ -331,6 +341,23 @@ bool Image::loadVolatile() throw; } + size_t prevmemsize = textureMemorySize; + + if (isCompressed()) + { + textureMemorySize = 0; + for (int i = 0; i < flags.mipmaps ? cdata->getMipmapCount() : 1; i++) + textureMemorySize += cdata->getSize(i); + } + else + { + textureMemorySize = width * height * 4; + if (flags.mipmaps) + textureMemorySize *= 1.333; + } + + gl.updateTextureMemorySize(prevmemsize, textureMemorySize); + usingDefaultTexture = false; return true; } @@ -342,6 +369,9 @@ void Image::unloadVolatile() { gl.deleteTexture(texture); texture = 0; + + gl.updateTextureMemorySize(textureMemorySize, 0); + textureMemorySize = 0; } } @@ -401,7 +431,7 @@ void Image::drawv(const Matrix &t, const Vertex *v) glTexCoordPointer(2, GL_FLOAT, sizeof(Vertex), (GLvoid *)&v[0].s); gl.prepareDraw(); - glDrawArrays(GL_QUADS, 0, 4); + gl.drawArrays(GL_QUADS, 0, 4); glDisableClientState(GL_TEXTURE_COORD_ARRAY); glDisableClientState(GL_VERTEX_ARRAY); diff --git a/src/modules/graphics/opengl/Image.h b/src/modules/graphics/opengl/Image.h index 556a728df..ed837a337 100644 --- a/src/modules/graphics/opengl/Image.h +++ b/src/modules/graphics/opengl/Image.h @@ -149,6 +149,8 @@ public: static bool getConstant(const char *in, FlagType &out); static bool getConstant(FlagType in, const char *&out); + static int imageCount; + private: void uploadDefaultTexture(); @@ -179,6 +181,8 @@ private: // back to a default texture. bool usingDefaultTexture; + size_t textureMemorySize; + void preload(); void uploadCompressedData(); diff --git a/src/modules/graphics/opengl/Mesh.cpp b/src/modules/graphics/opengl/Mesh.cpp index 0e11b2178..7bdbd1884 100644 --- a/src/modules/graphics/opengl/Mesh.cpp +++ b/src/modules/graphics/opengl/Mesh.cpp @@ -375,7 +375,7 @@ void Mesh::draw(float x, float y, float angle, float sx, float sy, float ox, flo GLenum type = element_data_type; const void *indices = ibo->getPointer(min * getGLDataTypeSize(type)); - glDrawElements(mode, max - min + 1, type, indices); + gl.drawElements(mode, max - min + 1, type, indices); } else { @@ -388,7 +388,7 @@ void Mesh::draw(float x, float y, float angle, float sx, float sy, float ox, flo min = std::min(range_min, max); // Normal non-indexed drawing (no custom vertex map.) - glDrawArrays(mode, min, max - min + 1); + gl.drawArrays(mode, min, max - min + 1); } glDisableClientState(GL_VERTEX_ARRAY); diff --git a/src/modules/graphics/opengl/OpenGL.cpp b/src/modules/graphics/opengl/OpenGL.cpp index 7f28981cf..a696bb475 100644 --- a/src/modules/graphics/opengl/OpenGL.cpp +++ b/src/modules/graphics/opengl/OpenGL.cpp @@ -41,7 +41,8 @@ namespace opengl { OpenGL::OpenGL() - : contextInitialized(false) + : stats() + , contextInitialized(false) , maxAnisotropy(1.0f) , maxTextureSize(0) , maxRenderTargets(0) @@ -293,6 +294,18 @@ void OpenGL::prepareDraw() } } +void OpenGL::drawArrays(GLenum mode, GLint first, GLsizei count) +{ + glDrawArrays(mode, first, count); + ++stats.drawCalls; +} + +void OpenGL::drawElements(GLenum mode, GLsizei count, GLenum type, const void *indices) +{ + glDrawElements(mode, count, type, indices); + ++stats.drawCalls; +} + void OpenGL::drawArraysInstanced(GLenum mode, GLint first, GLsizei count, GLsizei primcount) { Shader *shader = Shader::current; @@ -315,6 +328,8 @@ void OpenGL::drawArraysInstanced(GLenum mode, GLint first, GLsizei count, GLsize if (shaderHasID) state.lastPseudoInstanceID = primcount - 1; } + + ++stats.drawCalls; } void OpenGL::drawElementsInstanced(GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei primcount) @@ -339,6 +354,8 @@ void OpenGL::drawElementsInstanced(GLenum mode, GLsizei count, GLenum type, cons if (shaderHasID) state.lastPseudoInstanceID = primcount - 1; } + + ++stats.drawCalls; } void OpenGL::setColor(const Color &c) @@ -638,6 +655,12 @@ int OpenGL::getMaxRenderTargets() const return maxRenderTargets; } +void OpenGL::updateTextureMemorySize(size_t oldsize, size_t newsize) +{ + int64 memsize = (int64) stats.textureMemory + ((int64 )newsize - (int64) oldsize); + stats.textureMemory = (size_t) std::max(memsize, (int64) 0); +} + OpenGL::Vendor OpenGL::getVendor() const { return vendor; diff --git a/src/modules/graphics/opengl/OpenGL.h b/src/modules/graphics/opengl/OpenGL.h index ece0a1f08..63e263d19 100644 --- a/src/modules/graphics/opengl/OpenGL.h +++ b/src/modules/graphics/opengl/OpenGL.h @@ -139,6 +139,12 @@ public: OpenGL ≷ }; + struct Stats + { + size_t textureMemory; + int drawCalls; + } stats; + OpenGL(); /** @@ -170,13 +176,17 @@ public: void prepareDraw(); /** - * glDrawArraysInstanced with a pseudo-instancing fallback. + * glDrawArrays and glDrawElements which increment the draw-call counter by + * themselves. **/ - void drawArraysInstanced(GLenum mode, GLint first, GLsizei count, GLsizei primcount); + void drawArrays(GLenum mode, GLint first, GLsizei count); + void drawElements(GLenum mode, GLsizei count, GLenum type, const void *indices); /** - * glDrawElementsInstanced with a pseudo-instancing fallback. + * glDrawArraysInstanced and glDrawElementsInstanced with pseudo-instancing + * fallbacks. They also increment the draw-call counter (once per call). **/ + void drawArraysInstanced(GLenum mode, GLint first, GLsizei count, GLsizei primcount); void drawElementsInstanced(GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei primcount); /** @@ -291,6 +301,8 @@ public: **/ int getMaxRenderTargets() const; + void updateTextureMemorySize(size_t oldsize, size_t newsize); + /** * Get the GPU vendor of this OpenGL context. **/ diff --git a/src/modules/graphics/opengl/ParticleSystem.cpp b/src/modules/graphics/opengl/ParticleSystem.cpp index 289bcfcc1..c4c5b0524 100644 --- a/src/modules/graphics/opengl/ParticleSystem.cpp +++ b/src/modules/graphics/opengl/ParticleSystem.cpp @@ -878,7 +878,7 @@ void ParticleSystem::draw(float x, float y, float angle, float sx, float sy, flo glTexCoordPointer(2, GL_FLOAT, sizeof(Vertex), (GLvoid *) &particleVerts[0].s); gl.prepareDraw(); - glDrawArrays(GL_QUADS, 0, pCount * 4); + gl.drawArrays(GL_QUADS, 0, pCount * 4); glDisableClientState(GL_TEXTURE_COORD_ARRAY); glDisableClientState(GL_VERTEX_ARRAY); diff --git a/src/modules/graphics/opengl/Polyline.cpp b/src/modules/graphics/opengl/Polyline.cpp index 24d09405c..58c2eff11 100644 --- a/src/modules/graphics/opengl/Polyline.cpp +++ b/src/modules/graphics/opengl/Polyline.cpp @@ -333,7 +333,7 @@ void Polyline::draw() gl.bindTexture(0); glEnableClientState(GL_VERTEX_ARRAY); glVertexPointer(2, GL_FLOAT, 0, (const GLvoid *)vertices); - glDrawArrays(draw_mode, 0, vertex_count); + gl.drawArrays(draw_mode, 0, vertex_count); if (overdraw) { @@ -345,7 +345,7 @@ void Polyline::draw() glEnableClientState(GL_COLOR_ARRAY); glColorPointer(4, GL_UNSIGNED_BYTE, 0, colors); glVertexPointer(2, GL_FLOAT, 0, (const GLvoid *)overdraw); - glDrawArrays(draw_mode, 0, overdraw_vertex_count); + gl.drawArrays(draw_mode, 0, overdraw_vertex_count); glDisableClientState(GL_COLOR_ARRAY); delete[] colors; diff --git a/src/modules/graphics/opengl/SpriteBatch.cpp b/src/modules/graphics/opengl/SpriteBatch.cpp index 99d8d79c5..5d578e023 100644 --- a/src/modules/graphics/opengl/SpriteBatch.cpp +++ b/src/modules/graphics/opengl/SpriteBatch.cpp @@ -294,7 +294,7 @@ void SpriteBatch::draw(float x, float y, float angle, float sx, float sy, float glTexCoordPointer(2, GL_FLOAT, sizeof(Vertex), array_buf->getPointer(texel_offset)); gl.prepareDraw(); - glDrawElements(GL_TRIANGLES, element_buf->getIndexCount(next), element_buf->getType(), element_buf->getPointer(0)); + gl.drawElements(GL_TRIANGLES, element_buf->getIndexCount(next), element_buf->getType(), element_buf->getPointer(0)); glDisableClientState(GL_VERTEX_ARRAY); glDisableClientState(GL_TEXTURE_COORD_ARRAY); diff --git a/src/modules/graphics/opengl/wrap_Graphics.cpp b/src/modules/graphics/opengl/wrap_Graphics.cpp index 0eb22138f..b1c818e30 100644 --- a/src/modules/graphics/opengl/wrap_Graphics.cpp +++ b/src/modules/graphics/opengl/wrap_Graphics.cpp @@ -1051,6 +1051,41 @@ int w_getSystemLimits(lua_State *L) return 1; } +int w_getStats(lua_State *L) +{ + Graphics::Stats stats = instance()->getStats(); + + lua_createtable(L, 0, (int) Graphics::STAT_MAX_ENUM); + + const char *sname = nullptr; + + Graphics::getConstant(Graphics::STAT_DRAW_CALLS, sname); + lua_pushinteger(L, stats.drawCalls); + lua_setfield(L, -2, sname); + + Graphics::getConstant(Graphics::STAT_CANVAS_SWITCHES, sname); + lua_pushinteger(L, stats.canvasSwitches); + lua_setfield(L, -2, sname); + + Graphics::getConstant(Graphics::STAT_CANVASES, sname); + lua_pushinteger(L, stats.canvases); + lua_setfield(L, -2, sname); + + Graphics::getConstant(Graphics::STAT_IMAGES, sname); + lua_pushinteger(L, stats.images); + lua_setfield(L, -2, sname); + + Graphics::getConstant(Graphics::STAT_FONTS, sname); + lua_pushinteger(L, stats.fonts); + lua_setfield(L, -2, sname); + + Graphics::getConstant(Graphics::STAT_TEXTURE_MEMORY, sname); + lua_pushnumber(L, (lua_Number) stats.textureMemory); + lua_setfield(L, -2, sname); + + return 1; +} + int w_draw(lua_State *L) { Drawable *drawable = nullptr; @@ -1409,6 +1444,7 @@ static const luaL_Reg functions[] = { "getCompressedImageFormats", w_getCompressedImageFormats }, { "getRendererInfo", w_getRendererInfo }, { "getSystemLimits", w_getSystemLimits }, + { "getStats", w_getStats }, { "draw", w_draw }, diff --git a/src/modules/graphics/opengl/wrap_Graphics.h b/src/modules/graphics/opengl/wrap_Graphics.h index 600cada39..f20c1285f 100644 --- a/src/modules/graphics/opengl/wrap_Graphics.h +++ b/src/modules/graphics/opengl/wrap_Graphics.h @@ -94,6 +94,7 @@ int w_getCanvasFormats(lua_State *L); int w_getCompressedImageFormats(lua_State *L); int w_getRendererInfo(lua_State *L); int w_getSystemLimits(lua_State *L); +int w_getStats(lua_State *L); int w_draw(lua_State *L); int w_print(lua_State *L); int w_printf(lua_State *L); diff --git a/src/modules/window/Window.cpp b/src/modules/window/Window.cpp index 5d1e68f02..5d1865519 100644 --- a/src/modules/window/Window.cpp +++ b/src/modules/window/Window.cpp @@ -51,6 +51,7 @@ WindowSettings::WindowSettings() , display(0) , highdpi(false) , sRGB(false) + , refreshrate(0.0) { } @@ -98,6 +99,7 @@ StringMap::Entry Window::settingEntri {"display", SETTING_DISPLAY}, {"highdpi", SETTING_HIGHDPI}, {"srgb", SETTING_SRGB}, + {"refreshrate", SETTING_REFRESHRATE}, }; StringMap Window::settings(Window::settingEntries, sizeof(Window::settingEntries)); diff --git a/src/modules/window/Window.h b/src/modules/window/Window.h index 73c59e642..cfbec4d37 100644 --- a/src/modules/window/Window.h +++ b/src/modules/window/Window.h @@ -58,6 +58,7 @@ public: SETTING_DISPLAY, SETTING_HIGHDPI, SETTING_SRGB, + SETTING_REFRESHRATE, SETTING_MAX_ENUM }; @@ -194,6 +195,7 @@ struct WindowSettings int display; // = 0 bool highdpi; // false bool sRGB; // false + double refreshrate; // 0.0 }; // WindowSettings diff --git a/src/modules/window/sdl/Window.cpp b/src/modules/window/sdl/Window.cpp index f2f60372c..2cd866d63 100644 --- a/src/modules/window/sdl/Window.cpp +++ b/src/modules/window/sdl/Window.cpp @@ -390,6 +390,12 @@ void Window::updateSettings(const WindowSettings &newsettings) SDL_SetHint(SDL_HINT_VIDEO_MINIMIZE_ON_FOCUS_LOSS, "0"); curMode.settings.sRGB = newsettings.sRGB; + + SDL_DisplayMode dmode = {}; + SDL_GetCurrentDisplayMode(curMode.settings.display, &dmode); + + // May be 0 if the refresh rate can't be determined. + curMode.settings.refreshrate = (double) dmode.refresh_rate; } void Window::getWindow(int &width, int &height, WindowSettings &settings) diff --git a/src/modules/window/wrap_Window.cpp b/src/modules/window/wrap_Window.cpp index 70d907fce..518dabc0d 100644 --- a/src/modules/window/wrap_Window.cpp +++ b/src/modules/window/wrap_Window.cpp @@ -105,12 +105,11 @@ int w_setMode(lua_State *L) settings.minheight = luax_intflag(L, 3, settingName(Window::SETTING_MIN_HEIGHT), 1); settings.borderless = luax_boolflag(L, 3, settingName(Window::SETTING_BORDERLESS), false); settings.centered = luax_boolflag(L, 3, settingName(Window::SETTING_CENTERED), true); - settings.display = luax_intflag(L, 3, settingName(Window::SETTING_DISPLAY), 1); + settings.display = luax_intflag(L, 3, settingName(Window::SETTING_DISPLAY), 1) - 1; settings.highdpi = luax_boolflag(L, 3, settingName(Window::SETTING_HIGHDPI), false); settings.sRGB = luax_boolflag(L, 3, settingName(Window::SETTING_SRGB), false); - // Display index is 1-based in Lua and 0-based internally. - settings.display--; + // We don't explicitly set the refresh rate, it's "read-only". luax_catchexcept(L, [&](){ luax_pushboolean(L, instance()->setWindow(w, h, &settings)); } @@ -169,6 +168,9 @@ int w_getMode(lua_State *L) luax_pushboolean(L, settings.sRGB); lua_setfield(L, -2, settingName(Window::SETTING_SRGB)); + lua_pushnumber(L, settings.refreshrate); + lua_setfield(L, -2, settingName(Window::SETTING_REFRESHRATE)); + return 3; }