First public contribution.
2 * Copyright (c) 2003 Nokia Corporation and/or its subsidiary(-ies).
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".
9 * Initial Contributors:
10 * Nokia Corporation - initial contribution.
14 * Description: Texture2D implementation
22 * \brief Texture2D implementation
25 #ifndef M3G_CORE_INCLUDE
26 # error included by m3g_core.c; do not compile separately.
30 * Uncomment this line to switch tracing on for this file's functions
32 /* #define M3G_LOCAL_TRACEF_ON */
34 #include "m3g_object.h"
36 #include "m3g_image.h"
38 #include "m3g_texture.h"
39 #include "m3g_animationtrack.h"
40 #include "m3g_transformable.h"
44 * \brief Texture object
48 Transformable transformable;
63 * Uncomment this line to switch tracing on for this file's functions
65 /* #define M3G_LOCAL_TRACEF_ON */
67 /*----------------------------------------------------------------------
69 *--------------------------------------------------------------------*/
73 * \brief Destroys this Texture object.
75 * \param obj Texture object
77 static void m3gDestroyTexture(Object *obj)
79 Texture *tex = (Texture *) obj;
80 M3G_VALIDATE_OBJECT(tex);
82 M3G_ASSIGN_REF(tex->image, NULL);
83 m3gDestroyTransformable(obj);
88 * \brief Disables all texturing units and texture coordinate arrays
90 static void m3gDisableTextures(void)
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);
103 * \brief Applies texture to OpenGL.
105 * \param texture Texture object
107 static void m3gBindTexture(Texture *texture)
112 M3G_VALIDATE_OBJECT(texture);
114 m3gBindTextureImage(texture->image,
115 texture->levelFilter,
116 texture->imageFilter);
118 /* setting up texturing mode */
121 M3Gfloat matrixValues[16];
122 m3gGetCompositeTransform((Transformable *) texture, &mtx);
123 m3gGetMatrixColumns(&mtx, matrixValues);
124 glMatrixMode(GL_TEXTURE);
125 glLoadMatrixf(matrixValues);
127 glMatrixMode(GL_MODELVIEW);
130 switch (texture->blendFunc) {
131 case M3G_FUNC_REPLACE:
143 case M3G_FUNC_MODULATE:
147 /* This should never happen */
151 glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, (GLfixed)mode);
153 m3gFloatColor(texture->blendColor, 1.f, colors);
154 glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, colors);
156 /* setting up wrapping */
157 if (texture->wrapS == M3G_WRAP_CLAMP) {
158 glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
161 glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
163 if (texture->wrapT == M3G_WRAP_CLAMP) {
164 glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
167 glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
175 * \brief Releases a bound texture from the current texture unit
178 static void m3gReleaseTexture(Texture *texture)
180 m3gReleaseTextureImage(texture->image);
183 #if defined(M3G_NGL_TEXTURE_API)
186 * \brief Make sure that mipmaps are allocated if needed
188 static M3Gbool m3gValidateTextureMipmapping(Texture *texture)
190 return (texture->levelFilter == M3G_FILTER_BASE_LEVEL
191 || texture->image->mipData);
197 * \brief Overloaded Object3D method.
199 * \param property animation property
200 * \retval M3G_TRUE property supported
201 * \retval M3G_FALSE property not supported
203 static M3Gbool m3gTextureIsCompatible(M3Gint property)
209 return m3gTransformableIsCompatible(property);
215 * \brief Overloaded Object3D method.
217 * \param self Texture object
218 * \param property animation property
219 * \param valueSize size of value array
220 * \param value value array
222 static void m3gTextureUpdateProperty(Object *self,
225 const M3Gfloat *value)
227 Texture *texture = (Texture *)self;
228 M3G_VALIDATE_OBJECT(texture);
229 M3G_ASSERT_PTR(value);
233 M3G_ASSERT(valueSize >= 3);
234 texture->blendColor =
236 ? m3gColor3f(value[0], value[1], value[2])
237 : m3gColor4f(value[0], value[1], value[2], value[3]));
240 m3gTransformableUpdateProperty(self, property, valueSize, value);
246 * \brief Overloaded Object3D method.
248 * \param self Texture object
249 * \param references array of reference objects
250 * \return number of references
252 static M3Gint m3gTextureDoGetReferences(Object *self, Object **references)
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;
266 * \brief Overloaded Object3D method.
268 static Object *m3gTextureFindID(Object *self, M3Gint userID)
270 Texture *texture = (Texture *)self;
271 Object *found = m3gObjectFindID(self, userID);
273 if (!found && texture->image != NULL) {
274 found = m3gFindID((Object*) texture->image, userID);
281 * \brief Overloaded Object3D method.
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
288 static M3Gbool m3gTextureDuplicate(const Object *originalObj,
293 Texture *original = (Texture *)originalObj;
295 M3G_ASSERT(*cloneObj == NULL); /* no derived classes */
297 /* Create the clone object */
299 clone = (Texture *)m3gCreateTexture(originalObj->interface,
304 *cloneObj = (Object *)clone;
306 /* Duplicate base class data */
308 if (!m3gTransformableDuplicate(originalObj, cloneObj, pairs, numPairs)) {
312 /* Duplicate our own data */
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;
326 * \brief Check texture dimensions.
328 * \retval M3G_TRUE dimensions valid
329 * \retval M3G_FALSE dimensions invalid
331 static M3Gbool m3gIsValidDimensions(M3Gint width, M3Gint height)
333 return ( m3gInRange(width, 1, M3G_MAX_TEXTURE_DIMENSION)
334 && m3gInRange(height, 1, M3G_MAX_TEXTURE_DIMENSION)
335 && m3gIsPowerOfTwo(width)
336 && m3gIsPowerOfTwo(height) );
339 /*----------------------------------------------------------------------
340 * Virtual function table
341 *--------------------------------------------------------------------*/
343 static const ObjectVFTable m3gvf_Texture = {
344 m3gObjectApplyAnimation,
345 m3gTextureIsCompatible,
346 m3gTextureUpdateProperty,
347 m3gTextureDoGetReferences,
354 /*----------------------------------------------------------------------
355 * Public API functions
356 *--------------------------------------------------------------------*/
359 * \brief Texture constructor, creates a texture with
363 * \param interface M3G interface
364 * \param hImage texture Image object
365 * \retval Texture new Texture object
366 * \retval NULL Texture creating failed
368 M3G_API M3GTexture m3gCreateTexture(M3GInterface interface,
371 Interface *m3g = (Interface *) interface;
372 Image* image = (Image *)hImage;
373 M3G_VALIDATE_INTERFACE(m3g);
377 m3gRaiseError(m3g, M3G_NULL_POINTER);
381 if (!m3gIsValidDimensions(image->width, image->height)) {
382 m3gRaiseError(m3g, M3G_INVALID_VALUE);
386 /* Allocate and initialize the object */
389 texture = m3gAllocZ(m3g, sizeof(Texture));
390 if (texture != NULL) {
391 m3gInitTransformable(&texture->transformable, m3g,
394 M3G_ASSIGN_REF(texture->image, image);
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;
404 return (M3GTexture)texture;
409 * \brief Set texture image.
411 * \param hTexture Texture object
412 * \param hImage Image object
414 M3G_API void m3gSetTextureImage(M3GTexture hTexture, M3GImage hImage)
416 Texture *texture = (Texture*)hTexture;
417 Image *image = (Image *)hImage;
418 M3G_VALIDATE_OBJECT(texture);
421 m3gRaiseError(M3G_INTERFACE(texture), M3G_NULL_POINTER);
425 if (!m3gIsValidDimensions(image->width, image->height)) {
426 m3gRaiseError(M3G_INTERFACE(texture), M3G_INVALID_VALUE);
430 M3G_ASSIGN_REF(texture->image, image);
434 * \brief Get texture image.
436 * \param hTexture Texture object
437 * \return Image object
439 M3G_API M3GImage m3gGetTextureImage(M3GTexture hTexture)
441 const Texture *texture = (const Texture *) hTexture;
442 M3G_VALIDATE_OBJECT(texture);
444 return (M3GImage)(texture->image);
448 * \brief Set texture filtering.
450 * \param hTexture Texture object
451 * \param levelFilter level filter type
452 * \param imageFilter image filter type
454 M3G_API void m3gSetFiltering(M3GTexture hTexture,
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);
467 texture->levelFilter = levelFilter;
468 texture->imageFilter = imageFilter;
472 * \brief Set texture S & T wrapping mode.
474 * \param hTexture Texture object
475 * \param wrapS S wrap mode
476 * \param wrapT T wrap mode
478 M3G_API void m3gSetWrapping(M3GTexture hTexture, M3Gint wrapS, M3Gint wrapT)
480 Texture *texture = (Texture*)hTexture;
481 if (wrapS != M3G_WRAP_CLAMP && wrapS != M3G_WRAP_REPEAT) {
482 m3gRaiseError(M3G_INTERFACE(texture), M3G_INVALID_VALUE);
485 if (wrapT != M3G_WRAP_CLAMP && wrapT != M3G_WRAP_REPEAT) {
486 m3gRaiseError(M3G_INTERFACE(texture), M3G_INVALID_VALUE);
489 texture->wrapS = wrapS;
490 texture->wrapT = wrapT;
494 * \brief Get texture S wrapping mode.
496 * \param hTexture Texture object
497 * \return S wrapping mode
499 M3G_API M3Gint m3gGetWrappingS(M3GTexture hTexture)
501 Texture *texture = (Texture*)hTexture;
502 return texture->wrapS;
506 * \brief Get texture T wrapping mode.
508 * \param hTexture Texture object
509 * \return T wrapping mode
511 M3G_API M3Gint m3gGetWrappingT(M3GTexture hTexture)
513 Texture *texture = (Texture*)hTexture;
514 return texture->wrapT;
518 * \brief Set texture blending function.
520 * \param hTexture Texture object
521 * \param func blending function
523 M3G_API void m3gTextureSetBlending(M3GTexture hTexture, M3Gint func)
525 Texture *texture = (Texture*)hTexture;
531 case M3G_FUNC_MODULATE:
532 case M3G_FUNC_REPLACE:
533 texture->blendFunc = func;
536 m3gRaiseError(M3G_INTERFACE(texture), M3G_INVALID_VALUE);
542 * \brief Get texture blending function.
544 * \param hTexture Texture object
545 * \return blending function
547 M3G_API M3Gint m3gTextureGetBlending(M3GTexture hTexture)
549 Texture *texture = (Texture*)hTexture;
550 return texture->blendFunc;
554 * \brief Set texture blend color as RGB.
556 * \param hTexture Texture object
557 * \param RGB blend color as RGB
559 M3G_API void m3gSetBlendColor(M3GTexture hTexture, M3Guint RGB)
561 Texture *texture = (Texture*)hTexture;
562 texture->blendColor = RGB & M3G_RGB_MASK;
566 * \brief Get texture blend color as RGB.
568 * \param hTexture Texture object
569 * \return blend color as RGB
571 M3G_API M3Guint m3gGetBlendColor(M3GTexture hTexture)
573 Texture *texture = (Texture*)hTexture;
574 return texture->blendColor;
578 * \brief Get texture filtering
580 * \param hTexture Texture object
581 * \param levelFilter pointer to store level filter
582 * \param imageFilter pointer to store image filter
584 M3G_API void m3gGetFiltering(M3GTexture hTexture, M3Gint *levelFilter, M3Gint *imageFilter)
586 Texture *texture = (Texture*)hTexture;
587 *levelFilter = texture->levelFilter;
588 *imageFilter = texture->imageFilter;
592 * Uncomment these lines' opening pair at the begining of the file
593 * if you want to switch tracing on for this file.
595 #ifdef M3G_LOCAL_TRACEF_ON
596 #undef M3G_LOCAL_TRACEF_ON