source: OGRE/trunk/ogrenew/RenderSystems/GL/src/OgreGLTexture.cpp @ 692

Revision 692, 12.8 KB checked in by mattausch, 18 years ago (diff)

adding ogre 1.2 and dependencies

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