LCOV - code coverage report
Current view: top level - src - guiscalingfilter.cpp (source / functions) Hit Total Coverage
Test: report Lines: 23 65 35.4 %
Date: 2015-07-11 18:23:49 Functions: 6 7 85.7 %

          Line data    Source code
       1             : /*
       2             : Copyright (C) 2015 Aaron Suen <warr1024@gmail.com>
       3             : 
       4             : This program is free software; you can redistribute it and/or modify
       5             : it under the terms of the GNU Lesser General Public License as published by
       6             : the Free Software Foundation; either version 2.1 of the License, or
       7             : (at your option) any later version.
       8             : 
       9             : This program is distributed in the hope that it will be useful,
      10             : but WITHOUT ANY WARRANTY; without even the implied warranty of
      11             : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      12             : GNU Lesser General Public License for more details.
      13             : 
      14             : You should have received a copy of the GNU Lesser General Public License along
      15             : with this program; if not, write to the Free Software Foundation, Inc.,
      16             : 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
      17             : */
      18             : 
      19             : #include "guiscalingfilter.h"
      20             : #include "imagefilters.h"
      21             : #include "settings.h"
      22             : #include "util/numeric.h"
      23             : #include <stdio.h>
      24             : 
      25             : /* Maintain a static cache to store the images that correspond to textures
      26             :  * in a format that's manipulable by code.  Some platforms exhibit issues
      27             :  * converting textures back into images repeatedly, and some don't even
      28             :  * allow it at all.
      29             :  */
      30           1 : std::map<io::path, video::IImage *> g_imgCache;
      31             : 
      32             : /* Maintain a static cache of all pre-scaled textures.  These need to be
      33             :  * cleared as well when the cached images.
      34             :  */
      35           1 : std::map<io::path, video::ITexture *> g_txrCache;
      36             : 
      37             : /* Manually insert an image into the cache, useful to avoid texture-to-image
      38             :  * conversion whenever we can intercept it.
      39             :  */
      40        2682 : void guiScalingCache(io::path key, video::IVideoDriver *driver, video::IImage *value)
      41             : {
      42        2682 :         if (!g_settings->getBool("gui_scaling_filter"))
      43        2682 :                 return;
      44           0 :         video::IImage *copied = driver->createImage(value->getColorFormat(),
      45           0 :                         value->getDimension());
      46           0 :         value->copyTo(copied);
      47           0 :         g_imgCache[key] = copied;
      48             : }
      49             : 
      50             : // Manually clear the cache, e.g. when switching to different worlds.
      51           1 : void guiScalingCacheClear(video::IVideoDriver *driver)
      52             : {
      53           3 :         for (std::map<io::path, video::IImage *>::iterator it = g_imgCache.begin();
      54           2 :                         it != g_imgCache.end(); it++) {
      55           0 :                 if (it->second != NULL)
      56           0 :                         it->second->drop();
      57             :         }
      58           1 :         g_imgCache.clear();
      59           3 :         for (std::map<io::path, video::ITexture *>::iterator it = g_txrCache.begin();
      60           2 :                         it != g_txrCache.end(); it++) {
      61           0 :                 if (it->second != NULL)
      62           0 :                         driver->removeTexture(it->second);
      63             :         }
      64           1 :         g_txrCache.clear();
      65           1 : }
      66             : 
      67             : /* Get a cached, high-quality pre-scaled texture for display purposes.  If the
      68             :  * texture is not already cached, attempt to create it.  Returns a pre-scaled texture,
      69             :  * or the original texture if unable to pre-scale it.
      70             :  */
      71       22154 : video::ITexture *guiScalingResizeCached(video::IVideoDriver *driver,
      72             :                 video::ITexture *src, const core::rect<s32> &srcrect,
      73             :                 const core::rect<s32> &destrect)
      74             : {
      75       22154 :         if (src == NULL)
      76           0 :                 return src;
      77       22154 :         if (!g_settings->getBool("gui_scaling_filter"))
      78       22154 :                 return src;
      79             : 
      80             :         // Calculate scaled texture name.
      81             :         char rectstr[200];
      82           0 :         snprintf(rectstr, sizeof(rectstr), "%d:%d:%d:%d:%d:%d",
      83           0 :                 srcrect.UpperLeftCorner.X,
      84           0 :                 srcrect.UpperLeftCorner.Y,
      85             :                 srcrect.getWidth(),
      86             :                 srcrect.getHeight(),
      87             :                 destrect.getWidth(),
      88           0 :                 destrect.getHeight());
      89           0 :         io::path origname = src->getName().getPath();
      90           0 :         io::path scalename = origname + "@guiScalingFilter:" + rectstr;
      91             : 
      92             :         // Search for existing scaled texture.
      93           0 :         video::ITexture *scaled = g_txrCache[scalename];
      94           0 :         if (scaled)
      95           0 :                 return scaled;
      96             : 
      97             :         // Try to find the texture converted to an image in the cache.
      98             :         // If the image was not found, try to extract it from the texture.
      99           0 :         video::IImage* srcimg = g_imgCache[origname];
     100           0 :         if (srcimg == NULL) {
     101           0 :                 if (!g_settings->getBool("gui_scaling_filter_txr2img"))
     102           0 :                         return src;
     103           0 :                 srcimg = driver->createImageFromData(src->getColorFormat(),
     104           0 :                         src->getSize(), src->lock(), false);
     105           0 :                 src->unlock();
     106           0 :                 g_imgCache[origname] = srcimg;
     107             :         }
     108             : 
     109             :         // Create a new destination image and scale the source into it.
     110           0 :         imageCleanTransparent(srcimg, 0);
     111           0 :         video::IImage *destimg = driver->createImage(src->getColorFormat(),
     112           0 :                         core::dimension2d<u32>((u32)destrect.getWidth(),
     113           0 :                         (u32)destrect.getHeight()));
     114           0 :         imageScaleNNAA(srcimg, srcrect, destimg);
     115             : 
     116             : #ifdef __ANDROID__
     117             :         // Android is very picky about textures being powers of 2, so expand
     118             :         // the image dimensions to the next power of 2, if necessary, for
     119             :         // that platform.
     120             :         video::IImage *po2img = driver->createImage(src->getColorFormat(),
     121             :                         core::dimension2d<u32>(npot2((u32)destrect.getWidth()),
     122             :                         npot2((u32)destrect.getHeight())));
     123             :         po2img->fill(video::SColor(0, 0, 0, 0));
     124             :         destimg->copyTo(po2img);
     125             :         destimg->drop();
     126             :         destimg = po2img;
     127             : #endif
     128             : 
     129             :         // Convert the scaled image back into a texture.
     130           0 :         scaled = driver->addTexture(scalename, destimg, NULL);
     131           0 :         destimg->drop();
     132           0 :         g_txrCache[scalename] = scaled;
     133             : 
     134           0 :         return scaled;
     135             : }
     136             : 
     137             : /* Convenience wrapper for guiScalingResizeCached that accepts parameters that
     138             :  * are available at GUI imagebutton creation time.
     139             :  */
     140           0 : video::ITexture *guiScalingImageButton(video::IVideoDriver *driver,
     141             :                 video::ITexture *src, s32 width, s32 height)
     142             : {
     143           0 :         if (src == NULL)
     144           0 :                 return src;
     145           0 :         return guiScalingResizeCached(driver, src,
     146           0 :                 core::rect<s32>(0, 0, src->getSize().Width, src->getSize().Height),
     147           0 :                 core::rect<s32>(0, 0, width, height));
     148             : }
     149             : 
     150             : /* Replacement for driver->draw2DImage() that uses the high-quality pre-scaled
     151             :  * texture, if configured.
     152             :  */
     153       22154 : void draw2DImageFilterScaled(video::IVideoDriver *driver, video::ITexture *txr,
     154             :                 const core::rect<s32> &destrect, const core::rect<s32> &srcrect,
     155             :                 const core::rect<s32> *cliprect, const video::SColor *const colors,
     156             :                 bool usealpha)
     157             : {
     158             :         // Attempt to pre-scale image in software in high quality.
     159       22154 :         video::ITexture *scaled = guiScalingResizeCached(driver, txr, srcrect, destrect);
     160       22154 :         if (scaled == NULL)
     161           0 :                 return;
     162             : 
     163             :         // Correct source rect based on scaled image.
     164             :         const core::rect<s32> mysrcrect = (scaled != txr)
     165             :                 ? core::rect<s32>(0, 0, destrect.getWidth(), destrect.getHeight())
     166       22154 :                 : srcrect;
     167             : 
     168       22154 :         driver->draw2DImage(scaled, destrect, mysrcrect, cliprect, colors, usealpha);
     169           3 : }

Generated by: LCOV version 1.11