Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: downloads/RenderSystems/GL/src/OgreGLTexture.cpp @ 1

Last change on this file since 1 was 1, checked in by landauf, 17 years ago
File size: 13.1 KB
Line 
1/*
2-----------------------------------------------------------------------------
3This source file is part of OGRE
4    (Object-oriented Graphics Rendering Engine)
5For the latest info, see http://www.ogre3d.org
6
7Copyright (c) 2000-2006 Torus Knot Software Ltd
8Also see acknowledgements in Readme.html
9
10This program is free software; you can redistribute it and/or modify it under
11the terms of the GNU Lesser General Public License as published by the Free Software
12Foundation; either version 2 of the License, or (at your option) any later
13version.
14
15This program is distributed in the hope that it will be useful, but WITHOUT
16ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
17FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
18
19You should have received a copy of the GNU Lesser General Public License along with
20this program; if not, write to the Free Software Foundation, Inc., 59 Temple
21Place - Suite 330, Boston, MA 02111-1307, USA, or go to
22http://www.gnu.org/copyleft/lesser.txt.
23
24You may alternatively use this source under the terms of a specific version of
25the OGRE Unrestricted License provided you have obtained such a license from
26Torus Knot Software Ltd.
27-----------------------------------------------------------------------------
28*/
29
30#include "OgreGLTexture.h"
31#include "OgreGLSupport.h"
32#include "OgreGLPixelFormat.h"
33#include "OgreGLHardwarePixelBuffer.h"
34
35#include "OgreTextureManager.h"
36#include "OgreImage.h"
37#include "OgreLogManager.h"
38#include "OgreCamera.h"
39#include "OgreException.h"
40#include "OgreRoot.h"
41#include "OgreCodec.h"
42#include "OgreImageCodec.h"
43#include "OgreStringConverter.h"
44#include "OgreBitwise.h"
45
46#include "OgreGLFBORenderTexture.h"
47
48#if OGRE_PLATFORM == OGRE_PLATFORM_WIN32
49#   include <windows.h>
50#   include <wingdi.h>
51#endif
52
53namespace Ogre {
54
55
56
57    GLTexture::GLTexture(ResourceManager* creator, const String& name, 
58        ResourceHandle handle, const String& group, bool isManual, 
59        ManualResourceLoader* loader, GLSupport& support) 
60        : Texture(creator, name, handle, group, isManual, loader),
61        mTextureID(0), mGLSupport(support)
62    {
63    }
64
65
66    GLTexture::~GLTexture()
67    {
68        // have to call this here reather than in Resource destructor
69        // since calling virtual methods in base destructors causes crash
70                if (isLoaded())
71                {
72                        unload(); 
73                }
74                else
75                {
76                        freeInternalResources();
77                }
78    }
79
80    GLenum GLTexture::getGLTextureTarget(void) const
81    {
82        switch(mTextureType)
83        {
84            case TEX_TYPE_1D:
85                return GL_TEXTURE_1D;
86            case TEX_TYPE_2D:
87                return GL_TEXTURE_2D;
88            case TEX_TYPE_3D:
89                return GL_TEXTURE_3D;
90            case TEX_TYPE_CUBE_MAP:
91                return GL_TEXTURE_CUBE_MAP;
92            default:
93                return 0;
94        };
95    }
96
97        //* Creation / loading methods ********************************************
98        void GLTexture::createInternalResourcesImpl(void)
99    {
100                // Convert to nearest power-of-two size if required
101        mWidth = GLPixelUtil::optionalPO2(mWidth);     
102        mHeight = GLPixelUtil::optionalPO2(mHeight);
103        mDepth = GLPixelUtil::optionalPO2(mDepth);
104               
105
106                // Adjust format if required
107                mFormat = TextureManager::getSingleton().getNativeFormat(mTextureType, mFormat, mUsage);
108               
109                // Check requested number of mipmaps
110                size_t maxMips = GLPixelUtil::getMaxMipmaps(mWidth, mHeight, mDepth, mFormat);
111                mNumMipmaps = mNumRequestedMipmaps;
112                if(mNumMipmaps>maxMips)
113                        mNumMipmaps = maxMips;
114               
115                // Generate texture name
116        glGenTextures( 1, &mTextureID );
117               
118                // Set texture type
119                glBindTexture( getGLTextureTarget(), mTextureID );
120       
121                // This needs to be set otherwise the texture doesn't get rendered
122        glTexParameteri( getGLTextureTarget(), GL_TEXTURE_MAX_LEVEL, mNumMipmaps );
123       
124        // Set some misc default parameters so NVidia won't complain, these can of course be changed later
125        glTexParameteri(getGLTextureTarget(), GL_TEXTURE_MIN_FILTER, GL_NEAREST);
126        glTexParameteri(getGLTextureTarget(), GL_TEXTURE_MAG_FILTER, GL_NEAREST);
127        glTexParameteri(getGLTextureTarget(), GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
128        glTexParameteri(getGLTextureTarget(), GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
129               
130                // If we can do automip generation and the user desires this, do so
131                mMipmapsHardwareGenerated = 
132                        Root::getSingleton().getRenderSystem()->getCapabilities()->hasCapability(RSC_AUTOMIPMAP);
133                if((mUsage & TU_AUTOMIPMAP) &&
134                    mNumRequestedMipmaps && mMipmapsHardwareGenerated)
135        {
136            glTexParameteri( getGLTextureTarget(), GL_GENERATE_MIPMAP, GL_TRUE );
137        }
138               
139                // Allocate internal buffer so that glTexSubImageXD can be used
140                // Internal format
141                GLenum format = GLPixelUtil::getClosestGLInternalFormat(mFormat);
142                size_t width = mWidth;
143                size_t height = mHeight;
144                size_t depth = mDepth;
145#if 0
146        /** Luckily, this hack seems not to be needed; empty compressed textures can very well be created the
147            conventional way with glTexImageXD.
148        */
149                if(PixelUtil::isCompressed(mFormat))
150                {
151                        // Compressed formats
152                        size_t size = PixelUtil::getMemorySize(mWidth, mHeight, mDepth, mFormat);
153                        // Provide temporary buffer filled with zeroes as glCompressedTexImageXD does not
154                        // accept a 0 pointer like normal glTexImageXD
155                        // Run through this process for every mipmap to pregenerate mipmap piramid
156                        uint8 *tmpdata = new uint8[size];
157                        memset(tmpdata, 0, size);
158                       
159                        for(size_t mip=0; mip<=mNumMipmaps; mip++)
160                        {
161                                size = PixelUtil::getMemorySize(width, height, depth, mFormat);
162                                switch(mTextureType)
163                                {
164                                        case TEX_TYPE_1D:
165                                                glCompressedTexImage1DARB(GL_TEXTURE_1D, mip, format,
166                                                        width, 0,
167                                                        size, tmpdata);
168                                                break;
169                                        case TEX_TYPE_2D:
170                                                glCompressedTexImage2DARB(GL_TEXTURE_2D, mip, format,
171                                                        width, height, 0,
172                                                        size, tmpdata);
173                                                break;
174                                        case TEX_TYPE_3D:
175                                                glCompressedTexImage3DARB(GL_TEXTURE_3D, mip, format,
176                                                        width, height, depth, 0,
177                                                        size, tmpdata);
178                                                break;
179                                        case TEX_TYPE_CUBE_MAP:
180                                                for(int face=0; face<6; face++) {
181                                                        glCompressedTexImage2DARB(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, mip, format,
182                                                                width, height, 0,
183                                                                size, tmpdata);
184                                                }
185                                                break;
186                                };
187                                if(width>1)             width = width/2;
188                                if(height>1)    height = height/2;
189                                if(depth>1)             depth = depth/2;
190                        }
191                        delete [] tmpdata;
192                }
193                else
194#endif
195                {
196                        // Run through this process to pregenerate mipmap piramid
197                        for(size_t mip=0; mip<=mNumMipmaps; mip++)
198                        {
199                                // Normal formats
200                                switch(mTextureType)
201                                {
202                                        case TEX_TYPE_1D:
203                                                glTexImage1D(GL_TEXTURE_1D, mip, format,
204                                                        width, 0, 
205                                                        GL_RGBA, GL_UNSIGNED_BYTE, 0);
206       
207                                                break;
208                                        case TEX_TYPE_2D:
209                                                glTexImage2D(GL_TEXTURE_2D, mip, format,
210                                                        width, height, 0, 
211                                                        GL_RGBA, GL_UNSIGNED_BYTE, 0);
212                                                break;
213                                        case TEX_TYPE_3D:
214                                                glTexImage3D(GL_TEXTURE_3D, mip, format,
215                                                        width, height, depth, 0, 
216                                                        GL_RGBA, GL_UNSIGNED_BYTE, 0);
217                                                break;
218                                        case TEX_TYPE_CUBE_MAP:
219                                                for(int face=0; face<6; face++) {
220                                                        glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, mip, format,
221                                                                width, height, 0, 
222                                                                GL_RGBA, GL_UNSIGNED_BYTE, 0);
223                                                }
224                                                break;
225                                };
226                                if(width>1)             width = width/2;
227                                if(height>1)    height = height/2;
228                                if(depth>1)             depth = depth/2;
229                        }
230                }
231                _createSurfaceList();
232                // Get final internal format
233                mFormat = getBuffer(0,0)->getFormat();
234        }
235       
236    void GLTexture::createRenderTexture(void)
237    {
238        // Create the GL texture
239                // This already does everything neccessary
240        createInternalResources();
241    }
242       
243    void GLTexture::loadImpl()
244    {
245        if( mUsage & TU_RENDERTARGET )
246        {
247            createRenderTexture();
248        }
249        else
250        {
251                        String baseName, ext;
252                        size_t pos = mName.find_last_of(".");
253                        if( pos == String::npos )
254                                OGRE_EXCEPT(
255                                        Exception::ERR_INVALIDPARAMS, 
256                                        "Unable to load image file '"+ mName + "' - invalid extension.",
257                                        "GLTexture::loadImpl" );
258
259                        baseName = mName.substr(0, pos);
260                        ext = mName.substr(pos+1);
261   
262                        if(mTextureType == TEX_TYPE_1D || mTextureType == TEX_TYPE_2D || 
263                mTextureType == TEX_TYPE_3D)
264            {
265                Image img;
266                    // find & load resource data intro stream to allow resource
267                                // group changes if required
268                                DataStreamPtr dstream = 
269                                        ResourceGroupManager::getSingleton().openResource(
270                                                mName, mGroup, true, this);
271
272                img.load(dstream, ext);
273
274                                // If this is a cube map, set the texture type flag accordingly.
275                if (img.hasFlag(IF_CUBEMAP))
276                                        mTextureType = TEX_TYPE_CUBE_MAP;
277                                // If this is a volumetric texture set the texture type flag accordingly.
278                                if(img.getDepth() > 1)
279                                        mTextureType = TEX_TYPE_3D;
280
281                                // Call internal _loadImages, not loadImage since that's external and
282                                // will determine load status etc again
283                                ConstImagePtrList imagePtrs;
284                                imagePtrs.push_back(&img);
285                                _loadImages( imagePtrs );
286            }
287            else if (mTextureType == TEX_TYPE_CUBE_MAP)
288            {
289                                if(StringUtil::endsWith(getName(), ".dds"))
290                                {
291                                        // XX HACK there should be a better way to specify whether
292                                        // all faces are in the same file or not
293                                        Image img;
294                        // find & load resource data intro stream to allow resource
295                                        // group changes if required
296                                        DataStreamPtr dstream = 
297                                                ResourceGroupManager::getSingleton().openResource(
298                                                        mName, mGroup, true, this);
299
300                        img.load(dstream, ext);
301                                        // Call internal _loadImages, not loadImage since that's external and
302                                        // will determine load status etc again
303                                        ConstImagePtrList imagePtrs;
304                                        imagePtrs.push_back(&img);
305                                        _loadImages( imagePtrs );
306                                }
307                                else
308                                {
309                                        std::vector<Image> images(6);
310                                        ConstImagePtrList imagePtrs;
311                                        static const String suffixes[6] = {"_rt", "_lf", "_up", "_dn", "_fr", "_bk"};
312       
313                                        for(size_t i = 0; i < 6; i++)
314                                        {
315                                                String fullName = baseName + suffixes[i] + "." + ext;
316                                // find & load resource data intro stream to allow resource
317                                                // group changes if required
318                                                DataStreamPtr dstream = 
319                                                        ResourceGroupManager::getSingleton().openResource(
320                                                                fullName, mGroup, true, this);
321       
322                                                images[i].load(dstream, ext);
323                                                imagePtrs.push_back(&images[i]);
324                                        }
325       
326                                        _loadImages( imagePtrs );
327                                }
328            }
329            else
330                OGRE_EXCEPT( Exception::ERR_NOT_IMPLEMENTED, "**** Unknown texture type ****", "GLTexture::load" );
331        }
332    }
333       
334        //*************************************************************************
335   
336    void GLTexture::freeInternalResourcesImpl()
337    {
338                mSurfaceList.clear();
339        glDeleteTextures( 1, &mTextureID );
340    }
341
342       
343        //---------------------------------------------------------------------------------------------
344        void GLTexture::_createSurfaceList()
345        {
346                mSurfaceList.clear();
347               
348                // For all faces and mipmaps, store surfaces as HardwarePixelBufferSharedPtr
349                bool wantGeneratedMips = (mUsage & TU_AUTOMIPMAP)!=0;
350               
351                // Do mipmapping in software? (uses GLU) For some cards, this is still needed. Of course,
352                // only when mipmap generation is desired.
353                bool doSoftware = wantGeneratedMips && !mMipmapsHardwareGenerated && getNumMipmaps(); 
354               
355                for(size_t face=0; face<getNumFaces(); face++)
356                {
357                        for(size_t mip=0; mip<=getNumMipmaps(); mip++)
358                        {
359                GLHardwarePixelBuffer *buf = new GLTextureBuffer(mName, getGLTextureTarget(), mTextureID, face, mip,
360                                                static_cast<HardwareBuffer::Usage>(mUsage), doSoftware && mip==0);
361                                mSurfaceList.push_back(HardwarePixelBufferSharedPtr(buf));
362               
363                /// Check for error
364                if(buf->getWidth()==0 || buf->getHeight()==0 || buf->getDepth()==0)
365                {
366                    OGRE_EXCEPT(
367                        Exception::ERR_RENDERINGAPI_ERROR, 
368                        "Zero sized texture surface on texture "+getName()+
369                            " face "+StringConverter::toString(face)+
370                            " mipmap "+StringConverter::toString(mip)+
371                            ". Probably, the GL driver refused to create the texture.", 
372                            "GLTexture::_createSurfaceList");
373                }
374                        }
375                }
376        }
377       
378        //---------------------------------------------------------------------------------------------
379        HardwarePixelBufferSharedPtr GLTexture::getBuffer(size_t face, size_t mipmap)
380        {
381                if(face >= getNumFaces())
382                        OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS, "Face index out of range",
383                                        "GLTexture::getBuffer");
384                if(mipmap > mNumMipmaps)
385                        OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS, "Mipmap index out of range",
386                                        "GLTexture::getBuffer");
387                unsigned int idx = face*(mNumMipmaps+1) + mipmap;
388                assert(idx < mSurfaceList.size());
389                return mSurfaceList[idx];
390        }
391       
392}
393
Note: See TracBrowser for help on using the repository browser.