From e1f7e4abd3296d5af6e5dea7115dea67bcc5f175 Mon Sep 17 00:00:00 2001 From: Alex Szpakowski Date: Wed, 20 Aug 2014 20:22:46 -0300 Subject: [PATCH 1/3] Added a 'refreshrate' field to the table returned by love.window.getMode. The value may be 0 if the refresh rate of the monitor can't be determined. It might also be 59 instead of 60 on 59.94hz monitors on some operating systems. --- src/modules/window/Window.cpp | 2 ++ src/modules/window/Window.h | 2 ++ src/modules/window/sdl/Window.cpp | 6 ++++++ src/modules/window/wrap_Window.cpp | 10 ++++++---- 4 files changed, 16 insertions(+), 4 deletions(-) diff --git a/src/modules/window/Window.cpp b/src/modules/window/Window.cpp index 3e74db675..5ad2480ed 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) { } @@ -99,6 +100,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 dd0e1a18d..b7988f313 100644 --- a/src/modules/window/Window.h +++ b/src/modules/window/Window.h @@ -59,6 +59,7 @@ public: SETTING_DISPLAY, SETTING_HIGHDPI, SETTING_SRGB, + SETTING_REFRESHRATE, SETTING_MAX_ENUM }; @@ -198,6 +199,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 c149c9d35..8bc0d1935 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 c90f29e4d..c828c1379 100644 --- a/src/modules/window/wrap_Window.cpp +++ b/src/modules/window/wrap_Window.cpp @@ -105,17 +105,16 @@ 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); + // We don't explicitly set the refresh rate, it's "read-only". + // For backward-compatibility. TODO: remove! int fsaa = luax_intflag(L, 3, settingName(Window::SETTING_FSAA), 0); if (fsaa > settings.msaa) settings.msaa = fsaa; - // Display index is 1-based in Lua and 0-based internally. - settings.display--; - luax_catchexcept(L, [&](){ luax_pushboolean(L, instance()->setWindow(w, h, &settings)); } ); @@ -176,6 +175,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; } From 8ffe610659996be343ea1be470f7bec2c162273e Mon Sep 17 00:00:00 2001 From: Alex Szpakowski Date: Thu, 21 Aug 2014 15:01:29 -0300 Subject: [PATCH 2/3] Added love.graphics.getStats. It returns a table with performance-related graphics statistics. Currently it contains these fields: drawcalls: The number of internal draw calls made so far in the current frame. canvasswitches: The number of times the active Canvas has been changed so far in the current frame. texturememory: The approximate amount of video memory (in bytes) used by OpenGL textures created by Images, Canvases, and Fonts. images: The number of active Image objects. canvases: The number of active Canvas objects. fonts: The number of active Font objects. --- src/modules/graphics/Graphics.cpp | 22 ++++++++++ src/modules/graphics/Graphics.h | 27 ++++++++++++ src/modules/graphics/opengl/Canvas.cpp | 43 ++++++++++++++++++- src/modules/graphics/opengl/Canvas.h | 7 +++ src/modules/graphics/opengl/Font.cpp | 17 +++++++- src/modules/graphics/opengl/Font.h | 4 ++ src/modules/graphics/opengl/Graphics.cpp | 24 ++++++++++- src/modules/graphics/opengl/Graphics.h | 7 ++- src/modules/graphics/opengl/Image.cpp | 35 ++++++++++++++- src/modules/graphics/opengl/Image.h | 4 ++ src/modules/graphics/opengl/Mesh.cpp | 4 +- src/modules/graphics/opengl/OpenGL.cpp | 25 ++++++++++- src/modules/graphics/opengl/OpenGL.h | 18 ++++++-- .../graphics/opengl/ParticleSystem.cpp | 2 +- src/modules/graphics/opengl/Polyline.cpp | 4 +- src/modules/graphics/opengl/SpriteBatch.cpp | 2 +- src/modules/graphics/opengl/wrap_Graphics.cpp | 36 ++++++++++++++++ src/modules/graphics/opengl/wrap_Graphics.h | 1 + 18 files changed, 266 insertions(+), 16 deletions(-) diff --git a/src/modules/graphics/Graphics.cpp b/src/modules/graphics/Graphics.cpp index d6e16cd37..fffb895ea 100644 --- a/src/modules/graphics/Graphics.cpp +++ b/src/modules/graphics/Graphics.cpp @@ -119,6 +119,16 @@ bool Graphics::getConstant(StackType in, const char *&out) return stackTypes.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 }, @@ -210,5 +220,17 @@ StringMap::Entry Graphics::stackT StringMap Graphics::stackTypes(Graphics::stackTypeEntries, sizeof(Graphics::stackTypeEntries)); +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 8cdeb68d2..26dc2454e 100644 --- a/src/modules/graphics/Graphics.h +++ b/src/modules/graphics/Graphics.h @@ -119,6 +119,17 @@ public: STACK_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; @@ -127,6 +138,16 @@ public: std::string device; }; + struct Stats + { + int drawCalls; + int canvasSwitches; + int canvases; + int images; + int fonts; + size_t textureMemory; + }; + virtual ~Graphics(); // Implements Module. @@ -177,6 +198,9 @@ public: static bool getConstant(const char *in, StackType &out); static bool getConstant(StackType 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[]; @@ -206,6 +230,9 @@ private: static StringMap::Entry stackTypeEntries[]; static StringMap stackTypes; + 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 3e0b64bbe..7310df3ed 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() @@ -314,6 +315,7 @@ struct FramebufferStrategyPackedEXT : public FramebufferStrategy virtual void bindFBO(GLuint framebuffer) { glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, framebuffer); + ++Canvas::switchCount; } virtual void setAttachments() @@ -407,6 +409,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() { @@ -432,6 +436,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; @@ -462,10 +467,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(); @@ -581,6 +590,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; } @@ -595,6 +612,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) @@ -611,7 +631,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); @@ -1012,6 +1032,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 f2faee97e..df19f875d 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); @@ -561,6 +573,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 f2289ec37..1c1c5b2d9 100644 --- a/src/modules/graphics/opengl/Graphics.cpp +++ b/src/modules/graphics/opengl/Graphics.cpp @@ -350,6 +350,10 @@ void Graphics::clear() void Graphics::present() { currentWindow->swapBuffers(); + + // Reset the per-frame stat counts. + gl.stats.drawCalls = 0; + Canvas::switchCount = 0; } int Graphics::getWidth() const @@ -947,6 +951,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) @@ -1042,7 +1048,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); } @@ -1066,7 +1072,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); } } @@ -1165,6 +1171,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 aebceb333..e3e24b3f6 100644 --- a/src/modules/graphics/opengl/Graphics.h +++ b/src/modules/graphics/opengl/Graphics.h @@ -412,11 +412,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 791bea74b..678f0b9a6 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_NONE; @@ -47,10 +49,14 @@ Image::Image(love::image::ImageData *data, Format format) , compressed(false) , format(format) , usingDefaultTexture(false) + , textureMemorySize(0) { width = data->getWidth(); height = data->getHeight(); preload(); + + textureMemorySize = data->getSize(); + ++imageCount; } Image::Image(love::image::CompressedData *cdata, Format format) @@ -64,15 +70,21 @@ Image::Image(love::image::CompressedData *cdata, Format format) , compressed(true) , format(format) , usingDefaultTexture(false) + , textureMemorySize(0) { width = cdata->getWidth(0); height = cdata->getHeight(0); preload(); + + textureMemorySize = cdata->getSize(0); + ++imageCount; } Image::~Image() { unload(); + + --imageCount; } love::image::ImageData *Image::getImageData() const @@ -151,8 +163,11 @@ void Image::uploadCompressedMipmaps() "compressed image does not have all required levels."); } + size_t totalsize = cdata->getSize(0); + for (int i = 1; i < count; i++) { + totalsize += cdata->getSize(i); glCompressedTexImage2DARB(GL_TEXTURE_2D, i, getCompressedFormat(cdata->getFormat()), @@ -162,6 +177,10 @@ void Image::uploadCompressedMipmaps() GLsizei(cdata->getSize(i)), cdata->getData(i)); } + + size_t prevmemsize = textureMemorySize; + textureMemorySize = totalsize; + gl.updateTextureMemorySize(prevmemsize, textureMemorySize); } void Image::createMipmaps() @@ -216,6 +235,10 @@ void Image::createMipmaps() data->getData()); glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_FALSE); } + + size_t prevmemsize = textureMemorySize; + textureMemorySize = paddedWidth * paddedHeight * 4 * 1.3333; + gl.updateTextureMemorySize(prevmemsize, textureMemorySize); } void Image::checkMipmapsCreated() @@ -381,6 +404,13 @@ bool Image::loadVolatile() if (glerr != GL_NO_ERROR) throw love::Exception("Cannot create image (error code 0x%x)", glerr); + if (isCompressed()) + textureMemorySize = cdata->getSize(0); + else + textureMemorySize = paddedWidth * paddedHeight * 4; + + gl.updateTextureMemorySize(0, textureMemorySize); + usingDefaultTexture = false; mipmapsCreated = false; checkMipmapsCreated(); @@ -456,6 +486,9 @@ void Image::unloadVolatile() { gl.deleteTexture(texture); texture = 0; + + gl.updateTextureMemorySize(textureMemorySize, 0); + textureMemorySize = 0; } } @@ -530,7 +563,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 f15b0aa4a..c6a0964f6 100644 --- a/src/modules/graphics/opengl/Image.h +++ b/src/modules/graphics/opengl/Image.h @@ -148,6 +148,8 @@ public: static bool getConstant(const char *in, Format &out); static bool getConstant(Format in, const char *&out); + static int imageCount; + private: void uploadDefaultTexture(); @@ -184,6 +186,8 @@ private: // back to a default texture. bool usingDefaultTexture; + size_t textureMemorySize; + void preload(); void uploadTexturePadded(); 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 6798b0b00..f45bed50d 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) @@ -319,6 +320,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; @@ -341,6 +354,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) @@ -365,6 +380,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) @@ -689,6 +706,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 1cc174ff3..34f2146dc 100644 --- a/src/modules/graphics/opengl/OpenGL.h +++ b/src/modules/graphics/opengl/OpenGL.h @@ -133,6 +133,12 @@ public: OpenGL ≷ }; + struct Stats + { + size_t textureMemory; + int drawCalls; + } stats; + OpenGL(); /** @@ -159,13 +165,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); /** @@ -279,6 +289,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 e0a8a90e4..363b91fa3 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 677427ec5..8ae1b1b7e 100644 --- a/src/modules/graphics/opengl/wrap_Graphics.cpp +++ b/src/modules/graphics/opengl/wrap_Graphics.cpp @@ -1054,6 +1054,41 @@ int w_getRendererInfo(lua_State *L) return 4; } +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_getSystemLimit(lua_State *L) { const char *limitstr = luaL_checkstring(L, 1); @@ -1425,6 +1460,7 @@ static const luaL_Reg functions[] = { "getCanvasFormats", w_getCanvasFormats }, { "getCompressedImageFormats", w_getCompressedImageFormats }, { "getRendererInfo", w_getRendererInfo }, + { "getStats", w_getStats }, { "getSystemLimit", w_getSystemLimit }, { "draw", w_draw }, diff --git a/src/modules/graphics/opengl/wrap_Graphics.h b/src/modules/graphics/opengl/wrap_Graphics.h index 7f98a44ea..f08d3b8bf 100644 --- a/src/modules/graphics/opengl/wrap_Graphics.h +++ b/src/modules/graphics/opengl/wrap_Graphics.h @@ -96,6 +96,7 @@ int w_isSupported(lua_State *L); int w_getCanvasFormats(lua_State *L); int w_getCompressedImageFormats(lua_State *L); int w_getRendererInfo(lua_State *L); +int w_getStats(lua_State *L); int w_getSystemLimit(lua_State *L); int w_draw(lua_State *L); int w_print(lua_State *L); From 44b97dfadc39da8b0006bcf845cc9c9259ab4959 Mon Sep 17 00:00:00 2001 From: Alex Szpakowski Date: Thu, 21 Aug 2014 16:38:22 -0300 Subject: [PATCH 3/3] Updated the changelog. --- changes.txt | 4 ++++ 1 file changed, 4 insertions(+) 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.