1 #include "MyGUI_OpenGLESTexture.h" 2 #include "MyGUI_OpenGLESRenderManager.h" 3 #include "MyGUI_OpenGLESDiagnostic.h" 4 #include "MyGUI_OpenGLESPlatform.h" 5 #include "MyGUI_OpenGLESRTTexture.h" 6 7 #include "platform.h" 8 9 namespace MyGUI 10 { 11 OpenGLESTexture(const std::string & _name,OpenGLESImageLoader * _loader)12 OpenGLESTexture::OpenGLESTexture(const std::string& _name, OpenGLESImageLoader* _loader) : 13 mName(_name), 14 mTextureID(0), 15 mPboID(0), 16 mWidth(0), 17 mHeight(0), 18 mLock(false), 19 mPixelFormat(0), 20 mDataSize(0), 21 mUsage(0), 22 mBuffer(0), 23 mInternalPixelFormat(0), 24 mAccess(0), 25 mNumElemBytes(0), 26 mImageLoader(_loader), 27 mRenderTarget(nullptr) 28 { 29 } 30 ~OpenGLESTexture()31 OpenGLESTexture::~OpenGLESTexture() 32 { 33 destroy(); 34 } 35 getName() const36 const std::string& OpenGLESTexture::getName() const 37 { 38 return mName; 39 } 40 setUsage(TextureUsage _usage)41 void OpenGLESTexture::setUsage(TextureUsage _usage) 42 { 43 mAccess = 0; 44 mUsage = 0; 45 } 46 createManual(int _width,int _height,TextureUsage _usage,PixelFormat _format)47 void OpenGLESTexture::createManual(int _width, int _height, TextureUsage _usage, PixelFormat _format) 48 { 49 createManual(_width, _height, _usage, _format, 0); 50 } 51 createManual(int _width,int _height,TextureUsage _usage,PixelFormat _format,void * _data)52 void OpenGLESTexture::createManual(int _width, int _height, TextureUsage _usage, PixelFormat _format, void* _data) 53 { 54 MYGUI_PLATFORM_ASSERT(!mTextureID, "Texture already exist"); 55 56 //FIXME перенести в метод 57 mInternalPixelFormat = 0; 58 mPixelFormat = 0; 59 mNumElemBytes = 0; 60 if (_format == PixelFormat::L8) 61 { 62 mInternalPixelFormat = GL_LUMINANCE; 63 mPixelFormat = GL_LUMINANCE; 64 mNumElemBytes = 1; 65 } 66 else if (_format == PixelFormat::L8A8) 67 { 68 mInternalPixelFormat = GL_LUMINANCE_ALPHA; 69 mPixelFormat = GL_LUMINANCE_ALPHA; 70 mNumElemBytes = 2; 71 } 72 else if (_format == PixelFormat::R8G8B8) 73 { 74 mInternalPixelFormat = GL_RGB; 75 mPixelFormat = GL_RGB; 76 mNumElemBytes = 3; 77 } 78 else if (_format == PixelFormat::R8G8B8A8) 79 { 80 mInternalPixelFormat = GL_RGBA; 81 mPixelFormat = GL_RGBA; 82 mNumElemBytes = 4; 83 } 84 else 85 { 86 MYGUI_PLATFORM_EXCEPT("format not support"); 87 } 88 89 mWidth = _width; 90 mHeight = _height; 91 mDataSize = _width * _height * mNumElemBytes; 92 setUsage(_usage); 93 //MYGUI_PLATFORM_ASSERT(mUsage, "usage format not support"); 94 95 mOriginalFormat = _format; 96 mOriginalUsage = _usage; 97 98 // Set unpack alignment to one byte 99 int alignment = 0; 100 glGetIntegerv( GL_UNPACK_ALIGNMENT, (GLint *)&alignment ); 101 CHECK_GL_ERROR_DEBUG(); 102 glPixelStorei( GL_UNPACK_ALIGNMENT, 1 ); 103 CHECK_GL_ERROR_DEBUG(); 104 105 // создаем тукстуру 106 glGenTextures(1, (GLuint *)&mTextureID); 107 CHECK_GL_ERROR_DEBUG(); 108 glBindTexture(GL_TEXTURE_2D, mTextureID); 109 CHECK_GL_ERROR_DEBUG(); 110 // Set texture parameters 111 112 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); // GL_LINEAR 113 CHECK_GL_ERROR_DEBUG(); 114 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 115 CHECK_GL_ERROR_DEBUG(); 116 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); 117 CHECK_GL_ERROR_DEBUG(); 118 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); 119 CHECK_GL_ERROR_DEBUG(); 120 121 glTexImage2D(GL_TEXTURE_2D, 0, mInternalPixelFormat, mWidth, mHeight, 0, mPixelFormat, GL_UNSIGNED_BYTE, (GLvoid*)_data); 122 CHECK_GL_ERROR_DEBUG(); 123 glBindTexture(GL_TEXTURE_2D, 0); 124 CHECK_GL_ERROR_DEBUG(); 125 126 // Restore old unpack alignment 127 //glPixelStorei( GL_UNPACK_ALIGNMENT, alignment ); 128 //CHECK_GL_ERROR_DEBUG(); 129 #ifdef PixelBufferObjectSupported 130 if (!_data && OpenGLESRenderManager::getInstance().isPixelBufferObjectSupported()) 131 { 132 //создаем текстурнный буфер 133 //glGenBuffersARB(1, (GLuint *)&mPboID); 134 //glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, mPboID); 135 //glBufferDataARB(GL_PIXEL_UNPACK_BUFFER_ARB, mDataSize, 0, mUsage); 136 //glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, 0); 137 138 glGenBuffers(1, (GLuint *)&mPboID); 139 CHECK_GL_ERROR_DEBUG(); 140 glBindBuffer(GL_PIXEL_UNPACK_BUFFER, mPboID); 141 CHECK_GL_ERROR_DEBUG(); 142 glBufferData(GL_PIXEL_UNPACK_BUFFER, mDataSize, 0, mUsage); 143 CHECK_GL_ERROR_DEBUG(); 144 glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0); 145 CHECK_GL_ERROR_DEBUG(); 146 147 } 148 #endif 149 } 150 destroy()151 void OpenGLESTexture::destroy() 152 { 153 if (mRenderTarget != nullptr) 154 { 155 delete mRenderTarget; 156 mRenderTarget = nullptr; 157 } 158 159 if (mTextureID != 0) 160 { 161 glDeleteTextures(1, (GLuint *)&mTextureID); 162 mTextureID = 0; 163 } 164 if (mPboID != 0) 165 { 166 glDeleteBuffers(1, (GLuint *)&mPboID); 167 mPboID = 0; 168 } 169 170 mWidth = 0; 171 mHeight = 0; 172 mLock = false; 173 mPixelFormat = 0; 174 mDataSize = 0; 175 mUsage = 0; 176 mBuffer = nullptr; 177 mInternalPixelFormat = 0; 178 mAccess = 0; 179 mNumElemBytes = 0; 180 mOriginalFormat = PixelFormat::Unknow; 181 mOriginalUsage = TextureUsage::Default; 182 } 183 lock(TextureUsage _access)184 void* OpenGLESTexture::lock(TextureUsage _access) 185 { 186 MYGUI_PLATFORM_ASSERT(mTextureID, "Texture is not created"); 187 188 /* 189 if (_access == TextureUsage::Read) 190 { 191 glBindTexture(GL_TEXTURE_2D, mTextureID); 192 CHECK_GL_ERROR_DEBUG(); 193 194 mBuffer = new unsigned char[mDataSize]; 195 //glGetTexImage(GL_TEXTURE_2D, 0, mPixelFormat, GL_UNSIGNED_BYTE, mBuffer); 196 197 mLock = false; 198 199 return mBuffer; 200 }*/ 201 202 // bind the texture 203 glBindTexture(GL_TEXTURE_2D, mTextureID); 204 CHECK_GL_ERROR_DEBUG(); 205 if (!OpenGLESRenderManager::getInstance().isPixelBufferObjectSupported()) 206 { 207 //Fallback if PBO's are not supported 208 mBuffer = new unsigned char[mDataSize]; 209 } 210 else 211 { 212 #ifdef PixelBufferObjectSupported 213 // bind the PBO 214 //glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, mPboID); 215 glBindBuffer(GL_PIXEL_UNPACK_BUFFER, mPboID); 216 CHECK_GL_ERROR_DEBUG(); 217 218 // Note that glMapBufferARB() causes sync issue. 219 // If GPU is working with this buffer, glMapBufferARB() will wait(stall) 220 // until GPU to finish its job. To avoid waiting (idle), you can call 221 // first glBufferDataARB() with nullptr pointer before glMapBufferARB(). 222 // If you do that, the previous data in PBO will be discarded and 223 // glMapBufferARB() returns a new allocated pointer immediately 224 // even if GPU is still working with the previous data. 225 //glBufferDataARB(GL_PIXEL_UNPACK_BUFFER_ARB, mDataSize, 0, mUsage); 226 glBufferData(GL_PIXEL_UNPACK_BUFFER, mDataSize, 0, mUsage); 227 CHECK_GL_ERROR_DEBUG(); 228 229 // map the buffer object into client's memory 230 //mBuffer = (GLubyte*)glMapBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, mAccess); 231 mBuffer = (GLubyte*)glMapBufferOES(GL_PIXEL_UNPACK_BUFFER_ARB, mAccess); 232 CHECK_GL_ERROR_DEBUG(); 233 if (!mBuffer) 234 { 235 //glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, 0); 236 glBindBuffer(GL_PIXEL_UNPACK_BUFFER_ARB, 0); 237 CHECK_GL_ERROR_DEBUG(); 238 glBindTexture(GL_TEXTURE_2D, 0); 239 CHECK_GL_ERROR_DEBUG(); 240 MYGUI_PLATFORM_EXCEPT("Error texture lock"); 241 } 242 #endif 243 } 244 245 mLock = true; 246 247 return mBuffer; 248 } 249 unlock()250 void OpenGLESTexture::unlock() 251 { 252 if (!mLock && mBuffer) 253 { 254 delete (unsigned char*)mBuffer; 255 mBuffer = nullptr; 256 257 glBindTexture(GL_TEXTURE_2D, 0); 258 CHECK_GL_ERROR_DEBUG(); 259 260 return; 261 } 262 263 MYGUI_PLATFORM_ASSERT(mLock, "Texture is not locked"); 264 265 if (!OpenGLESRenderManager::getInstance().isPixelBufferObjectSupported()) 266 { 267 //Fallback if PBO's are not supported 268 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, mWidth, mHeight, mPixelFormat, GL_UNSIGNED_BYTE, mBuffer); 269 CHECK_GL_ERROR_DEBUG(); 270 delete (unsigned char*)mBuffer; 271 } 272 else 273 { 274 #ifdef PixelBufferObjectSupported 275 // release the mapped buffer 276 //glUnmapBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB); 277 glUnmapBufferOES(GL_PIXEL_UNPACK_BUFFER_ARB); 278 CHECK_GL_ERROR_DEBUG(); 279 280 // copy pixels from PBO to texture object 281 // Use offset instead of ponter. 282 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, mWidth, mHeight, mPixelFormat, GL_UNSIGNED_BYTE, 0); 283 CHECK_GL_ERROR_DEBUG(); 284 285 // it is good idea to release PBOs with ID 0 after use. 286 // Once bound with 0, all pixel operations are back to normal ways. 287 //glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, 0); 288 glBindBuffer(GL_PIXEL_UNPACK_BUFFER_ARB, 0); 289 CHECK_GL_ERROR_DEBUG(); 290 #endif 291 } 292 293 glBindTexture(GL_TEXTURE_2D, 0); 294 CHECK_GL_ERROR_DEBUG(); 295 mBuffer = nullptr; 296 mLock = false; 297 } 298 loadFromFile(const std::string & _filename)299 void OpenGLESTexture::loadFromFile(const std::string& _filename) 300 { 301 destroy(); 302 303 if (mImageLoader) 304 { 305 int width = 0; 306 int height = 0; 307 PixelFormat format = PixelFormat::Unknow; 308 309 void* data = mImageLoader->loadImage(width, height, format, _filename); 310 if (data) 311 { 312 createManual(width, height, TextureUsage::Static | TextureUsage::Write, format, data); 313 delete (unsigned char*)data; 314 } 315 } 316 } 317 saveToFile(const std::string & _filename)318 void OpenGLESTexture::saveToFile(const std::string& _filename) 319 { 320 if (mImageLoader) 321 { 322 void* data = lock(TextureUsage::Read); 323 mImageLoader->saveImage(mWidth, mHeight, mOriginalFormat, data, _filename); 324 unlock(); 325 } 326 } 327 getRenderTarget()328 IRenderTarget* OpenGLESTexture::getRenderTarget() 329 { 330 if (mRenderTarget == nullptr) 331 mRenderTarget = new OpenGLESRTTexture(mTextureID); 332 333 return mRenderTarget; 334 } 335 getTextureID() const336 unsigned int OpenGLESTexture::getTextureID() const 337 { 338 return mTextureID; 339 } 340 341 } // namespace MyGUI 342