LCOV - code coverage report
Current view: top level - ezlibs/ezGL - texture.hpp (source / functions) Coverage Total Hit
Test: Coverage (llvm-cov → lcov → genhtml) Lines: 0.0 % 541 0
Test Date: 2025-09-16 22:55:37 Functions: 0.0 % 34 0
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: - 0 0

             Branch data     Line data    Source code
       1                 :             : #pragma once
       2                 :             : 
       3                 :             : /*
       4                 :             : MIT License
       5                 :             : 
       6                 :             : Copyright (c) 2014-2024 Stephane Cuillerdier (aka aiekick)
       7                 :             : 
       8                 :             : Permission is hereby granted, free of charge, to any person obtaining a copy
       9                 :             : of this software and associated documentation files (the "Software"), to deal
      10                 :             : in the Software without restriction, including without limitation the rights
      11                 :             : to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
      12                 :             : copies of the Software, and to permit persons to whom the Software is
      13                 :             : furnished to do so, subject to the following conditions:
      14                 :             : 
      15                 :             : The above copyright notice and this permission notice shall be included in all
      16                 :             : copies or substantial portions of the Software.
      17                 :             : 
      18                 :             : THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
      19                 :             : IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      20                 :             : FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
      21                 :             : AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      22                 :             : LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
      23                 :             : OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
      24                 :             : SOFTWARE.
      25                 :             : */
      26                 :             : 
      27                 :             : // ezGL is part of the ezLibs project : https://github.com/aiekick/ezLibs.git
      28                 :             : 
      29                 :             : 
      30                 :             : #include "ezGL.hpp"
      31                 :             : 
      32                 :             : #ifdef STB_IMAGE_READER_INCLUDE
      33                 :             : #include STB_IMAGE_READER_INCLUDE
      34                 :             : #endif  // STB_IMAGE_READER_INCLUDE
      35                 :             : 
      36                 :             : #ifdef STB_IMAGE_WRITER_INCLUDE
      37                 :             : #include STB_IMAGE_WRITER_INCLUDE
      38                 :             : #endif // STB_IMAGE_WRITER_INCLUDE
      39                 :             : 
      40                 :             : #include <algorithm>
      41                 :             : #include <cassert>
      42                 :             : #include <memory>
      43                 :             : #include <string>
      44                 :             : #include <array>
      45                 :             : 
      46                 :             : namespace ez {
      47                 :             : namespace gl {
      48                 :             : 
      49                 :             : class Texture;
      50                 :             : typedef std::shared_ptr<Texture> TexturePtr;
      51                 :             : typedef std::weak_ptr<Texture> TextureWeak;
      52                 :             : 
      53                 :             : class Texture {
      54                 :             : public:
      55                 :             :     // wrap (repeat|mirror|clamp), filter (linear|nearest)
      56                 :           0 :     static TexturePtr createEmpty(const GLsizei vSx, const GLsizei vSy, const std::string vWrap, const std::string vFilter, const bool vEnableMipMap) {
      57                 :           0 :         auto res = std::make_shared<Texture>();
      58                 :           0 :         res->m_This = res;
      59                 :           0 :         if (!res->initEmpty(vSx, vSy, vWrap, vFilter, vEnableMipMap)) {
      60                 :           0 :             res.reset();
      61                 :           0 :         }
      62                 :           0 :         return res;
      63                 :           0 :     }
      64                 :             :     // wrap (repeat|mirror|clamp), filter (linear|nearest)
      65                 :             :     static TexturePtr createFromBuffer(
      66                 :             :         const uint8_t* vBuffer,
      67                 :             :         const GLsizei vSx,
      68                 :             :         const GLsizei vSy,
      69                 :             :         const GLenum vInternalFormat,
      70                 :             :         const GLenum vFormat,
      71                 :             :         const GLenum vPixelFormat,
      72                 :             :         const std::string vWrap,
      73                 :             :         const std::string vFilter,
      74                 :           0 :         const bool vEnableMipMap) {
      75                 :           0 :         auto res = std::make_shared<Texture>();
      76                 :           0 :         res->m_This = res;
      77                 :           0 :         if (!res->initFromBuffer(vBuffer, vSx, vSy, vInternalFormat, vFormat, vPixelFormat, vWrap, vFilter, vEnableMipMap)) {
      78                 :           0 :             res.reset();
      79                 :           0 :         }
      80                 :           0 :         return res;
      81                 :           0 :     }
      82                 :             :     // wrap (repeat|mirror|clamp), filter (linear|nearest)
      83                 :             :     static TexturePtr createFromBuffer(
      84                 :             :         const uint8_t* vBuffer,
      85                 :             :         const GLsizei vSx,
      86                 :             :         const GLsizei vSy,
      87                 :             :         const GLint vChannelsCount,
      88                 :             :         const GLenum vPixelFormat,
      89                 :             :         const std::string vWrap,
      90                 :             :         const std::string vFilter,
      91                 :           0 :         const bool vEnableMipMap) {
      92                 :           0 :         auto res = std::make_shared<Texture>();
      93                 :           0 :         res->m_This = res;
      94                 :           0 :         if (!res->initFromBuffer(vBuffer, vSx, vSy, vChannelsCount, vPixelFormat, vWrap, vFilter, vEnableMipMap)) {
      95                 :           0 :             res.reset();
      96                 :           0 :         }
      97                 :           0 :         return res;
      98                 :           0 :     }
      99                 :             : #ifdef STB_IMAGE_READER_INCLUDE
     100                 :             :     // wrap (repeat|mirror|clamp), filter (linear|nearest)
     101                 :             :     static TexturePtr createFromFile(const std::string& vFilePathName, bool vInvertY, std::string vWrap, std::string vFilter, bool vEnableMipMap) {
     102                 :             :         auto res = std::make_shared<Texture>();
     103                 :             :         res->m_This = res;
     104                 :             :         if (!res->initFromFile(vFilePathName, vInvertY, vWrap, vFilter, vEnableMipMap)) {
     105                 :             :             res.reset();
     106                 :             :         }
     107                 :             :         return res;
     108                 :             :     }
     109                 :             : #endif  // STB_IMAGE_READER_INCLUDE
     110                 :             : 
     111                 :             : private:
     112                 :             :     TextureWeak m_This;
     113                 :             :     GLuint m_TexId = 0U;
     114                 :             :     bool m_EnableMipMap = false;
     115                 :             :     GLsizei m_Width = 0U;
     116                 :             :     GLsizei m_Height = 0U;
     117                 :             :     GLuint m_ChannelsCount = 0U;
     118                 :             :     GLenum m_Format = GL_RGBA;
     119                 :             :     GLenum m_InternalFormat = GL_RGBA32F;
     120                 :             :     GLenum m_PixelFormat = GL_FLOAT;
     121                 :             :     GLenum m_WrapS = GL_REPEAT;
     122                 :             :     GLenum m_WrapT = GL_REPEAT;
     123                 :             :     GLenum m_MinFilter = GL_LINEAR_MIPMAP_LINEAR;
     124                 :             :     GLenum m_MagFilter = GL_LINEAR;
     125                 :             : 
     126                 :             : public:
     127                 :             :     Texture() = default;
     128                 :           0 :     ~Texture() { unit(); }
     129                 :           0 :     bool initEmpty(const GLsizei vSx, const GLsizei vSy, const std::string vWrap, const std::string vFilter, const bool vEnableMipMap) {
     130                 :           0 :         assert(vSx > 0);
     131                 :           0 :         assert(vSy > 0);
     132                 :           0 :         m_Width = vSx;
     133                 :           0 :         m_Height = vSy;
     134                 :           0 :         m_EnableMipMap = vEnableMipMap;
     135                 :           0 :         glGenTextures(1, &m_TexId);
     136                 :           0 :         CheckGLErrors;
     137                 :           0 :         glBindTexture(GL_TEXTURE_2D, m_TexId);
     138                 :           0 :         CheckGLErrors;
     139                 :           0 :         m_setFormat(GL_FLOAT, 4);
     140                 :           0 :         glPixelStorei(GL_UNPACK_ALIGNMENT, 1); 
     141                 :           0 :         glTexImage2D(GL_TEXTURE_2D, 0, m_InternalFormat, vSx, vSy, 0, m_Format, GL_FLOAT, nullptr);
     142                 :           0 :         CheckGLErrors;
     143                 :           0 :         glFinish();
     144                 :           0 :         CheckGLErrors;
     145                 :           0 :         m_setParameters(vWrap, vFilter, vEnableMipMap);
     146                 :           0 :         glFinish();
     147                 :           0 :         CheckGLErrors;
     148                 :           0 :         glBindTexture(GL_TEXTURE_2D, 0);
     149                 :           0 :         CheckGLErrors;
     150                 :           0 :         return check();
     151                 :           0 :     }
     152                 :             :     // wrap (repeat|mirror|clamp), filter (linear|nearest)
     153                 :             :     bool initFromBuffer(
     154                 :             :         const uint8_t* vBuffer,
     155                 :             :         const GLsizei vSx,
     156                 :             :         const GLsizei vSy,
     157                 :             :         const GLenum vInternalFormat,
     158                 :             :         const GLenum vFormat,
     159                 :             :         const GLenum vPixelFormat,
     160                 :             :         const std::string vWrap,
     161                 :             :         const std::string vFilter,
     162                 :           0 :         const bool vEnableMipMap) {
     163                 :           0 :         assert(vBuffer != nullptr);
     164                 :           0 :         assert(vSx > 0);
     165                 :           0 :         assert(vSy > 0);
     166                 :           0 :         m_Width = vSx;
     167                 :           0 :         m_Height = vSy;
     168                 :           0 :         glGenTextures(1, &m_TexId);
     169                 :           0 :         CheckGLErrors;
     170                 :           0 :         glBindTexture(GL_TEXTURE_2D, m_TexId);
     171                 :           0 :         CheckGLErrors;
     172                 :           0 :         m_InternalFormat = vInternalFormat;
     173                 :           0 :         m_Format = vFormat;
     174                 :           0 :         m_PixelFormat = vPixelFormat;
     175                 :           0 :         glPixelStorei(GL_UNPACK_ALIGNMENT, 1); 
     176                 :           0 :         glTexImage2D(GL_TEXTURE_2D, 0, m_InternalFormat, m_Width, m_Height, 0, m_Format, m_PixelFormat, vBuffer);
     177                 :           0 :         CheckGLErrors;
     178                 :           0 :         glFinish();
     179                 :           0 :         CheckGLErrors;
     180                 :           0 :         m_setParameters(vWrap, vFilter, vEnableMipMap);
     181                 :           0 :         glFinish();
     182                 :           0 :         CheckGLErrors;
     183                 :           0 :         glBindTexture(GL_TEXTURE_2D, 0);
     184                 :           0 :         CheckGLErrors;
     185                 :           0 :         return check();
     186                 :           0 :     }
     187                 :             :     // wrap (repeat|mirror|clamp), filter (linear|nearest)
     188                 :             :     bool initFromBuffer(
     189                 :             :         const uint8_t* vBuffer,
     190                 :             :         const GLsizei vSx,
     191                 :             :         const GLsizei vSy,
     192                 :             :         const GLint vChannelsCount,
     193                 :             :         const GLenum vPixelFormat,
     194                 :             :         const std::string vWrap,
     195                 :             :         const std::string vFilter,
     196                 :           0 :         const bool vEnableMipMap) {
     197                 :           0 :         assert(vBuffer != nullptr);
     198                 :           0 :         assert(vSx > 0);
     199                 :           0 :         assert(vSy > 0);
     200                 :           0 :         assert(vChannelsCount > 0);
     201                 :           0 :         m_Width = vSx;
     202                 :           0 :         m_Height = vSy;
     203                 :           0 :         glGenTextures(1, &m_TexId);
     204                 :           0 :         CheckGLErrors;
     205                 :           0 :         glBindTexture(GL_TEXTURE_2D, m_TexId);
     206                 :           0 :         CheckGLErrors;
     207                 :           0 :         m_setFormat(vPixelFormat, vChannelsCount);
     208                 :           0 :         glPixelStorei(GL_UNPACK_ALIGNMENT, 1); 
     209                 :           0 :         glTexImage2D(GL_TEXTURE_2D, 0, m_InternalFormat, m_Width, m_Height, 0, m_Format, m_PixelFormat, vBuffer);
     210                 :           0 :         CheckGLErrors;
     211                 :           0 :         glFinish();
     212                 :           0 :         CheckGLErrors;
     213                 :           0 :         m_setParameters(vWrap, vFilter, vEnableMipMap);
     214                 :           0 :         glFinish();
     215                 :           0 :         CheckGLErrors;
     216                 :           0 :         glBindTexture(GL_TEXTURE_2D, 0);
     217                 :           0 :         CheckGLErrors;
     218                 :           0 :         return check();
     219                 :           0 :     }
     220                 :             : #ifdef STB_IMAGE_READER_INCLUDE
     221                 :             :     // wrap (repeat|mirror|clamp), filter (linear|nearest)
     222                 :             :     bool initFromFile(
     223                 :             :         const std::string& vFilePathName,
     224                 :             :         const bool vInvertY,
     225                 :             :         const std::string vWrap,
     226                 :             :         const std::string vFilter,
     227                 :             :         const bool vEnableMipMap) {
     228                 :             :         assert(!vFilePathName.empty());
     229                 :             :         stbi_set_flip_vertically_on_load(vInvertY);
     230                 :             :         auto w = 0;
     231                 :             :         auto h = 0;
     232                 :             :         auto chans = 0;
     233                 :             :         auto buffer = stbi_load(vFilePathName.c_str(), &w, &h, &chans, 0);
     234                 :             :         if (buffer) {
     235                 :             :             stbi_image_free(buffer);
     236                 :             :             if (chans == 4) {
     237                 :             :                 buffer = stbi_load(vFilePathName.c_str(), &w, &h, &chans, STBI_rgb_alpha);
     238                 :             :             } else if (chans == 3) {
     239                 :             :                 buffer = stbi_load(vFilePathName.c_str(), &w, &h, &chans, STBI_rgb);
     240                 :             :             } else if (chans == 2) {
     241                 :             :                 buffer = stbi_load(vFilePathName.c_str(), &w, &h, &chans, STBI_grey_alpha);
     242                 :             :             } else if (chans == 1) {
     243                 :             :                 buffer = stbi_load(vFilePathName.c_str(), &w, &h, &chans, STBI_grey);
     244                 :             :             }
     245                 :             :         }
     246                 :             :         if (buffer) {
     247                 :             :             m_Width = w;
     248                 :             :             m_Height = h;
     249                 :             :             glGenTextures(1, &m_TexId);
     250                 :             :             CheckGLErrors;
     251                 :             :             glBindTexture(GL_TEXTURE_2D, m_TexId);
     252                 :             :             CheckGLErrors;
     253                 :             :             glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
     254                 :             :             CheckGLErrors;
     255                 :             :             m_setFormat(GL_UNSIGNED_BYTE, chans);
     256                 :             :             glPixelStorei(GL_UNPACK_ALIGNMENT, 1); 
     257                 :             :             glTexImage2D(GL_TEXTURE_2D, 0, m_InternalFormat, m_Width, m_Height, 0, m_Format, m_PixelFormat, buffer);
     258                 :             :             CheckGLErrors;
     259                 :             :             glFinish();
     260                 :             :             CheckGLErrors;
     261                 :             :             m_setParameters(vWrap, vFilter, vEnableMipMap);
     262                 :             :             glFinish();
     263                 :             :             CheckGLErrors;
     264                 :             :             glBindTexture(GL_TEXTURE_2D, 0);
     265                 :             :             CheckGLErrors;
     266                 :             :             stbi_image_free(buffer);
     267                 :             :         } 
     268                 :             :         return check();
     269                 :             :     }
     270                 :             : #endif // STB_IMAGE_READER_INCLUDE
     271                 :           0 :     void updateMipMaping() {
     272                 :           0 :         if (m_EnableMipMap) {
     273                 :           0 : #ifdef PROFILER_SCOPED
     274                 :           0 :             PROFILER_SCOPED("Opengl", "glGenerateMipmap %u", m_TexId);
     275                 :           0 : #endif
     276                 :           0 :             glGenerateMipmap(GL_TEXTURE_2D);
     277                 :           0 :             CheckGLErrors;
     278                 :           0 :             glFinish();
     279                 :           0 :             CheckGLErrors;
     280                 :           0 :         }
     281                 :           0 :     }
     282                 :           0 :     bool resize(const GLsizei& vSx, const GLsizei& vSy) {
     283                 :           0 :         if (m_TexId > 0U) {
     284                 :           0 :             glBindTexture(GL_TEXTURE_2D, m_TexId);
     285                 :           0 :             CheckGLErrors;
     286                 :           0 :             glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, vSx, vSy, 0, GL_RGBA, GL_FLOAT, nullptr);
     287                 :           0 :             CheckGLErrors;
     288                 :           0 :             glFinish();
     289                 :           0 :             glBindTexture(GL_TEXTURE_2D, 0);
     290                 :           0 :             CheckGLErrors;
     291                 :           0 :             return true;
     292                 :           0 :         }
     293                 :           0 :         return false;
     294                 :           0 :     }
     295                 :           0 :     void unit() {
     296                 :           0 :         glDeleteTextures(1, &m_TexId);
     297                 :           0 :         CheckGLErrors;
     298                 :           0 :     }
     299                 :           0 :     bool check() { return (glIsTexture(m_TexId) == GL_TRUE); }
     300                 :           0 :     GLuint getTexId() const { return m_TexId; }
     301                 :           0 :     std::array<GLsizei, 2U> getSize() const { return {m_Width, m_Height}; }
     302                 :             : 
     303                 :             : #ifdef STB_IMAGE_WRITER_INCLUDE
     304                 :             :     bool saveToPng(const std::string& vFilePathName) const {
     305                 :             :         if (vFilePathName.empty() || m_TexId == 0)
     306                 :             :             return false;
     307                 :             : 
     308                 :             :         // 1) Dimensions
     309                 :             :         glBindTexture(GL_TEXTURE_2D, m_TexId);
     310                 :             :         GLint w = 0, h = 0;
     311                 :             :         glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &w);
     312                 :             :         glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &h);
     313                 :             :         if (w <= 0 || h <= 0)
     314                 :             :             return false;
     315                 :             : 
     316                 :             :         // 2) Sauvegarde ?tat pack + configuration propre
     317                 :             :         GLint prevAlign = 0, prevRowLen = 0, prevSkipRows = 0, prevSkipPix = 0;
     318                 :             :         glGetIntegerv(GL_PACK_ALIGNMENT, &prevAlign);
     319                 :             :         glGetIntegerv(GL_PACK_ROW_LENGTH, &prevRowLen);
     320                 :             :         glGetIntegerv(GL_PACK_SKIP_ROWS, &prevSkipRows);
     321                 :             :         glGetIntegerv(GL_PACK_SKIP_PIXELS, &prevSkipPix);
     322                 :             : 
     323                 :             :         glPixelStorei(GL_PACK_ALIGNMENT, 1);
     324                 :             :         glPixelStorei(GL_PACK_ROW_LENGTH, 0);
     325                 :             :         glPixelStorei(GL_PACK_SKIP_ROWS, 0);
     326                 :             :         glPixelStorei(GL_PACK_SKIP_PIXELS, 0);
     327                 :             : 
     328                 :             :         // 3) Lecture RGBA8
     329                 :             :         std::vector<unsigned char> pixels(static_cast<size_t>(w) * static_cast<size_t>(h) * 4u);
     330                 :             :         glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels.data());
     331                 :             : 
     332                 :             :         // 4) ?criture PNG (top-left) : flip vertical pour correspondre aux viewers
     333                 :             :         stbi_flip_vertically_on_write(1);
     334                 :             :         const int ok = stbi_write_png(vFilePathName.c_str(), w, h, 4, pixels.data(), w * 4);
     335                 :             : 
     336                 :             :         // 5) Restauration ?tat pack
     337                 :             :         glPixelStorei(GL_PACK_ALIGNMENT, prevAlign);
     338                 :             :         glPixelStorei(GL_PACK_ROW_LENGTH, prevRowLen);
     339                 :             :         glPixelStorei(GL_PACK_SKIP_ROWS, prevSkipRows);
     340                 :             :         glPixelStorei(GL_PACK_SKIP_PIXELS, prevSkipPix);
     341                 :             : 
     342                 :             :         return ok != 0;
     343                 :             :     }
     344                 :             : #endif//STB_IMAGE_WRITER_INCLUDE
     345                 :             : 
     346                 :             : private:
     347                 :             :     // wrap (repeat|mirror|clamp), filter (linear|nearest)
     348                 :           0 :     void m_setParameters(const std::string vWrap, const std::string vFilter, const bool vEnableMipMap) {
     349                 :           0 :         if (vWrap == "repeat") {
     350                 :           0 :             m_WrapS = GL_REPEAT;
     351                 :           0 :             m_WrapT = GL_REPEAT;
     352                 :           0 :             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, m_WrapS);
     353                 :           0 :             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, m_WrapT);
     354                 :           0 :             CheckGLErrors;
     355                 :           0 :         } else if (vWrap == "mirror") {
     356                 :           0 :             m_WrapS = GL_MIRRORED_REPEAT;
     357                 :           0 :             m_WrapT = GL_MIRRORED_REPEAT;
     358                 :           0 :             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, m_WrapS);
     359                 :           0 :             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, m_WrapT);
     360                 :           0 :             CheckGLErrors;
     361                 :           0 :         } else if (vWrap == "clamp") {
     362                 :           0 :             m_WrapS = GL_CLAMP_TO_EDGE;
     363                 :           0 :             m_WrapT = GL_CLAMP_TO_EDGE;
     364                 :           0 :             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, m_WrapS);
     365                 :           0 :             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, m_WrapT);
     366                 :           0 :             CheckGLErrors;
     367                 :           0 :         } else {
     368                 :           0 :             m_WrapS = GL_CLAMP_TO_EDGE;
     369                 :           0 :             m_WrapT = GL_CLAMP_TO_EDGE;
     370                 :           0 :             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, m_WrapS);
     371                 :           0 :             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, m_WrapT);
     372                 :           0 :             CheckGLErrors;
     373                 :           0 :         }
     374                 :           0 : 
     375                 :           0 :         if (vFilter == "linear") {
     376                 :           0 :             if (vEnableMipMap) {
     377                 :           0 :                 m_MinFilter = GL_LINEAR_MIPMAP_LINEAR;
     378                 :           0 :                 m_MagFilter = GL_LINEAR;
     379                 :           0 :                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, m_MinFilter);
     380                 :           0 :                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, m_MagFilter);
     381                 :           0 :                 CheckGLErrors;
     382                 :           0 :             } else {
     383                 :           0 :                 m_MinFilter = GL_LINEAR;
     384                 :           0 :                 m_MagFilter = GL_LINEAR;
     385                 :           0 :                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, m_MinFilter);
     386                 :           0 :                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, m_MagFilter);
     387                 :           0 :                 CheckGLErrors;
     388                 :           0 :             }
     389                 :           0 :         } else if (vFilter == "nearest") {
     390                 :           0 :             if (vEnableMipMap) {
     391                 :           0 :                 m_MinFilter = GL_NEAREST_MIPMAP_NEAREST;
     392                 :           0 :                 m_MagFilter = GL_NEAREST;
     393                 :           0 :                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, m_MinFilter);
     394                 :           0 :                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, m_MagFilter);
     395                 :           0 :                 CheckGLErrors;
     396                 :           0 :             } else {
     397                 :           0 :                 m_MinFilter = GL_NEAREST;
     398                 :           0 :                 m_MagFilter = GL_NEAREST;
     399                 :           0 :                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, m_MinFilter);
     400                 :           0 :                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, m_MagFilter);
     401                 :           0 :                 CheckGLErrors;
     402                 :           0 :             }
     403                 :           0 :         } else {
     404                 :           0 :             m_MinFilter = GL_LINEAR;
     405                 :           0 :             m_MagFilter = GL_LINEAR;
     406                 :           0 :             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, m_MinFilter);
     407                 :           0 :             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, m_MagFilter);
     408                 :           0 :             CheckGLErrors;
     409                 :           0 :         }
     410                 :           0 :         if (m_EnableMipMap) {
     411                 :           0 :             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
     412                 :           0 :             CheckGLErrors;
     413                 :           0 :             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 8);
     414                 :           0 :             CheckGLErrors;
     415                 :           0 :             updateMipMaping();
     416                 :           0 :         } else {
     417                 :           0 :             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
     418                 :           0 :             CheckGLErrors;
     419                 :           0 :             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
     420                 :           0 :             CheckGLErrors;
     421                 :           0 :         }
     422                 :           0 :     }
     423                 :           0 :     void m_setFormat(const GLenum vPixelFormat, const GLint& vChannelsCount) {
     424                 :           0 :         assert(
     425                 :           0 :             vPixelFormat == GL_UNSIGNED_BYTE ||  // format BYTE
     426                 :           0 :             vPixelFormat == GL_FLOAT);  // format FLOAT
     427                 :           0 :         m_PixelFormat = vPixelFormat;
     428                 :           0 :         m_ChannelsCount = vChannelsCount;
     429                 :           0 :         // 1:r, 2:rg, 3:rgb, 4:rgba
     430                 :           0 :         switch (vChannelsCount) {
     431                 :           0 :             case 1: {
     432                 :           0 :                 m_Format = GL_RED;
     433                 :           0 :                 if (vPixelFormat == GL_UNSIGNED_BYTE) {
     434                 :           0 :                     m_InternalFormat = GL_R8;
     435                 :           0 :                 } else if (vPixelFormat == GL_FLOAT) {
     436                 :           0 :                     m_InternalFormat = GL_R32F;
     437                 :           0 :                 }
     438                 :           0 :             } break;
     439                 :           0 :             case 2: {
     440                 :           0 :                 m_Format = GL_RG;
     441                 :           0 :                 if (vPixelFormat == GL_UNSIGNED_BYTE) {
     442                 :           0 :                     m_InternalFormat = GL_RG8;
     443                 :           0 :                 } else if (vPixelFormat == GL_FLOAT) {
     444                 :           0 :                     m_InternalFormat = GL_RG32F;
     445                 :           0 :                 }
     446                 :           0 :             } break;
     447                 :           0 :             case 3: {
     448                 :           0 :                 m_Format = GL_RGB;
     449                 :           0 :                 if (vPixelFormat == GL_UNSIGNED_BYTE) {
     450                 :           0 :                     m_InternalFormat = GL_RGB8;
     451                 :           0 :                 } else if (vPixelFormat == GL_FLOAT) {
     452                 :           0 :                     m_InternalFormat = GL_RGB32F;
     453                 :           0 :                 }
     454                 :           0 :             } break;
     455                 :           0 :             case 4: {
     456                 :           0 :                 m_Format = GL_RGBA;
     457                 :           0 :                 if (vPixelFormat == GL_UNSIGNED_BYTE) {
     458                 :           0 :                     m_InternalFormat = GL_RGBA8;
     459                 :           0 :                 } else if (vPixelFormat == GL_FLOAT) {
     460                 :           0 :                     m_InternalFormat = GL_RGBA32F;
     461                 :           0 :                 }
     462                 :           0 :             } break;
     463                 :           0 :         }
     464                 :           0 :     }
     465                 :             : };
     466                 :             : class Texture2DArray;
     467                 :             : typedef std::shared_ptr<Texture2DArray> Texture2DArrayPtr;
     468                 :             : typedef std::weak_ptr<Texture2DArray> Texture2DArrayWeak;
     469                 :             : 
     470                 :             : class Texture2DArray {
     471                 :             : public:
     472                 :             :     static Texture2DArrayPtr create(
     473                 :             :         const GLsizei vSx,
     474                 :             :         const GLsizei vSy,
     475                 :             :         const GLsizei vLayers,
     476                 :             :         const GLenum vInternalFormat,  // ex: GL_RGBA8, GL_R16F, ...
     477                 :             :         const GLenum vAllocFormat,     // ex: GL_RGBA, GL_RED, GL_RG
     478                 :             :         const GLenum vPixelFormat,     // ex: GL_UNSIGNED_BYTE, GL_HALF_FLOAT, GL_FLOAT
     479                 :             :         const std::string& vWrap,
     480                 :             :         const std::string& vFilter,
     481                 :           0 :         const bool vUseMipMapping) {
     482                 :           0 :         auto res = std::make_shared<Texture2DArray>();
     483                 :           0 :         res->m_This = res;
     484                 :           0 :         if (!res->init(vSx, vSy, vLayers, vInternalFormat, vAllocFormat, vPixelFormat, vWrap, vFilter, vUseMipMapping)) {
     485                 :           0 :             res.reset();
     486                 :           0 :         }
     487                 :           0 :         return res;
     488                 :           0 :     }
     489                 :             : 
     490                 :             : private:
     491                 :             :     GLuint m_TexId = 0U;
     492                 :             : 
     493                 :             :     GLsizei m_Width = 0;
     494                 :             :     GLsizei m_Height = 0;
     495                 :             :     GLsizei m_Layers = 0;
     496                 :             : 
     497                 :             :     GLenum m_InternalFormat = GL_RGBA8;  // stockage interne
     498                 :             :     GLenum m_AllocFormat = GL_RGBA;      // format d?claration
     499                 :             :     GLenum m_PixelFormat = GL_UNSIGNED_BYTE;
     500                 :             : 
     501                 :             :     std::string m_wrap;
     502                 :             :     std::string m_filter;
     503                 :             : 
     504                 :             :     std::vector<int> m_FreeList;  // pile de layers libres
     505                 :             : 
     506                 :             :     bool m_useMipMapping = false;
     507                 :             :     GLsizei m_MipCount = 0;
     508                 :             :     bool m_useImmutable = false;        // vrai si glTexStorage3D est dispo et choisi
     509                 :             :     std::vector<bool> m_LevelDeclared;  // niveaux (L) ?disponibles? pour sampling
     510                 :             :     GLint m_MinDeclaredLevel = -1;
     511                 :             :     GLint m_MaxDeclaredLevel = -1;
     512                 :             : 
     513                 :             :     Texture2DArrayWeak m_This;
     514                 :             : 
     515                 :             : public:
     516                 :             :     Texture2DArray() = default;
     517                 :           0 :     ~Texture2DArray() { unit(); }
     518                 :             : 
     519                 :             :     bool init(
     520                 :             :         const GLsizei vSx,
     521                 :             :         const GLsizei vSy,
     522                 :             :         const GLsizei vLayers,
     523                 :             :         const GLenum vInternalFormat,
     524                 :             :         const GLenum vAllocFormat,
     525                 :             :         const GLenum vPixelFormat,
     526                 :             :         const std::string& vWrap,
     527                 :             :         const std::string& vFilter,
     528                 :           0 :         const bool vUseMipMapping) {
     529                 :           0 :         unit();
     530                 :           0 :         assert(vSx > 0 && vSy > 0 && vLayers > 0);
     531                 :           0 :         m_Width = vSx;
     532                 :           0 :         m_Height = vSy;
     533                 :           0 :         m_Layers = vLayers;
     534                 :           0 :         m_InternalFormat = vInternalFormat;
     535                 :           0 :         m_AllocFormat = vAllocFormat;
     536                 :           0 :         m_PixelFormat = vPixelFormat;
     537                 :           0 :         m_wrap = vWrap;
     538                 :           0 :         m_filter = vFilter;
     539                 :           0 :         m_useMipMapping = vUseMipMapping;
     540                 :           0 : 
     541                 :           0 :         GLint maxLayers = 0;
     542                 :           0 :         glGetIntegerv(GL_MAX_ARRAY_TEXTURE_LAYERS, &maxLayers);
     543                 :           0 :         if (vLayers > maxLayers) {
     544                 :           0 : #ifdef EZ_TOOLS_LOG
     545                 :           0 :             LogVarError("The layers count is superior to the max admissible of %i for your GPU", maxLayers);
     546                 :           0 : #endif
     547                 :           0 :             return false;
     548                 :           0 :         }
     549                 :           0 : 
     550                 :           0 :         glGenTextures(1, &m_TexId);
     551                 :           0 :         CheckGLErrors;
     552                 :           0 :         if (m_TexId == 0U) {
     553                 :           0 :             return false;
     554                 :           0 :         }
     555                 :           0 : 
     556                 :           0 :         // Mip count th?orique
     557                 :           0 :         m_MipCount = m_useMipMapping ? m_computeMipCount(m_Width, m_Height) : 1;
     558                 :           0 :         m_LevelDeclared.assign((size_t)m_MipCount, false);
     559                 :           0 :         m_MinDeclaredLevel = -1;
     560                 :           0 :         m_MaxDeclaredLevel = -1;
     561                 :           0 : 
     562                 :           0 :         // Param?tres de base (wrap/filter + fen?tre LOD initiale)
     563                 :           0 :         m_setParameters(m_wrap, m_filter);
     564                 :           0 : 
     565                 :           0 :         // D?tection simple de glTexStorage3D ? l?ex?cution
     566                 :           0 :         m_useImmutable = (reinterpret_cast<void*>(glTexStorage3D) != nullptr);
     567                 :           0 : 
     568                 :           0 :         glBindTexture(GL_TEXTURE_2D_ARRAY, m_TexId);
     569                 :           0 :         CheckGLErrors;
     570                 :           0 : 
     571                 :           0 :         if (m_useImmutable) {
     572                 :           0 :             // Allocation immuable de tous les niveaux
     573                 :           0 :             glTexStorage3D(GL_TEXTURE_2D_ARRAY, m_MipCount, m_InternalFormat, m_Width, m_Height, m_Layers);
     574                 :           0 :             CheckGLErrors;
     575                 :           0 : 
     576                 :           0 :             // Rien n?est ?rempli? mais tous les niveaux existent. On n?active la fen?tre [BASE..MAX]
     577                 :           0 :             // qu?une fois des niveaux marqu?s comme d?clar?s (upload effectu?s).
     578                 :           0 :             // On pourrait au choix marquer level 0 comme d?clar? imm?diatement si tu veux sampler tout de suite.
     579                 :           0 :         } else {
     580                 :           0 :             // Fallback : aucune alloc ici, on allouera paresseusement par niveau via TexImage3D
     581                 :           0 :             // ? la premi?re demande (m_ensureLevelDeclared).
     582                 :           0 :         }
     583                 :           0 : 
     584                 :           0 :         glBindTexture(GL_TEXTURE_2D_ARRAY, 0);
     585                 :           0 :         CheckGLErrors;
     586                 :           0 : 
     587                 :           0 :         // Pr?pare free-list
     588                 :           0 :         m_FreeList.clear();
     589                 :           0 :         m_FreeList.reserve((size_t)vLayers);
     590                 :           0 :         for (int i = vLayers - 1; i >= 0; --i) {
     591                 :           0 :             m_FreeList.push_back(i);
     592                 :           0 :         }
     593                 :           0 : 
     594                 :           0 :         return check();
     595                 :           0 :     }
     596                 :             : 
     597                 :           0 :     void unit() {
     598                 :           0 :         if (m_TexId != 0U) {
     599                 :           0 :             glDeleteTextures(1, &m_TexId);
     600                 :           0 :             CheckGLErrors;
     601                 :           0 :             m_TexId = 0U;
     602                 :           0 :         }
     603                 :           0 :         m_Width = m_Height = m_Layers = 0;
     604                 :           0 :         m_InternalFormat = GL_RGBA8;
     605                 :           0 :         m_AllocFormat = GL_RGBA;
     606                 :           0 :         m_PixelFormat = GL_UNSIGNED_BYTE;
     607                 :           0 :         m_MipCount = 0;
     608                 :           0 :         m_useImmutable = false;
     609                 :           0 :         m_FreeList.clear();
     610                 :           0 :         m_LevelDeclared.clear();
     611                 :           0 :         m_MinDeclaredLevel = m_MaxDeclaredLevel = -1;
     612                 :           0 :     }
     613                 :             : 
     614                 :             :     // Alloue une layer libre et uploade le mip 'vLevel' avec 'vpPixels'
     615                 :             :     // Retourne l'index de layer :
     616                 :             :     // -1 : erreur
     617                 :             :     // -2 : saturation
     618                 :           0 :     int addLayer(const GLsizei vLevel, const void* vpPixels) {
     619                 :           0 :         if (m_TexId == 0U || vpPixels == nullptr) {
     620                 :           0 :             return -1;
     621                 :           0 :         }
     622                 :           0 :         if (vLevel < 0 || vLevel >= m_MipCount) {
     623                 :           0 :             return -1;
     624                 :           0 :         }
     625                 :           0 :         if (m_FreeList.empty()) {
     626                 :           0 :             return -2;
     627                 :           0 :         }
     628                 :           0 : 
     629                 :           0 :         const int layer = m_FreeList.back();
     630                 :           0 :         m_FreeList.pop_back();
     631                 :           0 : 
     632                 :           0 :         if (!m_ensureLevelDeclared(vLevel)) {
     633                 :           0 :             m_FreeList.push_back(layer);
     634                 :           0 :             return -1;
     635                 :           0 :         }
     636                 :           0 : 
     637                 :           0 :         const GLsizei w = std::max<GLsizei>(1, m_Width >> vLevel);
     638                 :           0 :         const GLsizei h = std::max<GLsizei>(1, m_Height >> vLevel);
     639                 :           0 : 
     640                 :           0 :         glBindTexture(GL_TEXTURE_2D_ARRAY, m_TexId);
     641                 :           0 :         CheckGLErrors;
     642                 :           0 :         glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
     643                 :           0 :         CheckGLErrors;
     644                 :           0 :         glTexSubImage3D(GL_TEXTURE_2D_ARRAY, vLevel, 0, 0, layer, w, h, 1, m_AllocFormat, m_PixelFormat, vpPixels);
     645                 :           0 :         CheckGLErrors;
     646                 :           0 :         glBindTexture(GL_TEXTURE_2D_ARRAY, 0);
     647                 :           0 :         CheckGLErrors;
     648                 :           0 : 
     649                 :           0 :         m_enableMipTrilinearIfPossible(m_filter);
     650                 :           0 : 
     651                 :           0 :         return layer;
     652                 :           0 :     }
     653                 :             : 
     654                 :             :     // Met ? jour un mip sur une layer existante
     655                 :           0 :     bool uploadLayer(const GLint vLayer, const GLsizei vLevel, const void* vpPixels) {
     656                 :           0 :         if (m_TexId == 0U || vpPixels == nullptr) {
     657                 :           0 :             return false;
     658                 :           0 :         }
     659                 :           0 :         if (vLayer < 0 || vLayer >= m_Layers) {
     660                 :           0 :             return false;
     661                 :           0 :         }
     662                 :           0 :         if (vLevel < 0 || vLevel >= m_MipCount) {
     663                 :           0 :             return false;
     664                 :           0 :         }
     665                 :           0 :         if (!m_ensureLevelDeclared(vLevel)) {
     666                 :           0 :             return false;
     667                 :           0 :         }
     668                 :           0 : 
     669                 :           0 :         const GLsizei w = std::max<GLsizei>(1, m_Width >> vLevel);
     670                 :           0 :         const GLsizei h = std::max<GLsizei>(1, m_Height >> vLevel);
     671                 :           0 : 
     672                 :           0 :         glBindTexture(GL_TEXTURE_2D_ARRAY, m_TexId);
     673                 :           0 :         CheckGLErrors;
     674                 :           0 :         glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
     675                 :           0 :         CheckGLErrors;
     676                 :           0 :         glTexSubImage3D(GL_TEXTURE_2D_ARRAY, vLevel, 0, 0, vLayer, w, h, 1, m_AllocFormat, m_PixelFormat, vpPixels);
     677                 :           0 :         CheckGLErrors;
     678                 :           0 :         glBindTexture(GL_TEXTURE_2D_ARRAY, 0);
     679                 :           0 :         CheckGLErrors;
     680                 :           0 : 
     681                 :           0 :         m_enableMipTrilinearIfPossible(m_filter);
     682                 :           0 :         return true;
     683                 :           0 :     }
     684                 :             : 
     685                 :             :     // Lib?re la layer (r?utilisable par addLayer)
     686                 :           0 :     void removeLayer(const GLint vLayer) {
     687                 :           0 :         if (m_TexId == 0U) {
     688                 :           0 :             return;
     689                 :           0 :         }
     690                 :           0 :         if (vLayer < 0 || vLayer >= m_Layers) {
     691                 :           0 :             return;
     692                 :           0 :         }
     693                 :           0 :         const bool found = (std::find(m_FreeList.begin(), m_FreeList.end(), vLayer) != m_FreeList.end());
     694                 :           0 :         if (!found) {
     695                 :           0 :             m_FreeList.push_back(vLayer);
     696                 :           0 :         }
     697                 :           0 :     }
     698                 :             : 
     699                 :             :     // Param?tres (wrap/filter) ? safe ? appeler ? tout moment
     700                 :           0 :     void setParameters(const std::string& vWrap, const std::string& vFilter) {
     701                 :           0 :         if (m_TexId == 0U) {
     702                 :           0 :             return;
     703                 :           0 :         }
     704                 :           0 :         m_setParameters(vWrap, vFilter);
     705                 :           0 :         m_enableMipTrilinearIfPossible(vFilter);
     706                 :           0 :     }
     707                 :             : 
     708                 :           0 :     bool check() const { return (glIsTexture(m_TexId) == GL_TRUE); }
     709                 :           0 :     GLuint getTexId() const { return m_TexId; }
     710                 :           0 :     GLsizei getWidth() const { return m_Width; }
     711                 :           0 :     GLsizei getHeight() const { return m_Height; }
     712                 :           0 :     GLsizei getLayers() const { return m_Layers; }
     713                 :           0 :     GLsizei getMipCount() const { return m_MipCount; }
     714                 :             : 
     715                 :             : private:
     716                 :           0 :     static GLsizei m_computeMipCount(const GLsizei vSx, const GLsizei vSy) {
     717                 :           0 :         auto s = (vSx > vSy ? vSx : vSy);
     718                 :           0 :         GLsizei m = 1;
     719                 :           0 :         while (s > 1) {
     720                 :           0 :             s >>= 1;
     721                 :           0 :             ++m;
     722                 :           0 :         }
     723                 :           0 :         return m;
     724                 :           0 :     }
     725                 :             : 
     726                 :           0 :     void m_updateLodClamp() {
     727                 :           0 :         if (m_TexId == 0U) {
     728                 :           0 :             return;
     729                 :           0 :         }
     730                 :           0 :         if (m_MinDeclaredLevel < 0 || m_MaxDeclaredLevel < 0) {
     731                 :           0 :             return;
     732                 :           0 :         }
     733                 :           0 :         glBindTexture(GL_TEXTURE_2D_ARRAY, m_TexId);
     734                 :           0 :         CheckGLErrors;
     735                 :           0 :         glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_BASE_LEVEL, m_MinDeclaredLevel);
     736                 :           0 :         CheckGLErrors;
     737                 :           0 :         glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAX_LEVEL, m_MaxDeclaredLevel);
     738                 :           0 :         CheckGLErrors;
     739                 :           0 :         glBindTexture(GL_TEXTURE_2D_ARRAY, 0);
     740                 :           0 :         CheckGLErrors;
     741                 :           0 :     }
     742                 :             : 
     743                 :           0 :     bool m_ensureLevelDeclared(const GLsizei vLevel) {
     744                 :           0 :         if (vLevel < 0 || vLevel >= m_MipCount) {
     745                 :           0 :             return false;
     746                 :           0 :         }
     747                 :           0 :         if (m_LevelDeclared.empty()) {
     748                 :           0 :             return false;
     749                 :           0 :         }
     750                 :           0 :         if (m_LevelDeclared[(size_t)vLevel]) {
     751                 :           0 :             m_updateLodClamp();
     752                 :           0 :             return true;
     753                 :           0 :         }
     754                 :           0 : 
     755                 :           0 :         if (!m_useImmutable) {
     756                 :           0 :             // Fallback : on alloue le niveau (toutes layers) avec data=nullptr
     757                 :           0 :             const GLsizei w = std::max<GLsizei>(1, m_Width >> vLevel);
     758                 :           0 :             const GLsizei h = std::max<GLsizei>(1, m_Height >> vLevel);
     759                 :           0 : 
     760                 :           0 :             glBindTexture(GL_TEXTURE_2D_ARRAY, m_TexId);
     761                 :           0 :             CheckGLErrors;
     762                 :           0 :             glTexImage3D(GL_TEXTURE_2D_ARRAY, vLevel, m_InternalFormat, w, h, m_Layers, 0, m_AllocFormat, m_PixelFormat, nullptr);
     763                 :           0 :             CheckGLErrors;
     764                 :           0 :             glBindTexture(GL_TEXTURE_2D_ARRAY, 0);
     765                 :           0 :             CheckGLErrors;
     766                 :           0 :         }  // en immutable, rien ? allouer : les niveaux existent d?j?
     767                 :           0 : 
     768                 :           0 :         m_LevelDeclared[(size_t)vLevel] = true;
     769                 :           0 : 
     770                 :           0 :         if (m_MinDeclaredLevel < 0 || vLevel < m_MinDeclaredLevel) {
     771                 :           0 :             m_MinDeclaredLevel = vLevel;
     772                 :           0 :         }
     773                 :           0 :         if (m_MaxDeclaredLevel < 0 || vLevel > m_MaxDeclaredLevel) {
     774                 :           0 :             m_MaxDeclaredLevel = vLevel;
     775                 :           0 :         }
     776                 :           0 : 
     777                 :           0 :         m_updateLodClamp();
     778                 :           0 :         return true;
     779                 :           0 :     }
     780                 :             : 
     781                 :           0 :     void m_setParameters(const std::string& vWrap, const std::string& vFilter) {
     782                 :           0 :         glBindTexture(GL_TEXTURE_2D_ARRAY, m_TexId);
     783                 :           0 :         CheckGLErrors;
     784                 :           0 : 
     785                 :           0 :         // Wrap
     786                 :           0 :         GLenum wrap = GL_CLAMP_TO_EDGE;
     787                 :           0 :         if (vWrap == "repeat") {
     788                 :           0 :             wrap = GL_REPEAT;
     789                 :           0 :         } else if (vWrap == "mirror") {
     790                 :           0 :             wrap = GL_MIRRORED_REPEAT;
     791                 :           0 :         }
     792                 :           0 :         glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_S, wrap);
     793                 :           0 :         CheckGLErrors;
     794                 :           0 :         glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_T, wrap);
     795                 :           0 :         CheckGLErrors;
     796                 :           0 : 
     797                 :           0 :         // Filter
     798                 :           0 :         const bool linear = (vFilter != "nearest");
     799                 :           0 :         glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, linear ? GL_LINEAR : GL_NEAREST);
     800                 :           0 :         CheckGLErrors;
     801                 :           0 :         glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, linear ? GL_LINEAR : GL_NEAREST);
     802                 :           0 :         CheckGLErrors;
     803                 :           0 : 
     804                 :           0 :         // Fen?tre LOD initiale : [0 .. m_MipCount-1] si mipmap, sinon [0..0].
     805                 :           0 :         const GLint initialBase = 0;
     806                 :           0 :         const GLint initialMax = (m_useMipMapping && m_MipCount > 0) ? (m_MipCount - 1) : 0;
     807                 :           0 :         glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_BASE_LEVEL, initialBase);
     808                 :           0 :         CheckGLErrors;
     809                 :           0 :         glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAX_LEVEL, initialMax);
     810                 :           0 :         CheckGLErrors;
     811                 :           0 : 
     812                 :           0 :         glBindTexture(GL_TEXTURE_2D_ARRAY, 0);
     813                 :           0 :         CheckGLErrors;
     814                 :           0 :     }
     815                 :             : 
     816                 :           0 :     void m_enableMipTrilinearIfPossible(const std::string& vFilter) {
     817                 :           0 :         if (!m_useMipMapping) {
     818                 :           0 :             return;
     819                 :           0 :         }
     820                 :           0 :         if (m_MinDeclaredLevel < 0 || m_MaxDeclaredLevel < 0) {
     821                 :           0 :             return;
     822                 :           0 :         }
     823                 :           0 :         if (m_MaxDeclaredLevel <= m_MinDeclaredLevel) {
     824                 :           0 :             return;  // un seul niveau
     825                 :           0 :         }
     826                 :           0 :         glBindTexture(GL_TEXTURE_2D_ARRAY, m_TexId);
     827                 :           0 :         CheckGLErrors;
     828                 :           0 :         const bool linear = (vFilter != "nearest");
     829                 :           0 :         glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, linear ? GL_LINEAR_MIPMAP_LINEAR : GL_NEAREST_MIPMAP_NEAREST);
     830                 :           0 :         CheckGLErrors;
     831                 :           0 :         glBindTexture(GL_TEXTURE_2D_ARRAY, 0);
     832                 :           0 :         CheckGLErrors;
     833                 :           0 :     }
     834                 :             : };
     835                 :             : 
     836                 :             : }  // namespace gl
     837                 :             : }  // namespace ez
        

Generated by: LCOV version 2.0-1