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