aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/libraries/irrlicht-1.8/source/Irrlicht/COpenGLTexture.cpp
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--libraries/irrlicht-1.8/source/Irrlicht/COpenGLTexture.cpp1926
1 files changed, 963 insertions, 963 deletions
diff --git a/libraries/irrlicht-1.8/source/Irrlicht/COpenGLTexture.cpp b/libraries/irrlicht-1.8/source/Irrlicht/COpenGLTexture.cpp
index 3cc41c0..b259071 100644
--- a/libraries/irrlicht-1.8/source/Irrlicht/COpenGLTexture.cpp
+++ b/libraries/irrlicht-1.8/source/Irrlicht/COpenGLTexture.cpp
@@ -1,963 +1,963 @@
1// Copyright (C) 2002-2012 Nikolaus Gebhardt 1// Copyright (C) 2002-2012 Nikolaus Gebhardt
2// This file is part of the "Irrlicht Engine". 2// This file is part of the "Irrlicht Engine".
3// For conditions of distribution and use, see copyright notice in irrlicht.h 3// For conditions of distribution and use, see copyright notice in irrlicht.h
4 4
5#include "IrrCompileConfig.h" 5#include "IrrCompileConfig.h"
6 6
7#ifdef _IRR_COMPILE_WITH_OPENGL_ 7#ifdef _IRR_COMPILE_WITH_OPENGL_
8 8
9#include "irrTypes.h" 9#include "irrTypes.h"
10#include "COpenGLTexture.h" 10#include "COpenGLTexture.h"
11#include "COpenGLDriver.h" 11#include "COpenGLDriver.h"
12#include "os.h" 12#include "os.h"
13#include "CColorConverter.h" 13#include "CColorConverter.h"
14 14
15#include "irrString.h" 15#include "irrString.h"
16 16
17namespace irr 17namespace irr
18{ 18{
19namespace video 19namespace video
20{ 20{
21 21
22//! constructor for usual textures 22//! constructor for usual textures
23COpenGLTexture::COpenGLTexture(IImage* origImage, const io::path& name, void* mipmapData, COpenGLDriver* driver) 23COpenGLTexture::COpenGLTexture(IImage* origImage, const io::path& name, void* mipmapData, COpenGLDriver* driver)
24 : ITexture(name), ColorFormat(ECF_A8R8G8B8), Driver(driver), Image(0), MipImage(0), 24 : ITexture(name), ColorFormat(ECF_A8R8G8B8), Driver(driver), Image(0), MipImage(0),
25 TextureName(0), InternalFormat(GL_RGBA), PixelFormat(GL_BGRA_EXT), 25 TextureName(0), InternalFormat(GL_RGBA), PixelFormat(GL_BGRA_EXT),
26 PixelType(GL_UNSIGNED_BYTE), MipLevelStored(0), MipmapLegacyMode(true), 26 PixelType(GL_UNSIGNED_BYTE), MipLevelStored(0), MipmapLegacyMode(true),
27 IsRenderTarget(false), AutomaticMipmapUpdate(false), 27 IsRenderTarget(false), AutomaticMipmapUpdate(false),
28 ReadOnlyLock(false), KeepImage(true) 28 ReadOnlyLock(false), KeepImage(true)
29{ 29{
30 #ifdef _DEBUG 30 #ifdef _DEBUG
31 setDebugName("COpenGLTexture"); 31 setDebugName("COpenGLTexture");
32 #endif 32 #endif
33 33
34 HasMipMaps = Driver->getTextureCreationFlag(ETCF_CREATE_MIP_MAPS); 34 HasMipMaps = Driver->getTextureCreationFlag(ETCF_CREATE_MIP_MAPS);
35 getImageValues(origImage); 35 getImageValues(origImage);
36 36
37 glGenTextures(1, &TextureName); 37 glGenTextures(1, &TextureName);
38 38
39 if (ImageSize==TextureSize) 39 if (ImageSize==TextureSize)
40 { 40 {
41 Image = Driver->createImage(ColorFormat, ImageSize); 41 Image = Driver->createImage(ColorFormat, ImageSize);
42 origImage->copyTo(Image); 42 origImage->copyTo(Image);
43 } 43 }
44 else 44 else
45 { 45 {
46 Image = Driver->createImage(ColorFormat, TextureSize); 46 Image = Driver->createImage(ColorFormat, TextureSize);
47 // scale texture 47 // scale texture
48 origImage->copyToScaling(Image); 48 origImage->copyToScaling(Image);
49 } 49 }
50 uploadTexture(true, mipmapData); 50 uploadTexture(true, mipmapData);
51 if (!KeepImage) 51 if (!KeepImage)
52 { 52 {
53 Image->drop(); 53 Image->drop();
54 Image=0; 54 Image=0;
55 } 55 }
56} 56}
57 57
58 58
59//! constructor for basic setup (only for derived classes) 59//! constructor for basic setup (only for derived classes)
60COpenGLTexture::COpenGLTexture(const io::path& name, COpenGLDriver* driver) 60COpenGLTexture::COpenGLTexture(const io::path& name, COpenGLDriver* driver)
61 : ITexture(name), ColorFormat(ECF_A8R8G8B8), Driver(driver), Image(0), MipImage(0), 61 : ITexture(name), ColorFormat(ECF_A8R8G8B8), Driver(driver), Image(0), MipImage(0),
62 TextureName(0), InternalFormat(GL_RGBA), PixelFormat(GL_BGRA_EXT), 62 TextureName(0), InternalFormat(GL_RGBA), PixelFormat(GL_BGRA_EXT),
63 PixelType(GL_UNSIGNED_BYTE), MipLevelStored(0), HasMipMaps(true), 63 PixelType(GL_UNSIGNED_BYTE), MipLevelStored(0), HasMipMaps(true),
64 MipmapLegacyMode(true), IsRenderTarget(false), AutomaticMipmapUpdate(false), 64 MipmapLegacyMode(true), IsRenderTarget(false), AutomaticMipmapUpdate(false),
65 ReadOnlyLock(false), KeepImage(true) 65 ReadOnlyLock(false), KeepImage(true)
66{ 66{
67 #ifdef _DEBUG 67 #ifdef _DEBUG
68 setDebugName("COpenGLTexture"); 68 setDebugName("COpenGLTexture");
69 #endif 69 #endif
70} 70}
71 71
72 72
73//! destructor 73//! destructor
74COpenGLTexture::~COpenGLTexture() 74COpenGLTexture::~COpenGLTexture()
75{ 75{
76 if (TextureName) 76 if (TextureName)
77 glDeleteTextures(1, &TextureName); 77 glDeleteTextures(1, &TextureName);
78 if (Image) 78 if (Image)
79 Image->drop(); 79 Image->drop();
80} 80}
81 81
82 82
83//! Choose best matching color format, based on texture creation flags 83//! Choose best matching color format, based on texture creation flags
84ECOLOR_FORMAT COpenGLTexture::getBestColorFormat(ECOLOR_FORMAT format) 84ECOLOR_FORMAT COpenGLTexture::getBestColorFormat(ECOLOR_FORMAT format)
85{ 85{
86 ECOLOR_FORMAT destFormat = ECF_A8R8G8B8; 86 ECOLOR_FORMAT destFormat = ECF_A8R8G8B8;
87 switch (format) 87 switch (format)
88 { 88 {
89 case ECF_A1R5G5B5: 89 case ECF_A1R5G5B5:
90 if (!Driver->getTextureCreationFlag(ETCF_ALWAYS_32_BIT)) 90 if (!Driver->getTextureCreationFlag(ETCF_ALWAYS_32_BIT))
91 destFormat = ECF_A1R5G5B5; 91 destFormat = ECF_A1R5G5B5;
92 break; 92 break;
93 case ECF_R5G6B5: 93 case ECF_R5G6B5:
94 if (!Driver->getTextureCreationFlag(ETCF_ALWAYS_32_BIT)) 94 if (!Driver->getTextureCreationFlag(ETCF_ALWAYS_32_BIT))
95 destFormat = ECF_A1R5G5B5; 95 destFormat = ECF_A1R5G5B5;
96 break; 96 break;
97 case ECF_A8R8G8B8: 97 case ECF_A8R8G8B8:
98 if (Driver->getTextureCreationFlag(ETCF_ALWAYS_16_BIT) || 98 if (Driver->getTextureCreationFlag(ETCF_ALWAYS_16_BIT) ||
99 Driver->getTextureCreationFlag(ETCF_OPTIMIZED_FOR_SPEED)) 99 Driver->getTextureCreationFlag(ETCF_OPTIMIZED_FOR_SPEED))
100 destFormat = ECF_A1R5G5B5; 100 destFormat = ECF_A1R5G5B5;
101 break; 101 break;
102 case ECF_R8G8B8: 102 case ECF_R8G8B8:
103 if (Driver->getTextureCreationFlag(ETCF_ALWAYS_16_BIT) || 103 if (Driver->getTextureCreationFlag(ETCF_ALWAYS_16_BIT) ||
104 Driver->getTextureCreationFlag(ETCF_OPTIMIZED_FOR_SPEED)) 104 Driver->getTextureCreationFlag(ETCF_OPTIMIZED_FOR_SPEED))
105 destFormat = ECF_A1R5G5B5; 105 destFormat = ECF_A1R5G5B5;
106 default: 106 default:
107 break; 107 break;
108 } 108 }
109 if (Driver->getTextureCreationFlag(ETCF_NO_ALPHA_CHANNEL)) 109 if (Driver->getTextureCreationFlag(ETCF_NO_ALPHA_CHANNEL))
110 { 110 {
111 switch (destFormat) 111 switch (destFormat)
112 { 112 {
113 case ECF_A1R5G5B5: 113 case ECF_A1R5G5B5:
114 destFormat = ECF_R5G6B5; 114 destFormat = ECF_R5G6B5;
115 break; 115 break;
116 case ECF_A8R8G8B8: 116 case ECF_A8R8G8B8:
117 destFormat = ECF_R8G8B8; 117 destFormat = ECF_R8G8B8;
118 break; 118 break;
119 default: 119 default:
120 break; 120 break;
121 } 121 }
122 } 122 }
123 return destFormat; 123 return destFormat;
124} 124}
125 125
126 126
127//! Get opengl values for the GPU texture storage 127//! Get opengl values for the GPU texture storage
128GLint COpenGLTexture::getOpenGLFormatAndParametersFromColorFormat(ECOLOR_FORMAT format, 128GLint COpenGLTexture::getOpenGLFormatAndParametersFromColorFormat(ECOLOR_FORMAT format,
129 GLint& filtering, 129 GLint& filtering,
130 GLenum& colorformat, 130 GLenum& colorformat,
131 GLenum& type) 131 GLenum& type)
132{ 132{
133 // default 133 // default
134 filtering = GL_LINEAR; 134 filtering = GL_LINEAR;
135 colorformat = GL_RGBA; 135 colorformat = GL_RGBA;
136 type = GL_UNSIGNED_BYTE; 136 type = GL_UNSIGNED_BYTE;
137 GLenum internalformat = GL_RGBA; 137 GLenum internalformat = GL_RGBA;
138 138
139 switch(format) 139 switch(format)
140 { 140 {
141 case ECF_A1R5G5B5: 141 case ECF_A1R5G5B5:
142 colorformat=GL_BGRA_EXT; 142 colorformat=GL_BGRA_EXT;
143 type=GL_UNSIGNED_SHORT_1_5_5_5_REV; 143 type=GL_UNSIGNED_SHORT_1_5_5_5_REV;
144 internalformat = GL_RGBA; 144 internalformat = GL_RGBA;
145 break; 145 break;
146 case ECF_R5G6B5: 146 case ECF_R5G6B5:
147 colorformat=GL_RGB; 147 colorformat=GL_RGB;
148 type=GL_UNSIGNED_SHORT_5_6_5; 148 type=GL_UNSIGNED_SHORT_5_6_5;
149 internalformat = GL_RGB; 149 internalformat = GL_RGB;
150 break; 150 break;
151 case ECF_R8G8B8: 151 case ECF_R8G8B8:
152 colorformat=GL_BGR; 152 colorformat=GL_BGR;
153 type=GL_UNSIGNED_BYTE; 153 type=GL_UNSIGNED_BYTE;
154 internalformat = GL_RGB; 154 internalformat = GL_RGB;
155 break; 155 break;
156 case ECF_A8R8G8B8: 156 case ECF_A8R8G8B8:
157 colorformat=GL_BGRA_EXT; 157 colorformat=GL_BGRA_EXT;
158 if (Driver->Version > 101) 158 if (Driver->Version > 101)
159 type=GL_UNSIGNED_INT_8_8_8_8_REV; 159 type=GL_UNSIGNED_INT_8_8_8_8_REV;
160 internalformat = GL_RGBA; 160 internalformat = GL_RGBA;
161 break; 161 break;
162 // Floating Point texture formats. Thanks to Patryk "Nadro" Nadrowski. 162 // Floating Point texture formats. Thanks to Patryk "Nadro" Nadrowski.
163 case ECF_R16F: 163 case ECF_R16F:
164 { 164 {
165#ifdef GL_ARB_texture_rg 165#ifdef GL_ARB_texture_rg
166 filtering = GL_NEAREST; 166 filtering = GL_NEAREST;
167 colorformat = GL_RED; 167 colorformat = GL_RED;
168 type = GL_FLOAT; 168 type = GL_FLOAT;
169 169
170 internalformat = GL_R16F; 170 internalformat = GL_R16F;
171#else 171#else
172 ColorFormat = ECF_A8R8G8B8; 172 ColorFormat = ECF_A8R8G8B8;
173 internalformat = GL_RGB8; 173 internalformat = GL_RGB8;
174#endif 174#endif
175 } 175 }
176 break; 176 break;
177 case ECF_G16R16F: 177 case ECF_G16R16F:
178 { 178 {
179#ifdef GL_ARB_texture_rg 179#ifdef GL_ARB_texture_rg
180 filtering = GL_NEAREST; 180 filtering = GL_NEAREST;
181 colorformat = GL_RG; 181 colorformat = GL_RG;
182 type = GL_FLOAT; 182 type = GL_FLOAT;
183 183
184 internalformat = GL_RG16F; 184 internalformat = GL_RG16F;
185#else 185#else
186 ColorFormat = ECF_A8R8G8B8; 186 ColorFormat = ECF_A8R8G8B8;
187 internalformat = GL_RGB8; 187 internalformat = GL_RGB8;
188#endif 188#endif
189 } 189 }
190 break; 190 break;
191 case ECF_A16B16G16R16F: 191 case ECF_A16B16G16R16F:
192 { 192 {
193#ifdef GL_ARB_texture_rg 193#ifdef GL_ARB_texture_rg
194 filtering = GL_NEAREST; 194 filtering = GL_NEAREST;
195 colorformat = GL_RGBA; 195 colorformat = GL_RGBA;
196 type = GL_FLOAT; 196 type = GL_FLOAT;
197 197
198 internalformat = GL_RGBA16F_ARB; 198 internalformat = GL_RGBA16F_ARB;
199#else 199#else
200 ColorFormat = ECF_A8R8G8B8; 200 ColorFormat = ECF_A8R8G8B8;
201 internalformat = GL_RGBA8; 201 internalformat = GL_RGBA8;
202#endif 202#endif
203 } 203 }
204 break; 204 break;
205 case ECF_R32F: 205 case ECF_R32F:
206 { 206 {
207#ifdef GL_ARB_texture_rg 207#ifdef GL_ARB_texture_rg
208 filtering = GL_NEAREST; 208 filtering = GL_NEAREST;
209 colorformat = GL_RED; 209 colorformat = GL_RED;
210 type = GL_FLOAT; 210 type = GL_FLOAT;
211 211
212 internalformat = GL_R32F; 212 internalformat = GL_R32F;
213#else 213#else
214 ColorFormat = ECF_A8R8G8B8; 214 ColorFormat = ECF_A8R8G8B8;
215 internalformat = GL_RGB8; 215 internalformat = GL_RGB8;
216#endif 216#endif
217 } 217 }
218 break; 218 break;
219 case ECF_G32R32F: 219 case ECF_G32R32F:
220 { 220 {
221#ifdef GL_ARB_texture_rg 221#ifdef GL_ARB_texture_rg
222 filtering = GL_NEAREST; 222 filtering = GL_NEAREST;
223 colorformat = GL_RG; 223 colorformat = GL_RG;
224 type = GL_FLOAT; 224 type = GL_FLOAT;
225 225
226 internalformat = GL_RG32F; 226 internalformat = GL_RG32F;
227#else 227#else
228 ColorFormat = ECF_A8R8G8B8; 228 ColorFormat = ECF_A8R8G8B8;
229 internalformat = GL_RGB8; 229 internalformat = GL_RGB8;
230#endif 230#endif
231 } 231 }
232 break; 232 break;
233 case ECF_A32B32G32R32F: 233 case ECF_A32B32G32R32F:
234 { 234 {
235#ifdef GL_ARB_texture_float 235#ifdef GL_ARB_texture_float
236 filtering = GL_NEAREST; 236 filtering = GL_NEAREST;
237 colorformat = GL_RGBA; 237 colorformat = GL_RGBA;
238 type = GL_FLOAT; 238 type = GL_FLOAT;
239 239
240 internalformat = GL_RGBA32F_ARB; 240 internalformat = GL_RGBA32F_ARB;
241#else 241#else
242 ColorFormat = ECF_A8R8G8B8; 242 ColorFormat = ECF_A8R8G8B8;
243 internalformat = GL_RGBA8; 243 internalformat = GL_RGBA8;
244#endif 244#endif
245 } 245 }
246 break; 246 break;
247 default: 247 default:
248 { 248 {
249 os::Printer::log("Unsupported texture format", ELL_ERROR); 249 os::Printer::log("Unsupported texture format", ELL_ERROR);
250 internalformat = GL_RGBA8; 250 internalformat = GL_RGBA8;
251 } 251 }
252 } 252 }
253#if defined(GL_ARB_framebuffer_sRGB) || defined(GL_EXT_framebuffer_sRGB) 253#if defined(GL_ARB_framebuffer_sRGB) || defined(GL_EXT_framebuffer_sRGB)
254 if (Driver->Params.HandleSRGB) 254 if (Driver->Params.HandleSRGB)
255 { 255 {
256 if (internalformat==GL_RGBA) 256 if (internalformat==GL_RGBA)
257 internalformat=GL_SRGB_ALPHA_EXT; 257 internalformat=GL_SRGB_ALPHA_EXT;
258 else if (internalformat==GL_RGB) 258 else if (internalformat==GL_RGB)
259 internalformat=GL_SRGB_EXT; 259 internalformat=GL_SRGB_EXT;
260 } 260 }
261#endif 261#endif
262 return internalformat; 262 return internalformat;
263} 263}
264 264
265 265
266// prepare values ImageSize, TextureSize, and ColorFormat based on image 266// prepare values ImageSize, TextureSize, and ColorFormat based on image
267void COpenGLTexture::getImageValues(IImage* image) 267void COpenGLTexture::getImageValues(IImage* image)
268{ 268{
269 if (!image) 269 if (!image)
270 { 270 {
271 os::Printer::log("No image for OpenGL texture.", ELL_ERROR); 271 os::Printer::log("No image for OpenGL texture.", ELL_ERROR);
272 return; 272 return;
273 } 273 }
274 274
275 ImageSize = image->getDimension(); 275 ImageSize = image->getDimension();
276 276
277 if ( !ImageSize.Width || !ImageSize.Height) 277 if ( !ImageSize.Width || !ImageSize.Height)
278 { 278 {
279 os::Printer::log("Invalid size of image for OpenGL Texture.", ELL_ERROR); 279 os::Printer::log("Invalid size of image for OpenGL Texture.", ELL_ERROR);
280 return; 280 return;
281 } 281 }
282 282
283 const f32 ratio = (f32)ImageSize.Width/(f32)ImageSize.Height; 283 const f32 ratio = (f32)ImageSize.Width/(f32)ImageSize.Height;
284 if ((ImageSize.Width>Driver->MaxTextureSize) && (ratio >= 1.0f)) 284 if ((ImageSize.Width>Driver->MaxTextureSize) && (ratio >= 1.0f))
285 { 285 {
286 ImageSize.Width = Driver->MaxTextureSize; 286 ImageSize.Width = Driver->MaxTextureSize;
287 ImageSize.Height = (u32)(Driver->MaxTextureSize/ratio); 287 ImageSize.Height = (u32)(Driver->MaxTextureSize/ratio);
288 } 288 }
289 else if (ImageSize.Height>Driver->MaxTextureSize) 289 else if (ImageSize.Height>Driver->MaxTextureSize)
290 { 290 {
291 ImageSize.Height = Driver->MaxTextureSize; 291 ImageSize.Height = Driver->MaxTextureSize;
292 ImageSize.Width = (u32)(Driver->MaxTextureSize*ratio); 292 ImageSize.Width = (u32)(Driver->MaxTextureSize*ratio);
293 } 293 }
294 TextureSize=ImageSize.getOptimalSize(!Driver->queryFeature(EVDF_TEXTURE_NPOT)); 294 TextureSize=ImageSize.getOptimalSize(!Driver->queryFeature(EVDF_TEXTURE_NPOT));
295 295
296 ColorFormat = getBestColorFormat(image->getColorFormat()); 296 ColorFormat = getBestColorFormat(image->getColorFormat());
297} 297}
298 298
299 299
300//! copies the the texture into an open gl texture. 300//! copies the the texture into an open gl texture.
301void COpenGLTexture::uploadTexture(bool newTexture, void* mipmapData, u32 level) 301void COpenGLTexture::uploadTexture(bool newTexture, void* mipmapData, u32 level)
302{ 302{
303 // check which image needs to be uploaded 303 // check which image needs to be uploaded
304 IImage* image = level?MipImage:Image; 304 IImage* image = level?MipImage:Image;
305 if (!image) 305 if (!image)
306 { 306 {
307 os::Printer::log("No image for OpenGL texture to upload", ELL_ERROR); 307 os::Printer::log("No image for OpenGL texture to upload", ELL_ERROR);
308 return; 308 return;
309 } 309 }
310 310
311 // get correct opengl color data values 311 // get correct opengl color data values
312 GLenum oldInternalFormat = InternalFormat; 312 GLenum oldInternalFormat = InternalFormat;
313 GLint filtering; 313 GLint filtering;
314 InternalFormat = getOpenGLFormatAndParametersFromColorFormat(ColorFormat, filtering, PixelFormat, PixelType); 314 InternalFormat = getOpenGLFormatAndParametersFromColorFormat(ColorFormat, filtering, PixelFormat, PixelType);
315 // make sure we don't change the internal format of existing images 315 // make sure we don't change the internal format of existing images
316 if (!newTexture) 316 if (!newTexture)
317 InternalFormat=oldInternalFormat; 317 InternalFormat=oldInternalFormat;
318 318
319 Driver->setActiveTexture(0, this); 319 Driver->setActiveTexture(0, this);
320 if (Driver->testGLError()) 320 if (Driver->testGLError())
321 os::Printer::log("Could not bind Texture", ELL_ERROR); 321 os::Printer::log("Could not bind Texture", ELL_ERROR);
322 322
323 // mipmap handling for main texture 323 // mipmap handling for main texture
324 if (!level && newTexture) 324 if (!level && newTexture)
325 { 325 {
326#ifndef DISABLE_MIPMAPPING 326#ifndef DISABLE_MIPMAPPING
327#ifdef GL_SGIS_generate_mipmap 327#ifdef GL_SGIS_generate_mipmap
328 // auto generate if possible and no mipmap data is given 328 // auto generate if possible and no mipmap data is given
329 if (HasMipMaps && !mipmapData && Driver->queryFeature(EVDF_MIP_MAP_AUTO_UPDATE)) 329 if (HasMipMaps && !mipmapData && Driver->queryFeature(EVDF_MIP_MAP_AUTO_UPDATE))
330 { 330 {
331 if (Driver->getTextureCreationFlag(ETCF_OPTIMIZED_FOR_SPEED)) 331 if (Driver->getTextureCreationFlag(ETCF_OPTIMIZED_FOR_SPEED))
332 glHint(GL_GENERATE_MIPMAP_HINT_SGIS, GL_FASTEST); 332 glHint(GL_GENERATE_MIPMAP_HINT_SGIS, GL_FASTEST);
333 else if (Driver->getTextureCreationFlag(ETCF_OPTIMIZED_FOR_QUALITY)) 333 else if (Driver->getTextureCreationFlag(ETCF_OPTIMIZED_FOR_QUALITY))
334 glHint(GL_GENERATE_MIPMAP_HINT_SGIS, GL_NICEST); 334 glHint(GL_GENERATE_MIPMAP_HINT_SGIS, GL_NICEST);
335 else 335 else
336 glHint(GL_GENERATE_MIPMAP_HINT_SGIS, GL_DONT_CARE); 336 glHint(GL_GENERATE_MIPMAP_HINT_SGIS, GL_DONT_CARE);
337 337
338 AutomaticMipmapUpdate=true; 338 AutomaticMipmapUpdate=true;
339 339
340 if (!Driver->queryFeature(EVDF_FRAMEBUFFER_OBJECT)) 340 if (!Driver->queryFeature(EVDF_FRAMEBUFFER_OBJECT))
341 { 341 {
342 glTexParameteri( GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_TRUE ); 342 glTexParameteri( GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_TRUE );
343 MipmapLegacyMode=true; 343 MipmapLegacyMode=true;
344 } 344 }
345 else 345 else
346 MipmapLegacyMode=false; 346 MipmapLegacyMode=false;
347 } 347 }
348 else 348 else
349#endif 349#endif
350 { 350 {
351 // Either generate manually due to missing capability 351 // Either generate manually due to missing capability
352 // or use predefined mipmap data 352 // or use predefined mipmap data
353 AutomaticMipmapUpdate=false; 353 AutomaticMipmapUpdate=false;
354 regenerateMipMapLevels(mipmapData); 354 regenerateMipMapLevels(mipmapData);
355 } 355 }
356 if (HasMipMaps) // might have changed in regenerateMipMapLevels 356 if (HasMipMaps) // might have changed in regenerateMipMapLevels
357 { 357 {
358 // enable bilinear mipmap filter 358 // enable bilinear mipmap filter
359 glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST ); 359 glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST );
360 glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 360 glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
361 } 361 }
362 else 362 else
363#else 363#else
364 HasMipMaps=false; 364 HasMipMaps=false;
365 os::Printer::log("Did not create OpenGL texture mip maps.", ELL_INFORMATION); 365 os::Printer::log("Did not create OpenGL texture mip maps.", ELL_INFORMATION);
366#endif 366#endif
367 { 367 {
368 // enable bilinear filter without mipmaps 368 // enable bilinear filter without mipmaps
369 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 369 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
370 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 370 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
371 } 371 }
372 } 372 }
373 373
374 // now get image data and upload to GPU 374 // now get image data and upload to GPU
375 void* source = image->lock(); 375 void* source = image->lock();
376 if (newTexture) 376 if (newTexture)
377 glTexImage2D(GL_TEXTURE_2D, level, InternalFormat, image->getDimension().Width, 377 glTexImage2D(GL_TEXTURE_2D, level, InternalFormat, image->getDimension().Width,
378 image->getDimension().Height, 0, PixelFormat, PixelType, source); 378 image->getDimension().Height, 0, PixelFormat, PixelType, source);
379 else 379 else
380 glTexSubImage2D(GL_TEXTURE_2D, level, 0, 0, image->getDimension().Width, 380 glTexSubImage2D(GL_TEXTURE_2D, level, 0, 0, image->getDimension().Width,
381 image->getDimension().Height, PixelFormat, PixelType, source); 381 image->getDimension().Height, PixelFormat, PixelType, source);
382 image->unlock(); 382 image->unlock();
383 383
384 if (!MipmapLegacyMode && AutomaticMipmapUpdate) 384 if (!MipmapLegacyMode && AutomaticMipmapUpdate)
385 { 385 {
386 glEnable(GL_TEXTURE_2D); 386 glEnable(GL_TEXTURE_2D);
387 Driver->extGlGenerateMipmap(GL_TEXTURE_2D); 387 Driver->extGlGenerateMipmap(GL_TEXTURE_2D);
388 } 388 }
389 389
390 if (Driver->testGLError()) 390 if (Driver->testGLError())
391 os::Printer::log("Could not glTexImage2D", ELL_ERROR); 391 os::Printer::log("Could not glTexImage2D", ELL_ERROR);
392} 392}
393 393
394 394
395//! lock function 395//! lock function
396void* COpenGLTexture::lock(E_TEXTURE_LOCK_MODE mode, u32 mipmapLevel) 396void* COpenGLTexture::lock(E_TEXTURE_LOCK_MODE mode, u32 mipmapLevel)
397{ 397{
398 // store info about which image is locked 398 // store info about which image is locked
399 IImage* image = (mipmapLevel==0)?Image:MipImage; 399 IImage* image = (mipmapLevel==0)?Image:MipImage;
400 ReadOnlyLock |= (mode==ETLM_READ_ONLY); 400 ReadOnlyLock |= (mode==ETLM_READ_ONLY);
401 MipLevelStored = mipmapLevel; 401 MipLevelStored = mipmapLevel;
402 if (!ReadOnlyLock && mipmapLevel) 402 if (!ReadOnlyLock && mipmapLevel)
403 { 403 {
404#ifdef GL_SGIS_generate_mipmap 404#ifdef GL_SGIS_generate_mipmap
405 if (Driver->queryFeature(EVDF_MIP_MAP_AUTO_UPDATE)) 405 if (Driver->queryFeature(EVDF_MIP_MAP_AUTO_UPDATE))
406 { 406 {
407 // do not automatically generate and update mipmaps 407 // do not automatically generate and update mipmaps
408 glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_FALSE); 408 glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_FALSE);
409 } 409 }
410#endif 410#endif
411 AutomaticMipmapUpdate=false; 411 AutomaticMipmapUpdate=false;
412 } 412 }
413 413
414 // if data not available or might have changed on GPU download it 414 // if data not available or might have changed on GPU download it
415 if (!image || IsRenderTarget) 415 if (!image || IsRenderTarget)
416 { 416 {
417 // prepare the data storage if necessary 417 // prepare the data storage if necessary
418 if (!image) 418 if (!image)
419 { 419 {
420 if (mipmapLevel) 420 if (mipmapLevel)
421 { 421 {
422 u32 i=0; 422 u32 i=0;
423 u32 width = TextureSize.Width; 423 u32 width = TextureSize.Width;
424 u32 height = TextureSize.Height; 424 u32 height = TextureSize.Height;
425 do 425 do
426 { 426 {
427 if (width>1) 427 if (width>1)
428 width>>=1; 428 width>>=1;
429 if (height>1) 429 if (height>1)
430 height>>=1; 430 height>>=1;
431 ++i; 431 ++i;
432 } 432 }
433 while (i != mipmapLevel); 433 while (i != mipmapLevel);
434 MipImage = image = Driver->createImage(ECF_A8R8G8B8, core::dimension2du(width,height)); 434 MipImage = image = Driver->createImage(ECF_A8R8G8B8, core::dimension2du(width,height));
435 } 435 }
436 else 436 else
437 Image = image = Driver->createImage(ECF_A8R8G8B8, ImageSize); 437 Image = image = Driver->createImage(ECF_A8R8G8B8, ImageSize);
438 ColorFormat = ECF_A8R8G8B8; 438 ColorFormat = ECF_A8R8G8B8;
439 } 439 }
440 if (!image) 440 if (!image)
441 return 0; 441 return 0;
442 442
443 if (mode != ETLM_WRITE_ONLY) 443 if (mode != ETLM_WRITE_ONLY)
444 { 444 {
445 u8* pixels = static_cast<u8*>(image->lock()); 445 u8* pixels = static_cast<u8*>(image->lock());
446 if (!pixels) 446 if (!pixels)
447 return 0; 447 return 0;
448 448
449 // we need to keep the correct texture bound later on 449 // we need to keep the correct texture bound later on
450 GLint tmpTexture; 450 GLint tmpTexture;
451 glGetIntegerv(GL_TEXTURE_BINDING_2D, &tmpTexture); 451 glGetIntegerv(GL_TEXTURE_BINDING_2D, &tmpTexture);
452 glBindTexture(GL_TEXTURE_2D, TextureName); 452 glBindTexture(GL_TEXTURE_2D, TextureName);
453 453
454 // we need to flip textures vertical 454 // we need to flip textures vertical
455 // however, it seems that this does not hold for mipmap 455 // however, it seems that this does not hold for mipmap
456 // textures, for unknown reasons. 456 // textures, for unknown reasons.
457 457
458 // allows to read pixels in top-to-bottom order 458 // allows to read pixels in top-to-bottom order
459#ifdef GL_MESA_pack_invert 459#ifdef GL_MESA_pack_invert
460 if (!mipmapLevel && Driver->queryOpenGLFeature(COpenGLExtensionHandler::IRR_MESA_pack_invert)) 460 if (!mipmapLevel && Driver->queryOpenGLFeature(COpenGLExtensionHandler::IRR_MESA_pack_invert))
461 glPixelStorei(GL_PACK_INVERT_MESA, GL_TRUE); 461 glPixelStorei(GL_PACK_INVERT_MESA, GL_TRUE);
462#endif 462#endif
463 463
464 // download GPU data as ARGB8 to pixels; 464 // download GPU data as ARGB8 to pixels;
465 glGetTexImage(GL_TEXTURE_2D, mipmapLevel, GL_BGRA_EXT, GL_UNSIGNED_BYTE, pixels); 465 glGetTexImage(GL_TEXTURE_2D, mipmapLevel, GL_BGRA_EXT, GL_UNSIGNED_BYTE, pixels);
466 466
467 if (!mipmapLevel) 467 if (!mipmapLevel)
468 { 468 {
469#ifdef GL_MESA_pack_invert 469#ifdef GL_MESA_pack_invert
470 if (Driver->queryOpenGLFeature(COpenGLExtensionHandler::IRR_MESA_pack_invert)) 470 if (Driver->queryOpenGLFeature(COpenGLExtensionHandler::IRR_MESA_pack_invert))
471 glPixelStorei(GL_PACK_INVERT_MESA, GL_FALSE); 471 glPixelStorei(GL_PACK_INVERT_MESA, GL_FALSE);
472 else 472 else
473#endif 473#endif
474 { 474 {
475 // opengl images are horizontally flipped, so we have to fix that here. 475 // opengl images are horizontally flipped, so we have to fix that here.
476 const s32 pitch=image->getPitch(); 476 const s32 pitch=image->getPitch();
477 u8* p2 = pixels + (image->getDimension().Height - 1) * pitch; 477 u8* p2 = pixels + (image->getDimension().Height - 1) * pitch;
478 u8* tmpBuffer = new u8[pitch]; 478 u8* tmpBuffer = new u8[pitch];
479 for (u32 i=0; i < image->getDimension().Height; i += 2) 479 for (u32 i=0; i < image->getDimension().Height; i += 2)
480 { 480 {
481 memcpy(tmpBuffer, pixels, pitch); 481 memcpy(tmpBuffer, pixels, pitch);
482 memcpy(pixels, p2, pitch); 482 memcpy(pixels, p2, pitch);
483 memcpy(p2, tmpBuffer, pitch); 483 memcpy(p2, tmpBuffer, pitch);
484 pixels += pitch; 484 pixels += pitch;
485 p2 -= pitch; 485 p2 -= pitch;
486 } 486 }
487 delete [] tmpBuffer; 487 delete [] tmpBuffer;
488 } 488 }
489 } 489 }
490 image->unlock(); 490 image->unlock();
491 491
492 //reset old bound texture 492 //reset old bound texture
493 glBindTexture(GL_TEXTURE_2D, tmpTexture); 493 glBindTexture(GL_TEXTURE_2D, tmpTexture);
494 } 494 }
495 } 495 }
496 return image->lock(); 496 return image->lock();
497} 497}
498 498
499 499
500//! unlock function 500//! unlock function
501void COpenGLTexture::unlock() 501void COpenGLTexture::unlock()
502{ 502{
503 // test if miplevel or main texture was locked 503 // test if miplevel or main texture was locked
504 IImage* image = MipImage?MipImage:Image; 504 IImage* image = MipImage?MipImage:Image;
505 if (!image) 505 if (!image)
506 return; 506 return;
507 // unlock image to see changes 507 // unlock image to see changes
508 image->unlock(); 508 image->unlock();
509 // copy texture data to GPU 509 // copy texture data to GPU
510 if (!ReadOnlyLock) 510 if (!ReadOnlyLock)
511 uploadTexture(false, 0, MipLevelStored); 511 uploadTexture(false, 0, MipLevelStored);
512 ReadOnlyLock = false; 512 ReadOnlyLock = false;
513 // cleanup local image 513 // cleanup local image
514 if (MipImage) 514 if (MipImage)
515 { 515 {
516 MipImage->drop(); 516 MipImage->drop();
517 MipImage=0; 517 MipImage=0;
518 } 518 }
519 else if (!KeepImage) 519 else if (!KeepImage)
520 { 520 {
521 Image->drop(); 521 Image->drop();
522 Image=0; 522 Image=0;
523 } 523 }
524 // update information 524 // update information
525 if (Image) 525 if (Image)
526 ColorFormat=Image->getColorFormat(); 526 ColorFormat=Image->getColorFormat();
527 else 527 else
528 ColorFormat=ECF_A8R8G8B8; 528 ColorFormat=ECF_A8R8G8B8;
529} 529}
530 530
531 531
532//! Returns size of the original image. 532//! Returns size of the original image.
533const core::dimension2d<u32>& COpenGLTexture::getOriginalSize() const 533const core::dimension2d<u32>& COpenGLTexture::getOriginalSize() const
534{ 534{
535 return ImageSize; 535 return ImageSize;
536} 536}
537 537
538 538
539//! Returns size of the texture. 539//! Returns size of the texture.
540const core::dimension2d<u32>& COpenGLTexture::getSize() const 540const core::dimension2d<u32>& COpenGLTexture::getSize() const
541{ 541{
542 return TextureSize; 542 return TextureSize;
543} 543}
544 544
545 545
546//! returns driver type of texture, i.e. the driver, which created the texture 546//! returns driver type of texture, i.e. the driver, which created the texture
547E_DRIVER_TYPE COpenGLTexture::getDriverType() const 547E_DRIVER_TYPE COpenGLTexture::getDriverType() const
548{ 548{
549 return EDT_OPENGL; 549 return EDT_OPENGL;
550} 550}
551 551
552 552
553//! returns color format of texture 553//! returns color format of texture
554ECOLOR_FORMAT COpenGLTexture::getColorFormat() const 554ECOLOR_FORMAT COpenGLTexture::getColorFormat() const
555{ 555{
556 return ColorFormat; 556 return ColorFormat;
557} 557}
558 558
559 559
560//! returns pitch of texture (in bytes) 560//! returns pitch of texture (in bytes)
561u32 COpenGLTexture::getPitch() const 561u32 COpenGLTexture::getPitch() const
562{ 562{
563 if (Image) 563 if (Image)
564 return Image->getPitch(); 564 return Image->getPitch();
565 else 565 else
566 return 0; 566 return 0;
567} 567}
568 568
569 569
570//! return open gl texture name 570//! return open gl texture name
571GLuint COpenGLTexture::getOpenGLTextureName() const 571GLuint COpenGLTexture::getOpenGLTextureName() const
572{ 572{
573 return TextureName; 573 return TextureName;
574} 574}
575 575
576 576
577//! Returns whether this texture has mipmaps 577//! Returns whether this texture has mipmaps
578bool COpenGLTexture::hasMipMaps() const 578bool COpenGLTexture::hasMipMaps() const
579{ 579{
580 return HasMipMaps; 580 return HasMipMaps;
581} 581}
582 582
583 583
584//! Regenerates the mip map levels of the texture. Useful after locking and 584//! Regenerates the mip map levels of the texture. Useful after locking and
585//! modifying the texture 585//! modifying the texture
586void COpenGLTexture::regenerateMipMapLevels(void* mipmapData) 586void COpenGLTexture::regenerateMipMapLevels(void* mipmapData)
587{ 587{
588 if (AutomaticMipmapUpdate || !HasMipMaps || !Image) 588 if (AutomaticMipmapUpdate || !HasMipMaps || !Image)
589 return; 589 return;
590 if ((Image->getDimension().Width==1) && (Image->getDimension().Height==1)) 590 if ((Image->getDimension().Width==1) && (Image->getDimension().Height==1))
591 return; 591 return;
592 592
593 // Manually create mipmaps or use prepared version 593 // Manually create mipmaps or use prepared version
594 u32 width=Image->getDimension().Width; 594 u32 width=Image->getDimension().Width;
595 u32 height=Image->getDimension().Height; 595 u32 height=Image->getDimension().Height;
596 u32 i=0; 596 u32 i=0;
597 u8* target = static_cast<u8*>(mipmapData); 597 u8* target = static_cast<u8*>(mipmapData);
598 do 598 do
599 { 599 {
600 if (width>1) 600 if (width>1)
601 width>>=1; 601 width>>=1;
602 if (height>1) 602 if (height>1)
603 height>>=1; 603 height>>=1;
604 ++i; 604 ++i;
605 if (!target) 605 if (!target)
606 target = new u8[width*height*Image->getBytesPerPixel()]; 606 target = new u8[width*height*Image->getBytesPerPixel()];
607 // create scaled version if no mipdata available 607 // create scaled version if no mipdata available
608 if (!mipmapData) 608 if (!mipmapData)
609 Image->copyToScaling(target, width, height, Image->getColorFormat()); 609 Image->copyToScaling(target, width, height, Image->getColorFormat());
610 glTexImage2D(GL_TEXTURE_2D, i, InternalFormat, width, height, 610 glTexImage2D(GL_TEXTURE_2D, i, InternalFormat, width, height,
611 0, PixelFormat, PixelType, target); 611 0, PixelFormat, PixelType, target);
612 // get next prepared mipmap data if available 612 // get next prepared mipmap data if available
613 if (mipmapData) 613 if (mipmapData)
614 { 614 {
615 mipmapData = static_cast<u8*>(mipmapData)+width*height*Image->getBytesPerPixel(); 615 mipmapData = static_cast<u8*>(mipmapData)+width*height*Image->getBytesPerPixel();
616 target = static_cast<u8*>(mipmapData); 616 target = static_cast<u8*>(mipmapData);
617 } 617 }
618 } 618 }
619 while (width!=1 || height!=1); 619 while (width!=1 || height!=1);
620 // cleanup 620 // cleanup
621 if (!mipmapData) 621 if (!mipmapData)
622 delete [] target; 622 delete [] target;
623} 623}
624 624
625 625
626bool COpenGLTexture::isRenderTarget() const 626bool COpenGLTexture::isRenderTarget() const
627{ 627{
628 return IsRenderTarget; 628 return IsRenderTarget;
629} 629}
630 630
631 631
632void COpenGLTexture::setIsRenderTarget(bool isTarget) 632void COpenGLTexture::setIsRenderTarget(bool isTarget)
633{ 633{
634 IsRenderTarget = isTarget; 634 IsRenderTarget = isTarget;
635} 635}
636 636
637 637
638bool COpenGLTexture::isFrameBufferObject() const 638bool COpenGLTexture::isFrameBufferObject() const
639{ 639{
640 return false; 640 return false;
641} 641}
642 642
643 643
644//! Bind Render Target Texture 644//! Bind Render Target Texture
645void COpenGLTexture::bindRTT() 645void COpenGLTexture::bindRTT()
646{ 646{
647} 647}
648 648
649 649
650//! Unbind Render Target Texture 650//! Unbind Render Target Texture
651void COpenGLTexture::unbindRTT() 651void COpenGLTexture::unbindRTT()
652{ 652{
653 Driver->setActiveTexture(0, this); 653 Driver->setActiveTexture(0, this);
654 654
655 // Copy Our ViewPort To The Texture 655 // Copy Our ViewPort To The Texture
656 glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, getSize().Width, getSize().Height); 656 glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, getSize().Width, getSize().Height);
657} 657}
658 658
659 659
660/* FBO Textures */ 660/* FBO Textures */
661 661
662// helper function for render to texture 662// helper function for render to texture
663static bool checkFBOStatus(COpenGLDriver* Driver); 663static bool checkFBOStatus(COpenGLDriver* Driver);
664 664
665//! RTT ColorFrameBuffer constructor 665//! RTT ColorFrameBuffer constructor
666COpenGLFBOTexture::COpenGLFBOTexture(const core::dimension2d<u32>& size, 666COpenGLFBOTexture::COpenGLFBOTexture(const core::dimension2d<u32>& size,
667 const io::path& name, COpenGLDriver* driver, 667 const io::path& name, COpenGLDriver* driver,
668 ECOLOR_FORMAT format) 668 ECOLOR_FORMAT format)
669 : COpenGLTexture(name, driver), DepthTexture(0), ColorFrameBuffer(0) 669 : COpenGLTexture(name, driver), DepthTexture(0), ColorFrameBuffer(0)
670{ 670{
671 #ifdef _DEBUG 671 #ifdef _DEBUG
672 setDebugName("COpenGLTexture_FBO"); 672 setDebugName("COpenGLTexture_FBO");
673 #endif 673 #endif
674 674
675 ImageSize = size; 675 ImageSize = size;
676 TextureSize = size; 676 TextureSize = size;
677 677
678 if (ECF_UNKNOWN == format) 678 if (ECF_UNKNOWN == format)
679 format = getBestColorFormat(driver->getColorFormat()); 679 format = getBestColorFormat(driver->getColorFormat());
680 680
681 ColorFormat = format; 681 ColorFormat = format;
682 682
683 GLint FilteringType; 683 GLint FilteringType;
684 InternalFormat = getOpenGLFormatAndParametersFromColorFormat(format, FilteringType, PixelFormat, PixelType); 684 InternalFormat = getOpenGLFormatAndParametersFromColorFormat(format, FilteringType, PixelFormat, PixelType);
685 685
686 HasMipMaps = false; 686 HasMipMaps = false;
687 IsRenderTarget = true; 687 IsRenderTarget = true;
688 688
689#ifdef GL_EXT_framebuffer_object 689#ifdef GL_EXT_framebuffer_object
690 // generate frame buffer 690 // generate frame buffer
691 Driver->extGlGenFramebuffers(1, &ColorFrameBuffer); 691 Driver->extGlGenFramebuffers(1, &ColorFrameBuffer);
692 bindRTT(); 692 bindRTT();
693 693
694 // generate color texture 694 // generate color texture
695 glGenTextures(1, &TextureName); 695 glGenTextures(1, &TextureName);
696 Driver->setActiveTexture(0, this); 696 Driver->setActiveTexture(0, this);
697 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, FilteringType); 697 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, FilteringType);
698 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); 698 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
699 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); 699 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
700 glTexImage2D(GL_TEXTURE_2D, 0, InternalFormat, ImageSize.Width, 700 glTexImage2D(GL_TEXTURE_2D, 0, InternalFormat, ImageSize.Width,
701 ImageSize.Height, 0, PixelFormat, PixelType, 0); 701 ImageSize.Height, 0, PixelFormat, PixelType, 0);
702#ifdef _DEBUG 702#ifdef _DEBUG
703 driver->testGLError(); 703 driver->testGLError();
704#endif 704#endif
705 705
706 // attach color texture to frame buffer 706 // attach color texture to frame buffer
707 Driver->extGlFramebufferTexture2D(GL_FRAMEBUFFER_EXT, 707 Driver->extGlFramebufferTexture2D(GL_FRAMEBUFFER_EXT,
708 GL_COLOR_ATTACHMENT0_EXT, 708 GL_COLOR_ATTACHMENT0_EXT,
709 GL_TEXTURE_2D, 709 GL_TEXTURE_2D,
710 TextureName, 710 TextureName,
711 0); 711 0);
712#ifdef _DEBUG 712#ifdef _DEBUG
713 checkFBOStatus(Driver); 713 checkFBOStatus(Driver);
714#endif 714#endif
715 715
716#endif 716#endif
717 unbindRTT(); 717 unbindRTT();
718} 718}
719 719
720 720
721//! destructor 721//! destructor
722COpenGLFBOTexture::~COpenGLFBOTexture() 722COpenGLFBOTexture::~COpenGLFBOTexture()
723{ 723{
724 if (DepthTexture) 724 if (DepthTexture)
725 if (DepthTexture->drop()) 725 if (DepthTexture->drop())
726 Driver->removeDepthTexture(DepthTexture); 726 Driver->removeDepthTexture(DepthTexture);
727 if (ColorFrameBuffer) 727 if (ColorFrameBuffer)
728 Driver->extGlDeleteFramebuffers(1, &ColorFrameBuffer); 728 Driver->extGlDeleteFramebuffers(1, &ColorFrameBuffer);
729} 729}
730 730
731 731
732bool COpenGLFBOTexture::isFrameBufferObject() const 732bool COpenGLFBOTexture::isFrameBufferObject() const
733{ 733{
734 return true; 734 return true;
735} 735}
736 736
737 737
738//! Bind Render Target Texture 738//! Bind Render Target Texture
739void COpenGLFBOTexture::bindRTT() 739void COpenGLFBOTexture::bindRTT()
740{ 740{
741#ifdef GL_EXT_framebuffer_object 741#ifdef GL_EXT_framebuffer_object
742 if (ColorFrameBuffer != 0) 742 if (ColorFrameBuffer != 0)
743 Driver->extGlBindFramebuffer(GL_FRAMEBUFFER_EXT, ColorFrameBuffer); 743 Driver->extGlBindFramebuffer(GL_FRAMEBUFFER_EXT, ColorFrameBuffer);
744 glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT); 744 glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT);
745#endif 745#endif
746} 746}
747 747
748 748
749//! Unbind Render Target Texture 749//! Unbind Render Target Texture
750void COpenGLFBOTexture::unbindRTT() 750void COpenGLFBOTexture::unbindRTT()
751{ 751{
752#ifdef GL_EXT_framebuffer_object 752#ifdef GL_EXT_framebuffer_object
753 if (ColorFrameBuffer != 0) 753 if (ColorFrameBuffer != 0)
754 Driver->extGlBindFramebuffer(GL_FRAMEBUFFER_EXT, 0); 754 Driver->extGlBindFramebuffer(GL_FRAMEBUFFER_EXT, 0);
755#endif 755#endif
756} 756}
757 757
758 758
759/* FBO Depth Textures */ 759/* FBO Depth Textures */
760 760
761//! RTT DepthBuffer constructor 761//! RTT DepthBuffer constructor
762COpenGLFBODepthTexture::COpenGLFBODepthTexture( 762COpenGLFBODepthTexture::COpenGLFBODepthTexture(
763 const core::dimension2d<u32>& size, 763 const core::dimension2d<u32>& size,
764 const io::path& name, 764 const io::path& name,
765 COpenGLDriver* driver, 765 COpenGLDriver* driver,
766 bool useStencil) 766 bool useStencil)
767 : COpenGLTexture(name, driver), DepthRenderBuffer(0), 767 : COpenGLTexture(name, driver), DepthRenderBuffer(0),
768 StencilRenderBuffer(0), UseStencil(useStencil) 768 StencilRenderBuffer(0), UseStencil(useStencil)
769{ 769{
770#ifdef _DEBUG 770#ifdef _DEBUG
771 setDebugName("COpenGLTextureFBO_Depth"); 771 setDebugName("COpenGLTextureFBO_Depth");
772#endif 772#endif
773 773
774 ImageSize = size; 774 ImageSize = size;
775 TextureSize = size; 775 TextureSize = size;
776 InternalFormat = GL_RGBA; 776 InternalFormat = GL_RGBA;
777 PixelFormat = GL_RGBA; 777 PixelFormat = GL_RGBA;
778 PixelType = GL_UNSIGNED_BYTE; 778 PixelType = GL_UNSIGNED_BYTE;
779 HasMipMaps = false; 779 HasMipMaps = false;
780 780
781 if (useStencil) 781 if (useStencil)
782 { 782 {
783 glGenTextures(1, &DepthRenderBuffer); 783 glGenTextures(1, &DepthRenderBuffer);
784 glBindTexture(GL_TEXTURE_2D, DepthRenderBuffer); 784 glBindTexture(GL_TEXTURE_2D, DepthRenderBuffer);
785 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 785 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
786 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); 786 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
787 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); 787 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
788#ifdef GL_EXT_packed_depth_stencil 788#ifdef GL_EXT_packed_depth_stencil
789 if (Driver->queryOpenGLFeature(COpenGLExtensionHandler::IRR_EXT_packed_depth_stencil)) 789 if (Driver->queryOpenGLFeature(COpenGLExtensionHandler::IRR_EXT_packed_depth_stencil))
790 { 790 {
791 // generate packed depth stencil texture 791 // generate packed depth stencil texture
792 glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_STENCIL_EXT, ImageSize.Width, 792 glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_STENCIL_EXT, ImageSize.Width,
793 ImageSize.Height, 0, GL_DEPTH_STENCIL_EXT, GL_UNSIGNED_INT_24_8_EXT, 0); 793 ImageSize.Height, 0, GL_DEPTH_STENCIL_EXT, GL_UNSIGNED_INT_24_8_EXT, 0);
794 StencilRenderBuffer = DepthRenderBuffer; // stencil is packed with depth 794 StencilRenderBuffer = DepthRenderBuffer; // stencil is packed with depth
795 } 795 }
796 else // generate separate stencil and depth textures 796 else // generate separate stencil and depth textures
797#endif 797#endif
798 { 798 {
799 // generate depth texture 799 // generate depth texture
800 glTexImage2D(GL_TEXTURE_2D, 0, Driver->getZBufferBits(), ImageSize.Width, 800 glTexImage2D(GL_TEXTURE_2D, 0, Driver->getZBufferBits(), ImageSize.Width,
801 ImageSize.Height, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, 0); 801 ImageSize.Height, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, 0);
802 802
803 // generate stencil texture 803 // generate stencil texture
804 glGenTextures(1, &StencilRenderBuffer); 804 glGenTextures(1, &StencilRenderBuffer);
805 glBindTexture(GL_TEXTURE_2D, StencilRenderBuffer); 805 glBindTexture(GL_TEXTURE_2D, StencilRenderBuffer);
806 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 806 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
807 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); 807 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
808 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); 808 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
809 glTexImage2D(GL_TEXTURE_2D, 0, GL_STENCIL_INDEX, ImageSize.Width, 809 glTexImage2D(GL_TEXTURE_2D, 0, GL_STENCIL_INDEX, ImageSize.Width,
810 ImageSize.Height, 0, GL_STENCIL_INDEX, GL_UNSIGNED_BYTE, 0); 810 ImageSize.Height, 0, GL_STENCIL_INDEX, GL_UNSIGNED_BYTE, 0);
811 } 811 }
812 } 812 }
813#ifdef GL_EXT_framebuffer_object 813#ifdef GL_EXT_framebuffer_object
814 else 814 else
815 { 815 {
816 // generate depth buffer 816 // generate depth buffer
817 Driver->extGlGenRenderbuffers(1, &DepthRenderBuffer); 817 Driver->extGlGenRenderbuffers(1, &DepthRenderBuffer);
818 Driver->extGlBindRenderbuffer(GL_RENDERBUFFER_EXT, DepthRenderBuffer); 818 Driver->extGlBindRenderbuffer(GL_RENDERBUFFER_EXT, DepthRenderBuffer);
819 Driver->extGlRenderbufferStorage(GL_RENDERBUFFER_EXT, 819 Driver->extGlRenderbufferStorage(GL_RENDERBUFFER_EXT,
820 Driver->getZBufferBits(), ImageSize.Width, 820 Driver->getZBufferBits(), ImageSize.Width,
821 ImageSize.Height); 821 ImageSize.Height);
822 } 822 }
823#endif 823#endif
824} 824}
825 825
826 826
827//! destructor 827//! destructor
828COpenGLFBODepthTexture::~COpenGLFBODepthTexture() 828COpenGLFBODepthTexture::~COpenGLFBODepthTexture()
829{ 829{
830 if (DepthRenderBuffer && UseStencil) 830 if (DepthRenderBuffer && UseStencil)
831 glDeleteTextures(1, &DepthRenderBuffer); 831 glDeleteTextures(1, &DepthRenderBuffer);
832 else 832 else
833 Driver->extGlDeleteRenderbuffers(1, &DepthRenderBuffer); 833 Driver->extGlDeleteRenderbuffers(1, &DepthRenderBuffer);
834 if (StencilRenderBuffer && StencilRenderBuffer != DepthRenderBuffer) 834 if (StencilRenderBuffer && StencilRenderBuffer != DepthRenderBuffer)
835 glDeleteTextures(1, &StencilRenderBuffer); 835 glDeleteTextures(1, &StencilRenderBuffer);
836} 836}
837 837
838 838
839//combine depth texture and rtt 839//combine depth texture and rtt
840bool COpenGLFBODepthTexture::attach(ITexture* renderTex) 840bool COpenGLFBODepthTexture::attach(ITexture* renderTex)
841{ 841{
842 if (!renderTex) 842 if (!renderTex)
843 return false; 843 return false;
844 video::COpenGLFBOTexture* rtt = static_cast<video::COpenGLFBOTexture*>(renderTex); 844 video::COpenGLFBOTexture* rtt = static_cast<video::COpenGLFBOTexture*>(renderTex);
845 rtt->bindRTT(); 845 rtt->bindRTT();
846#ifdef GL_EXT_framebuffer_object 846#ifdef GL_EXT_framebuffer_object
847 if (UseStencil) 847 if (UseStencil)
848 { 848 {
849 // attach stencil texture to stencil buffer 849 // attach stencil texture to stencil buffer
850 Driver->extGlFramebufferTexture2D(GL_FRAMEBUFFER_EXT, 850 Driver->extGlFramebufferTexture2D(GL_FRAMEBUFFER_EXT,
851 GL_STENCIL_ATTACHMENT_EXT, 851 GL_STENCIL_ATTACHMENT_EXT,
852 GL_TEXTURE_2D, 852 GL_TEXTURE_2D,
853 StencilRenderBuffer, 853 StencilRenderBuffer,
854 0); 854 0);
855 855
856 // attach depth texture to depth buffer 856 // attach depth texture to depth buffer
857 Driver->extGlFramebufferTexture2D(GL_FRAMEBUFFER_EXT, 857 Driver->extGlFramebufferTexture2D(GL_FRAMEBUFFER_EXT,
858 GL_DEPTH_ATTACHMENT_EXT, 858 GL_DEPTH_ATTACHMENT_EXT,
859 GL_TEXTURE_2D, 859 GL_TEXTURE_2D,
860 DepthRenderBuffer, 860 DepthRenderBuffer,
861 0); 861 0);
862 } 862 }
863 else 863 else
864 { 864 {
865 // attach depth renderbuffer to depth buffer 865 // attach depth renderbuffer to depth buffer
866 Driver->extGlFramebufferRenderbuffer(GL_FRAMEBUFFER_EXT, 866 Driver->extGlFramebufferRenderbuffer(GL_FRAMEBUFFER_EXT,
867 GL_DEPTH_ATTACHMENT_EXT, 867 GL_DEPTH_ATTACHMENT_EXT,
868 GL_RENDERBUFFER_EXT, 868 GL_RENDERBUFFER_EXT,
869 DepthRenderBuffer); 869 DepthRenderBuffer);
870 } 870 }
871#endif 871#endif
872 // check the status 872 // check the status
873 if (!checkFBOStatus(Driver)) 873 if (!checkFBOStatus(Driver))
874 { 874 {
875 os::Printer::log("FBO incomplete"); 875 os::Printer::log("FBO incomplete");
876 return false; 876 return false;
877 } 877 }
878 rtt->DepthTexture=this; 878 rtt->DepthTexture=this;
879 grab(); // grab the depth buffer, not the RTT 879 grab(); // grab the depth buffer, not the RTT
880 rtt->unbindRTT(); 880 rtt->unbindRTT();
881 return true; 881 return true;
882} 882}
883 883
884 884
885//! Bind Render Target Texture 885//! Bind Render Target Texture
886void COpenGLFBODepthTexture::bindRTT() 886void COpenGLFBODepthTexture::bindRTT()
887{ 887{
888} 888}
889 889
890 890
891//! Unbind Render Target Texture 891//! Unbind Render Target Texture
892void COpenGLFBODepthTexture::unbindRTT() 892void COpenGLFBODepthTexture::unbindRTT()
893{ 893{
894} 894}
895 895
896 896
897bool checkFBOStatus(COpenGLDriver* Driver) 897bool checkFBOStatus(COpenGLDriver* Driver)
898{ 898{
899#ifdef GL_EXT_framebuffer_object 899#ifdef GL_EXT_framebuffer_object
900 GLenum status = Driver->extGlCheckFramebufferStatus(GL_FRAMEBUFFER_EXT); 900 GLenum status = Driver->extGlCheckFramebufferStatus(GL_FRAMEBUFFER_EXT);
901 901
902 switch (status) 902 switch (status)
903 { 903 {
904 //Our FBO is perfect, return true 904 //Our FBO is perfect, return true
905 case GL_FRAMEBUFFER_COMPLETE_EXT: 905 case GL_FRAMEBUFFER_COMPLETE_EXT:
906 return true; 906 return true;
907 907
908 case GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT: 908 case GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT:
909 os::Printer::log("FBO has invalid read buffer", ELL_ERROR); 909 os::Printer::log("FBO has invalid read buffer", ELL_ERROR);
910 break; 910 break;
911 911
912 case GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT: 912 case GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT:
913 os::Printer::log("FBO has invalid draw buffer", ELL_ERROR); 913 os::Printer::log("FBO has invalid draw buffer", ELL_ERROR);
914 break; 914 break;
915 915
916 case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT: 916 case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT:
917 os::Printer::log("FBO has one or several incomplete image attachments", ELL_ERROR); 917 os::Printer::log("FBO has one or several incomplete image attachments", ELL_ERROR);
918 break; 918 break;
919 919
920 case GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT: 920 case GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT:
921 os::Printer::log("FBO has one or several image attachments with different internal formats", ELL_ERROR); 921 os::Printer::log("FBO has one or several image attachments with different internal formats", ELL_ERROR);
922 break; 922 break;
923 923
924 case GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT: 924 case GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT:
925 os::Printer::log("FBO has one or several image attachments with different dimensions", ELL_ERROR); 925 os::Printer::log("FBO has one or several image attachments with different dimensions", ELL_ERROR);
926 break; 926 break;
927 927
928// not part of fbo_object anymore, but won't harm as it is just a return value 928// not part of fbo_object anymore, but won't harm as it is just a return value
929#ifdef GL_FRAMEBUFFER_INCOMPLETE_DUPLICATE_ATTACHMENT_EXT 929#ifdef GL_FRAMEBUFFER_INCOMPLETE_DUPLICATE_ATTACHMENT_EXT
930 case GL_FRAMEBUFFER_INCOMPLETE_DUPLICATE_ATTACHMENT_EXT: 930 case GL_FRAMEBUFFER_INCOMPLETE_DUPLICATE_ATTACHMENT_EXT:
931 os::Printer::log("FBO has a duplicate image attachment", ELL_ERROR); 931 os::Printer::log("FBO has a duplicate image attachment", ELL_ERROR);
932 break; 932 break;
933#endif 933#endif
934 934
935 case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT: 935 case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT:
936 os::Printer::log("FBO missing an image attachment", ELL_ERROR); 936 os::Printer::log("FBO missing an image attachment", ELL_ERROR);
937 break; 937 break;
938 938
939#ifdef GL_EXT_framebuffer_multisample 939#ifdef GL_EXT_framebuffer_multisample
940 case GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_EXT: 940 case GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_EXT:
941 os::Printer::log("FBO wrong multisample setup", ELL_ERROR); 941 os::Printer::log("FBO wrong multisample setup", ELL_ERROR);
942 break; 942 break;
943#endif 943#endif
944 944
945 case GL_FRAMEBUFFER_UNSUPPORTED_EXT: 945 case GL_FRAMEBUFFER_UNSUPPORTED_EXT:
946 os::Printer::log("FBO format unsupported", ELL_ERROR); 946 os::Printer::log("FBO format unsupported", ELL_ERROR);
947 break; 947 break;
948 948
949 default: 949 default:
950 break; 950 break;
951 } 951 }
952#endif 952#endif
953 os::Printer::log("FBO error", ELL_ERROR); 953 os::Printer::log("FBO error", ELL_ERROR);
954// _IRR_DEBUG_BREAK_IF(true); 954// _IRR_DEBUG_BREAK_IF(true);
955 return false; 955 return false;
956} 956}
957 957
958 958
959} // end namespace video 959} // end namespace video
960} // end namespace irr 960} // end namespace irr
961 961
962#endif // _IRR_COMPILE_WITH_OPENGL_ 962#endif // _IRR_COMPILE_WITH_OPENGL_
963 963