d2c1b0d7b682377b899d2d7d160e905a9a66c087
[platform/core/uifw/dali-core.git] / dali / internal / render / gl-resources / texture.cpp
1 /*
2  * Copyright (c) 2014 Samsung Electronics Co., Ltd.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  *
16  */
17
18 // CLASS HEADER
19 #include <dali/internal/render/gl-resources/texture.h>
20
21 // EXTERNAL INCLUDES
22 #include <math.h>
23 #include <memory.h>
24
25 // INTERNAL INCLUDES
26 #include <dali/integration-api/debug.h>
27 #include <dali/internal/render/common/vertex.h>
28 #include <dali/internal/render/gl-resources/context.h>
29 #include <dali/internal/common/image-sampler.h>
30
31 namespace Dali
32 {
33
34 namespace Internal
35 {
36
37 namespace
38 {
39
40 // These match the GL specification
41 const GLint SYSTEM_MINIFY_DEFAULT  = GL_NEAREST_MIPMAP_LINEAR;
42 const GLint SYSTEM_MAGNIFY_DEFAULT = GL_LINEAR;
43
44 // These are the Dali defaults
45 const GLint DALI_MINIFY_DEFAULT  = GL_LINEAR;
46 const GLint DALI_MAGNIFY_DEFAULT = GL_LINEAR;
47
48 } // namespace
49
50 /**
51  * @brief Convert a FilterMode to it's corresponding GL type.
52  *
53  * @param[in] filterMode The FilterMode type.
54  * @param[in] defaultfilterMode The filter mode to use if filterMode is DEFAULT.
55  * @param[in] defaultSystemFilterMode The filter mode to use if filterMode is NONE.
56  * @return Return the equivalent GL type.
57  */
58 GLint FilterModeToGL( FilterMode::Type filterMode, GLint defaultfilterMode, GLint defaultSystemFilterMode )
59 {
60   switch( filterMode )
61   {
62     case FilterMode::NEAREST:
63     {
64       return GL_NEAREST;
65     }
66     case FilterMode::LINEAR:
67     {
68       return GL_LINEAR;
69     }
70     case FilterMode::NONE:
71     {
72       return defaultSystemFilterMode;
73     }
74     case FilterMode::DEFAULT:
75     {
76       return defaultfilterMode;
77     }
78   }
79
80   return GL_LINEAR;
81 }
82
83 using Dali::Internal::Vertex2D;
84 using Dali::Internal::Vertex3D;
85
86 using namespace Dali::Pixel;
87
88 Texture::Texture(Context&      context,
89                  unsigned int  width,
90                  unsigned int  height,
91                  unsigned int  imageWidth,
92                  unsigned int  imageHeight,
93                  Pixel::Format pixelFormat)
94 : mContext(context),
95   mId(0),
96   mSamplerBitfield( 0 ),
97   mWidth(width),
98   mHeight(height),
99   mImageWidth(imageWidth),
100   mImageHeight(imageHeight),
101   mPixelFormat(pixelFormat)
102 {
103 }
104
105 Texture::~Texture()
106 {
107   // GlCleanup() should already have been called by TextureCache ensuring the resource is destroyed
108   // on the render thread. (And avoiding a potentially problematic virtual call in the destructor)
109 }
110
111 void Texture::SetTextureId(GLuint id)
112 {
113   mId=id;
114 }
115
116 void Texture::Update(Integration::Bitmap* bitmap)
117 {
118   DALI_ASSERT_DEBUG( "Updating incorrect texture type" == NULL );
119 }
120
121 void Texture::UpdateArea( const RectArea& area )
122 {
123   DALI_ASSERT_DEBUG( "Updating incorrect texture type" == NULL );
124 }
125
126 bool Texture::UpdateOnCreate()
127 {
128   return false;
129 }
130
131 bool Texture::Bind(GLenum target, TextureUnit textureunit )
132 {
133   // This is the only supported type at the moment
134   DALI_ASSERT_DEBUG( target == GL_TEXTURE_2D );
135   bool created = false;
136
137   if( mId == 0 )
138   {
139     if( CreateGlTexture() )
140     {
141       created = true;
142     }
143   }
144
145   // Bind the texture id
146   mContext.BindTextureForUnit(textureunit, mId );
147
148   return created;
149 }
150
151 void Texture::GlContextDestroyed()
152 {
153   // texture is gone
154   mId = 0;
155   // reset sampler state as well
156   mSamplerBitfield = 0;
157 }
158
159 void Texture::GlCleanup()
160 {
161   // delete the gl texture
162   if (mId != 0)
163   {
164     mContext.DeleteTextures(1,&mId);
165     mId = 0;
166   }
167 }
168
169 void Texture::MapUV(unsigned int numVerts,Vertex2D *verts, const PixelArea* pixelArea)
170 {
171   MapUV(numVerts, (float*)(&verts->mU), sizeof(Vertex2D)/sizeof(float), pixelArea);
172 }
173
174 void Texture::MapUV(unsigned int numVerts,Vertex3D *verts, const PixelArea* pixelArea)
175 {
176   MapUV(numVerts, (float*)(&verts->mU), sizeof(Vertex3D)/sizeof(float), pixelArea);
177 }
178
179 void Texture::MapUV(unsigned int numVerts, float* verts, unsigned int stride, const PixelArea* pixelArea)
180 {
181   UvRect uv;
182
183   GetTextureCoordinates(uv, pixelArea);
184
185   float uScale = fabsf(uv.u2 - uv.u0);
186   float vScale = fabsf(uv.v2 - uv.v0);
187
188   for (unsigned int i = 0; i < numVerts; ++i)
189   {
190     verts[0] = uv.u0 + verts[0] * uScale;
191     verts[1] = uv.v0 + verts[1] * vScale;
192     verts += stride;
193   }
194 }
195
196 unsigned int Texture::GetWidth() const
197 {
198   return mWidth;
199 }
200
201 unsigned int Texture::GetHeight() const
202 {
203   return mHeight;
204 }
205
206 Pixel::Format Texture::GetPixelFormat() const
207 {
208   return mPixelFormat;
209 }
210
211 void Texture::GetTextureCoordinates(UvRect& uv, const PixelArea* pixelArea)
212 {
213   if( pixelArea == NULL )
214   {
215      GetDefaultTextureCoordinates(uv);
216      return;
217   }
218
219   // pre-calulate the normalized values
220
221   const float uScale = 1.0f / float(mWidth);
222   const float vScale = 1.0f / float(mHeight);
223   const float x = uScale * float(pixelArea->x);
224   const float y = vScale * float(pixelArea->y);
225   const float width  = uScale * float(pixelArea->width);
226   const float height = vScale * float(pixelArea->height);
227
228
229   // bottom left
230   uv.u0 = x;
231   uv.v0 = y;
232
233   // top right
234   uv.u2 = x + width;
235   uv.v2 = y + height;
236
237 };
238
239 void Texture::GetDefaultTextureCoordinates(UvRect& uv) const
240 {
241   if ((mWidth == mImageWidth) && (mHeight == mImageHeight))
242   {
243     // set the uv's to display 0,0 to 1,1
244     uv.Reset();
245     return;
246   }
247
248   // the texture co-ordinates go from 0 to 1. But the image is smaller than the
249   // texture, so we need to adjust the uv values.
250   float uScale = float(mImageWidth)  / float(mWidth);
251   float vScale = float(mImageHeight) / float(mHeight);
252
253   // bottom left
254   uv.u0 = 0.0f;
255   uv.v0 = 0.0f;
256
257   // top right
258   uv.u2 = uScale;
259   uv.v2 = vScale;
260
261 }
262
263 void Texture::ApplyTextureParameter( TextureUnit unit, GLint filterType, FilterMode::Type currentFilterMode, FilterMode::Type newFilterMode, GLint daliDefault, GLint systemDefault )
264 {
265   GLint newFilterModeGL = FilterModeToGL( newFilterMode, daliDefault, systemDefault );
266   GLint currentFilterModeGL = FilterModeToGL( currentFilterMode, daliDefault, systemDefault );
267
268   if( newFilterModeGL != currentFilterModeGL )
269   {
270     mContext.ActiveTexture( unit );
271     mContext.TexParameteri( GL_TEXTURE_2D, filterType, newFilterModeGL );
272   }
273 }
274
275 void Texture::ApplySampler( TextureUnit unit, unsigned int samplerBitfield )
276 {
277   if( mSamplerBitfield != samplerBitfield && mId != 0 )
278   {
279     ApplyTextureParameter( unit,
280                            GL_TEXTURE_MIN_FILTER,
281                            ImageSampler::GetMinifyFilterMode( mSamplerBitfield ),
282                            ImageSampler::GetMinifyFilterMode( samplerBitfield ),
283                            DALI_MINIFY_DEFAULT,
284                            SYSTEM_MINIFY_DEFAULT );
285
286     ApplyTextureParameter( unit,
287                            GL_TEXTURE_MAG_FILTER,
288                            ImageSampler::GetMagnifyFilterMode( mSamplerBitfield ),
289                            ImageSampler::GetMagnifyFilterMode( samplerBitfield ),
290                            DALI_MAGNIFY_DEFAULT,
291                            SYSTEM_MAGNIFY_DEFAULT );
292
293     mSamplerBitfield = samplerBitfield;
294   }
295 }
296
297 } // namespace Internal
298
299 } // namespace Dali