os/graphics/m3g/m3gcore11/src/m3g_texture.c
author sl
Tue, 10 Jun 2014 14:32:02 +0200
changeset 1 260cb5ec6c19
permissions -rw-r--r--
Update contrib.
     1 /*
     2 * Copyright (c) 2003 Nokia Corporation and/or its subsidiary(-ies).
     3 * All rights reserved.
     4 * This component and the accompanying materials are made available
     5 * under the terms of the License "Eclipse Public License v1.0"
     6 * which accompanies this distribution, and is available
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
     8 *
     9 * Initial Contributors:
    10 * Nokia Corporation - initial contribution.
    11 *
    12 * Contributors:
    13 *
    14 * Description: Texture2D implementation
    15 *
    16 */
    17 
    18 
    19 /*!
    20  * \internal
    21  * \file
    22  * \brief Texture2D implementation
    23  */
    24 
    25 #ifndef M3G_CORE_INCLUDE
    26 #   error included by m3g_core.c; do not compile separately.
    27 #endif
    28 
    29 /*
    30  * Uncomment this line to switch tracing on for this file's functions
    31  */
    32 /* #define M3G_LOCAL_TRACEF_ON */
    33 
    34 #include "m3g_object.h"
    35 
    36 #include "m3g_image.h"
    37 #include "m3g_math.h"
    38 #include "m3g_texture.h"
    39 #include "m3g_animationtrack.h"
    40 #include "m3g_transformable.h"
    41 
    42 /*!
    43  * \internal
    44  * \brief Texture object
    45  */
    46 struct M3GTextureImpl
    47 {
    48     Transformable transformable;
    49 
    50     Image *image;
    51 
    52     M3Guint blendColor;
    53     M3Genum blendFunc;
    54 
    55     M3Genum levelFilter;
    56     M3Genum imageFilter;
    57 
    58     M3Genum wrapS;
    59     M3Genum wrapT;
    60 };
    61 
    62 /*
    63  * Uncomment this line to switch tracing on for this file's functions
    64  */
    65 /* #define M3G_LOCAL_TRACEF_ON */
    66 
    67 /*----------------------------------------------------------------------
    68  * Internal functions
    69  *--------------------------------------------------------------------*/
    70 
    71 /*!
    72  * \internal
    73  * \brief Destroys this Texture object.
    74  *
    75  * \param obj Texture object
    76  */
    77 static void m3gDestroyTexture(Object *obj)
    78 {
    79     Texture *tex = (Texture *) obj;
    80     M3G_VALIDATE_OBJECT(tex);
    81 
    82     M3G_ASSIGN_REF(tex->image, NULL);
    83     m3gDestroyTransformable(obj);
    84 }
    85 
    86 /*!
    87  * \internal
    88  * \brief Disables all texturing units and texture coordinate arrays
    89  */
    90 static void m3gDisableTextures(void)
    91 {
    92     M3Gint i;
    93     for (i = 0; i < M3G_NUM_TEXTURE_UNITS; ++i) {
    94         glClientActiveTexture(GL_TEXTURE0 + i);
    95         glDisableClientState(GL_TEXTURE_COORD_ARRAY);
    96         glActiveTexture(GL_TEXTURE0 + i);
    97         glDisable(GL_TEXTURE_2D);
    98     }
    99 }
   100 
   101 /*!
   102  * \internal
   103  * \brief Applies texture to OpenGL.
   104  *
   105  * \param texture Texture object
   106  */
   107 static void m3gBindTexture(Texture *texture)
   108 {
   109     M3Gfloat colors[4];
   110     M3Gint mode;
   111 
   112     M3G_VALIDATE_OBJECT(texture);
   113     
   114     m3gBindTextureImage(texture->image,
   115                         texture->levelFilter,
   116                         texture->imageFilter); 
   117 
   118     /* setting up texturing mode */
   119     {
   120         M3GMatrix mtx;
   121         M3Gfloat matrixValues[16];
   122         m3gGetCompositeTransform((Transformable *) texture, &mtx);
   123         m3gGetMatrixColumns(&mtx, matrixValues);
   124         glMatrixMode(GL_TEXTURE);
   125         glLoadMatrixf(matrixValues);
   126     }
   127     glMatrixMode(GL_MODELVIEW);
   128 
   129     mode = GL_REPLACE;
   130     switch (texture->blendFunc) {
   131     case M3G_FUNC_REPLACE:
   132         mode = GL_REPLACE;
   133         break;
   134     case M3G_FUNC_ADD:
   135         mode = GL_ADD;
   136         break;
   137     case M3G_FUNC_BLEND:
   138         mode = GL_BLEND;
   139         break;
   140     case M3G_FUNC_DECAL:
   141         mode = GL_DECAL;
   142         break;
   143     case M3G_FUNC_MODULATE:
   144         mode = GL_MODULATE;
   145         break;
   146     default:
   147         /* This should never happen */
   148         M3G_ASSERT(0);
   149         break;
   150     }
   151     glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, (GLfixed)mode);
   152 
   153     m3gFloatColor(texture->blendColor, 1.f, colors);
   154     glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, colors);
   155 
   156     /* setting up wrapping */
   157     if (texture->wrapS  == M3G_WRAP_CLAMP) {
   158         glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
   159     }
   160     else {
   161         glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
   162     }
   163     if (texture->wrapT == M3G_WRAP_CLAMP) {
   164         glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
   165     }
   166     else {
   167         glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
   168     }
   169 
   170     M3G_ASSERT_GL;
   171 }
   172 
   173 /*!
   174  * \internal
   175  * \brief Releases a bound texture from the current texture unit
   176  *
   177  */
   178 static void m3gReleaseTexture(Texture *texture)
   179 {
   180     m3gReleaseTextureImage(texture->image);
   181 }
   182 
   183 #if defined(M3G_NGL_TEXTURE_API)
   184 /*!
   185  * \internal
   186  * \brief Make sure that mipmaps are allocated if needed
   187  */
   188 static M3Gbool m3gValidateTextureMipmapping(Texture *texture)
   189 {
   190     return (texture->levelFilter == M3G_FILTER_BASE_LEVEL
   191             || texture->image->mipData);
   192 }
   193 #endif
   194 
   195 /*!
   196  * \internal
   197  * \brief Overloaded Object3D method.
   198  *
   199  * \param property      animation property
   200  * \retval M3G_TRUE     property supported
   201  * \retval M3G_FALSE    property not supported
   202  */
   203 static M3Gbool m3gTextureIsCompatible(M3Gint property)
   204 {
   205     switch (property) {
   206     case M3G_ANIM_COLOR:
   207         return M3G_TRUE;
   208     default:
   209         return m3gTransformableIsCompatible(property);
   210     }
   211 }
   212 
   213 /*!
   214  * \internal
   215  * \brief Overloaded Object3D method.
   216  *
   217  * \param self          Texture object
   218  * \param property      animation property
   219  * \param valueSize     size of value array
   220  * \param value         value array
   221  */
   222 static void m3gTextureUpdateProperty(Object *self,
   223                                      M3Gint property,
   224                                      M3Gint valueSize,
   225                                      const M3Gfloat *value)
   226 {
   227     Texture *texture = (Texture *)self;
   228     M3G_VALIDATE_OBJECT(texture);
   229     M3G_ASSERT_PTR(value);
   230 
   231     switch (property) {
   232     case M3G_ANIM_COLOR:
   233         M3G_ASSERT(valueSize >= 3);
   234         texture->blendColor =
   235             (valueSize == 3
   236              ? m3gColor3f(value[0], value[1], value[2])
   237              : m3gColor4f(value[0], value[1], value[2], value[3]));
   238         break;
   239     default:
   240         m3gTransformableUpdateProperty(self, property, valueSize, value);
   241     }
   242 }
   243 
   244 /*!
   245  * \internal
   246  * \brief Overloaded Object3D method.
   247  *
   248  * \param self Texture object
   249  * \param references array of reference objects
   250  * \return number of references
   251  */
   252 static M3Gint m3gTextureDoGetReferences(Object *self, Object **references)
   253 {
   254     Texture *texture = (Texture *)self;
   255     M3Gint num = m3gObjectDoGetReferences(self, references);
   256     if (texture->image != NULL) {
   257         if (references != NULL)
   258             references[num] = (Object *)texture->image;
   259         num++;
   260     }
   261     return num;
   262 }
   263 
   264 /*!
   265  * \internal
   266  * \brief Overloaded Object3D method.
   267  */
   268 static Object *m3gTextureFindID(Object *self, M3Gint userID)
   269 {
   270     Texture *texture = (Texture *)self;
   271     Object *found = m3gObjectFindID(self, userID);
   272     
   273     if (!found && texture->image != NULL) {
   274         found = m3gFindID((Object*) texture->image, userID);
   275     }
   276     return found;
   277 }
   278 
   279 /*!
   280  * \internal
   281  * \brief Overloaded Object3D method.
   282  *
   283  * \param originalObj original Texture object
   284  * \param cloneObj pointer to cloned Texture object
   285  * \param pairs array for all object-duplicate pairs
   286  * \param numPairs number of pairs
   287  */
   288 static M3Gbool m3gTextureDuplicate(const Object *originalObj,
   289                                    Object **cloneObj,
   290                                    Object **pairs,
   291                                    M3Gint *numPairs)
   292 {
   293     Texture *original = (Texture *)originalObj;
   294     Texture *clone;
   295     M3G_ASSERT(*cloneObj == NULL); /* no derived classes */
   296 
   297     /* Create the clone object */
   298     
   299     clone = (Texture *)m3gCreateTexture(originalObj->interface,
   300                                         original->image);
   301     if (!clone) {
   302         return M3G_FALSE;
   303     }
   304     *cloneObj = (Object *)clone;
   305 
   306     /* Duplicate base class data */
   307     
   308     if (!m3gTransformableDuplicate(originalObj, cloneObj, pairs, numPairs)) {
   309         return M3G_FALSE;
   310     }
   311 
   312     /* Duplicate our own data */
   313     
   314     clone->blendColor = original->blendColor;
   315     clone->blendFunc = original->blendFunc;
   316     clone->levelFilter = original->levelFilter;
   317     clone->imageFilter = original->imageFilter;
   318     clone->wrapS = original->wrapS;
   319     clone->wrapT = original->wrapT;
   320 
   321     return M3G_TRUE;
   322 }
   323 
   324 /*!
   325  * \internal
   326  * \brief Check texture dimensions.
   327  *
   328  * \retval M3G_TRUE dimensions valid
   329  * \retval M3G_FALSE dimensions invalid
   330  */
   331 static M3Gbool m3gIsValidDimensions(M3Gint width, M3Gint height)
   332 {
   333     return (       m3gInRange(width,  1, M3G_MAX_TEXTURE_DIMENSION)
   334                 && m3gInRange(height, 1, M3G_MAX_TEXTURE_DIMENSION)
   335                 && m3gIsPowerOfTwo(width)
   336                 && m3gIsPowerOfTwo(height) );
   337 }
   338 
   339 /*----------------------------------------------------------------------
   340  * Virtual function table
   341  *--------------------------------------------------------------------*/
   342 
   343 static const ObjectVFTable m3gvf_Texture = {
   344     m3gObjectApplyAnimation,
   345     m3gTextureIsCompatible,
   346     m3gTextureUpdateProperty,
   347     m3gTextureDoGetReferences,
   348     m3gTextureFindID,
   349     m3gTextureDuplicate,
   350     m3gDestroyTexture
   351 };
   352 
   353 
   354 /*----------------------------------------------------------------------
   355  * Public API functions
   356  *--------------------------------------------------------------------*/
   357 
   358 /*!
   359  * \brief Texture constructor, creates a texture with
   360  * default values.
   361  *
   362  *
   363  * \param interface             M3G interface
   364  * \param hImage                texture Image object
   365  * \retval Texture new Texture object
   366  * \retval NULL Texture creating failed
   367  */
   368 M3G_API M3GTexture m3gCreateTexture(M3GInterface interface,
   369                                     M3GImage hImage)
   370 {
   371     Interface *m3g = (Interface *) interface;
   372     Image* image = (Image *)hImage;
   373     M3G_VALIDATE_INTERFACE(m3g);
   374 
   375     /* Check inputs */
   376     if (image == NULL) {
   377         m3gRaiseError(m3g, M3G_NULL_POINTER);
   378         return NULL;
   379     }
   380 
   381     if (!m3gIsValidDimensions(image->width, image->height)) {
   382         m3gRaiseError(m3g, M3G_INVALID_VALUE);
   383         return NULL;
   384     }
   385 
   386     /* Allocate and initialize the object */
   387     {
   388         Texture *texture;
   389         texture = m3gAllocZ(m3g, sizeof(Texture));
   390         if (texture != NULL) {
   391             m3gInitTransformable(&texture->transformable, m3g,
   392                                  M3G_CLASS_TEXTURE);
   393 
   394             M3G_ASSIGN_REF(texture->image, image);
   395     
   396             texture->blendColor = 0x00000000;   /* Black */
   397             texture->blendFunc = M3G_FUNC_MODULATE;
   398             texture->levelFilter = M3G_FILTER_BASE_LEVEL;
   399             texture->imageFilter = M3G_FILTER_NEAREST;
   400             texture->wrapS = M3G_WRAP_REPEAT;
   401             texture->wrapT = M3G_WRAP_REPEAT;
   402         }
   403 
   404         return (M3GTexture)texture;
   405     }
   406 }
   407 
   408 /*!
   409  * \brief Set texture image.
   410  *
   411  * \param hTexture  Texture object
   412  * \param hImage    Image object
   413  */
   414 M3G_API void m3gSetTextureImage(M3GTexture hTexture, M3GImage hImage)
   415 {
   416     Texture *texture = (Texture*)hTexture;
   417     Image *image = (Image *)hImage;
   418     M3G_VALIDATE_OBJECT(texture);
   419 
   420     if (image == NULL) {
   421         m3gRaiseError(M3G_INTERFACE(texture), M3G_NULL_POINTER);
   422         return;
   423     }
   424 
   425     if (!m3gIsValidDimensions(image->width, image->height)) {
   426         m3gRaiseError(M3G_INTERFACE(texture), M3G_INVALID_VALUE);
   427         return;
   428     }
   429 
   430     M3G_ASSIGN_REF(texture->image, image);
   431 }
   432 
   433 /*!
   434  * \brief Get texture image.
   435  *
   436  * \param hTexture  Texture object
   437  * \return          Image object
   438  */
   439 M3G_API M3GImage m3gGetTextureImage(M3GTexture hTexture)
   440 {
   441     const Texture *texture = (const Texture *) hTexture;
   442     M3G_VALIDATE_OBJECT(texture);
   443 
   444     return (M3GImage)(texture->image);
   445 }
   446 
   447 /*!
   448  * \brief Set texture filtering.
   449  *
   450  * \param hTexture      Texture object
   451  * \param levelFilter   level filter type
   452  * \param imageFilter   image filter type
   453  */
   454 M3G_API void m3gSetFiltering(M3GTexture hTexture,
   455                              M3Gint levelFilter,
   456                              M3Gint imageFilter)
   457 {
   458     Texture *texture = (Texture*)hTexture;
   459     if ((levelFilter != M3G_FILTER_LINEAR &&
   460          levelFilter != M3G_FILTER_NEAREST &&
   461          levelFilter != M3G_FILTER_BASE_LEVEL)
   462         || (imageFilter != M3G_FILTER_LINEAR &&
   463             imageFilter != M3G_FILTER_NEAREST)) {
   464         m3gRaiseError(M3G_INTERFACE(texture), M3G_INVALID_VALUE);
   465         return;
   466     }
   467     texture->levelFilter = levelFilter;
   468     texture->imageFilter = imageFilter;
   469 }
   470 
   471 /*!
   472  * \brief Set texture S & T wrapping mode.
   473  *
   474  * \param hTexture  Texture object
   475  * \param wrapS     S wrap mode
   476  * \param wrapT     T wrap mode
   477  */
   478 M3G_API void m3gSetWrapping(M3GTexture hTexture, M3Gint wrapS, M3Gint wrapT)
   479 {
   480     Texture *texture = (Texture*)hTexture;
   481     if (wrapS != M3G_WRAP_CLAMP && wrapS != M3G_WRAP_REPEAT) {
   482         m3gRaiseError(M3G_INTERFACE(texture), M3G_INVALID_VALUE);
   483         return;
   484     }
   485     if (wrapT != M3G_WRAP_CLAMP && wrapT != M3G_WRAP_REPEAT) {
   486         m3gRaiseError(M3G_INTERFACE(texture), M3G_INVALID_VALUE);
   487         return;
   488     }
   489     texture->wrapS = wrapS;
   490     texture->wrapT = wrapT;
   491 }
   492 
   493 /*!
   494  * \brief Get texture S wrapping mode.
   495  *
   496  * \param hTexture  Texture object
   497  * \return S wrapping mode
   498  */
   499 M3G_API M3Gint m3gGetWrappingS(M3GTexture hTexture)
   500 {
   501     Texture *texture = (Texture*)hTexture;
   502     return texture->wrapS;
   503 }
   504 
   505 /*!
   506  * \brief Get texture T wrapping mode.
   507  *
   508  * \param hTexture  Texture object
   509  * \return T wrapping mode
   510  */
   511 M3G_API M3Gint m3gGetWrappingT(M3GTexture hTexture)
   512 {
   513     Texture *texture = (Texture*)hTexture;
   514     return texture->wrapT;
   515 }
   516 
   517 /*!
   518  * \brief Set texture blending function.
   519  *
   520  * \param hTexture  Texture object
   521  * \param func      blending function
   522  */
   523 M3G_API void m3gTextureSetBlending(M3GTexture hTexture, M3Gint func)
   524 {
   525     Texture *texture = (Texture*)hTexture;
   526 
   527     switch (func) {
   528     case M3G_FUNC_ADD:
   529     case M3G_FUNC_BLEND:
   530     case M3G_FUNC_DECAL:
   531     case M3G_FUNC_MODULATE:
   532     case M3G_FUNC_REPLACE:
   533         texture->blendFunc = func;
   534         break;
   535     default:
   536         m3gRaiseError(M3G_INTERFACE(texture), M3G_INVALID_VALUE);
   537         break;
   538     }
   539 }
   540 
   541 /*!
   542  * \brief Get texture blending function.
   543  *
   544  * \param hTexture  Texture object
   545  * \return          blending function
   546  */
   547 M3G_API M3Gint m3gTextureGetBlending(M3GTexture hTexture)
   548 {
   549     Texture *texture = (Texture*)hTexture;
   550     return texture->blendFunc;
   551 }
   552 
   553 /*!
   554  * \brief Set texture blend color as RGB.
   555  *
   556  * \param hTexture  Texture object
   557  * \param RGB       blend color as RGB
   558  */
   559 M3G_API void m3gSetBlendColor(M3GTexture hTexture, M3Guint RGB)
   560 {
   561     Texture *texture = (Texture*)hTexture;
   562     texture->blendColor = RGB & M3G_RGB_MASK;
   563 }
   564 
   565 /*!
   566  * \brief Get texture blend color as RGB.
   567  *
   568  * \param hTexture  Texture object
   569  * \return          blend color as RGB
   570  */
   571 M3G_API M3Guint m3gGetBlendColor(M3GTexture hTexture)
   572 {
   573     Texture *texture = (Texture*)hTexture;
   574     return texture->blendColor;
   575 }
   576 
   577 /*!
   578  * \brief Get texture filtering
   579  *
   580  * \param hTexture      Texture object
   581  * \param levelFilter   pointer to store level filter
   582  * \param imageFilter   pointer to store image filter
   583  */
   584 M3G_API void m3gGetFiltering(M3GTexture hTexture, M3Gint *levelFilter, M3Gint *imageFilter)
   585 {
   586     Texture *texture = (Texture*)hTexture;
   587     *levelFilter = texture->levelFilter;
   588     *imageFilter = texture->imageFilter;
   589 }
   590 
   591 /*
   592  * Uncomment these lines' opening pair at the begining of the file
   593  * if you want to switch tracing on for this file.
   594  */
   595 #ifdef M3G_LOCAL_TRACEF_ON
   596 #undef M3G_LOCAL_TRACEF_ON
   597 #endif
   598