1 /*
2 * Copyright (C) 1997-2005, R3vis Corporation.
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
13 *
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
17 * USA, or visit http://www.gnu.org/copyleft/lgpl.html.
18 *
19 * Original Contributor:
20 * Wes Bethel, R3vis Corporation, Marin County, California
21 * Additional Contributor(s):
22 *
23 * The OpenRM project is located at http://openrm.sourceforge.net/.
24 */
25 /*
26 * $Id: rmtxture.c,v 1.13 2005/06/06 02:04:29 wes Exp $
27 * Version: $Name: OpenRM-1-6-0-2-RC2 $
28 * $Revision: 1.13 $
29 * $Log: rmtxture.c,v $
30 * Revision 1.13 2005/06/06 02:04:29 wes
31 * Lots of small additions to clean up compiler warnings.
32 *
33 * Revision 1.12 2005/05/07 15:40:42 wes
34 * Remove error message indicating 1D texture downloads not tested.
35 *
36 * Revision 1.11 2005/05/06 16:33:49 wes
37 * Update texture state/env manipulation for 1D textures. Update
38 * documentation to reflect that 1D textures are supported.
39 *
40 * Revision 1.10 2005/02/27 19:34:04 wes
41 * Added support for application supplied texture object IDs and display lists.
42 *
43 * Revision 1.9 2005/02/19 16:43:48 wes
44 * Distro sync and consolidation.
45 * Remove dead and test code.
46 *
47 * Revision 1.8 2005/01/23 17:08:25 wes
48 * Copyright updated to 2005.
49 * Updates to support access and use of extensions; multitexturing on all
50 * platforms, use of 3d texture extension to realize implementation of
51 * volume rendering and related functions on Windows platforms.
52 *
53 * Revision 1.7 2004/01/16 16:49:13 wes
54 * Updated copyright line for 2004.
55 *
56 * Revision 1.6 2003/11/22 00:53:41 wes
57 * Changes to support RMtextures being shared when assigned as scene parameters
58 * to properly implement instancing.
59 *
60 * Revision 1.5 2003/06/14 03:17:20 wes
61 * Minor documentation tweaks.
62 *
63 * Revision 1.4 2003/03/16 21:56:16 wes
64 * Documentation updates.
65 *
66 * Revision 1.3 2003/02/14 00:19:25 wes
67 * No significant changes.
68 *
69 * Revision 1.2 2003/02/02 02:07:16 wes
70 * Updated copyright to 2003.
71 *
72 * Revision 1.1.1.1 2003/01/28 02:15:23 wes
73 * Manual rebuild of rm150 repository.
74 *
75 * Revision 1.16 2003/01/27 05:04:42 wes
76 * Changes to RMpipe API and initialization sequence to unify GLX, WGL and CR
77 * platforms w/o too much disruption to existing apps.
78 *
79 * Revision 1.15 2003/01/20 05:39:49 wes
80 * Rewrote texture state handling code.
81 *
82 * Revision 1.14 2003/01/16 22:21:17 wes
83 * Updated all source files to reflect new organization of header files:
84 * all header files formerly located in include/rmaux, include/rmi, include/rmv
85 * are now located in include/rm.
86 *
87 * Revision 1.13 2003/01/12 23:50:06 wes
88 * Minor adjustments to texturing environment controls to fix problems with
89 * the texture environment not being set correctly.
90 *
91 * Revision 1.12 2002/11/14 15:34:51 wes
92 * Minor editing for beautification.
93 *
94 * Revision 1.11 2002/09/17 14:18:30 wes
95 * Conditional code added to rmTextureSetImages() that will do a more
96 * conservative job of deleting old mipmaps when new images are
97 * assigned to an RMtexture.
98 *
99 * Revision 1.10 2002/04/30 19:36:03 wes
100 * Added support for non-byte texture data for 3D textures. All RM
101 * image formats are now supported for 3D textures.
102 *
103 * Revision 1.9 2001/06/03 20:50:48 wes
104 * Removed dead code.
105 *
106 * Revision 1.8 2001/03/31 17:12:39 wes
107 * v1.4.0-alpha-2 checkin.
108 *
109 * Revision 1.7 2000/12/05 03:04:53 wes
110 * Cosmetic changes.
111 *
112 * Revision 1.6 2000/12/04 00:42:35 wes
113 * Minor tweaks to eliminate compile warnings.
114 *
115 * Revision 1.5 2000/12/03 22:35:27 wes
116 * Mods for thread safety.
117 *
118 * Revision 1.4 2000/08/22 16:19:36 wes
119 * Moved code that turns off texturing to "the right place" after
120 * textures have been downloaded.
121 *
122 * Revision 1.3 2000/05/17 14:19:19 wes
123 * Removed #ifdef MESA from around the glIsTexture call - this crash
124 * bug was fixed in the nVidia driver released on 1 May 2000.
125 *
126 * Revision 1.2 2000/04/20 16:29:47 wes
127 * Documentation additions/enhancements, some code rearragement.
128 *
129 * Revision 1.1.1.1 2000/02/28 21:29:40 wes
130 * OpenRM 1.2 Checkin
131 *
132 * Revision 1.1.1.1 2000/02/28 17:18:48 wes
133 * Initial entry - pre-RM120 release, source base for OpenRM 1.2.
134 *
135 */
136
137
138 #include <rm/rm.h>
139 #include "rmprivat.h"
140
141 /*
142 * ----------------------------------------------------
143 * @Name rmTextureNew
144 @pstart
145 RMtexture * rmTextureNew (int ntdims)
146 @pend
147
148 @astart
149 int ntdims - an integer value specifying whether the new texture
150 object will be a 1D, 2D or 3D texture. The value for this parameter
151 must be one of 1, 2 or 3.
152 (input).
153 @aend
154
155 @dstart
156
157 Creates a new RMtexture object, returning a handle to the caller upon
158 success, or NULL upon failure.
159
160 Texture mapping in RM is accomplished by assigning an RMtexture
161 object to an RMnode as a scene parameter (see rmNodeSetSceneTexture).
162 Primitives that have texture coordinates (assigned with one of
163 rmPrimitiveSetTexcoord1D, rmPrimitiveSetTexcoord2D, or
164 rmPrimitiveSetTexcoord3D) that are located within any descendent
165 nodes, including the node containing the RMtexture object, that has
166 an RMprimitive with texture coordinates, will be rendered with
167 texture mapping active. The presence of the RMtexture object causes
168 texture mapping to become active, and texture coordinates cause
169 texture mapping to occur once active.
170
171 The RMtexture object is a container for both texture images
172 (rmTextureSetImages) and texturing environment, so it encompasses
173 both the OpenGL texture object as well as the OpenGL texturing
174 environment. The texturing environment consists of wrap mode
175 (rmTextureSetWrapMode), any texture filtering that occurs when
176 textures get small or large (rmTextureSetFilterMode), selection of
177 one of several environmental modes that control how the texture color
178 is blended with the pixel fragment color (rmTextureSetEnv),
179 manipulation over how the texture is physically represented in the
180 OpenGL pipeline (rmTextureSetGLTexelFormat).
181
182 Upon creation, rmTextureNew sets the following defaults all texture objects:
183
184 1. Texturing environment (blending) set to GL_MODULATE
185 (rmTextureSetEnv).
186
187 2. Wrap mode is set to GL_CLAMP (rmTextureSetWrapMode).
188
189 4. Texel storage format is GL_RGBA. Can be overridden by a subsequent
190 call to rmTextureGLSetTexelFormat().
191
192 For the texture filtering mode, 3D textures are assigned GL_NEAREST for
193 maximum speed, while 1D and 2D textures are assigned the value of
194 GL_LINEAR for best quality.
195
196 Before assigning an RMtexture object to an RMnode as a scene
197 parameter with rmNodeSetSceneTexture, the application must populate
198 the RMtexture object with RMimage object(s) that contain the texture
199 data.
200
201 @dend
202 * ----------------------------------------------------
203 */
204 RMtexture *
rmTextureNew(int ntdims)205 rmTextureNew (int ntdims)
206 {
207 int i;
208 int save;
209
210 RMtexture *t = private_rmTextureNew();
211 save = t->compListIndx;
212 memset(t,0,sizeof(RMtexture));
213 t->compListIndx = save;
214
215 /*
216 * initialize the struct (formerly done with bzero).
217 */
218 for (i=0;i<RM_MAX_MIPMAPS;i++)
219 t->images[i] = NULL;
220
221 t->nmipmaps = 0;
222
223 t->blendColor = NULL;
224
225 /* OpenGL texel format is initially left unspecified. the default
226 * behavior will be to ask for GL_RGBA as the OpenGL texel format.
227 * the default can be overridden by the application by calling
228 * rmTextureGLSetTexelFormat().
229 */
230 rmTextureSetGLTexelFormat(t, GL_RGBA);
231
232 /*
233 * 11/21/03 - initialize the cache ID and data keys to a known value
234 */
235 t->cacheKeyID = RM_CACHEKEY_UNINITIALIZED_VALUE;
236 t->cacheKeyData = RM_CACHEKEY_UNINITIALIZED_VALUE;
237
238 /*
239 * 11/21/03 - initialize the reference count to 0.
240 */
241 private_rmTextureSetRefCount(t, 0);
242
243 /* now fill in caller-supplied info. */
244
245 t->dims = ntdims;
246
247 /* set the default filtering modes */
248 switch (ntdims)
249 {
250 case 3: /* 3D textures: use GL_NEAREST for speed */
251 rmTextureSetFilterMode(t, GL_NEAREST, GL_NEAREST);
252 break;
253
254 default:
255 /*
256 * for all non 3D textures, use GL_LINEAR and pals for best images.
257 * apps that use mipmaps will probably want to use
258 * GL_LINEAR_MIPMAP_LINEAR for better images.
259 */
260 rmTextureSetFilterMode(t, GL_LINEAR, GL_LINEAR);
261 break;
262 }
263
264 /* set the default wrap mode */
265 rmTextureSetWrapMode(t, GL_CLAMP);
266
267 /* set the default texture environment mode - it determines how texels
268 are combined with existing fragments*/
269 rmTextureSetEnv(t, GL_MODULATE, NULL);
270
271 return(t);
272 }
273
274
275 /*
276 * ----------------------------------------------------
277 * @Name rmTextureDelete
278 @pstart
279 RMenum rmTextureDelete (RMtexture *toDelete,
280 RMenum deleteImagesBool)
281 @pend
282
283 @astart
284 RMtexture *toDelete - a handle to an RMtexture object to delete.
285
286 RMenum deleteImagesBool - an RMenum value, either RM_TRUE or
287 RM_FALSE, that indicates whether or not to delete the underlying
288 RMimage data.
289 @aend
290
291 @dstart
292
293 Use this routine to free an RMtexture object when no longer
294 needed. At this time (Jan 2000), it is the applications
295 responsibility to dictate whether or not the underlying RMimage
296 texture data will be deleted. This control may become obsolete with
297 the addition of reference counting at the RMimage level, but this
298 feature is not implemented at this time.
299
300 When the application specifies RM_TRUE for "deleteImagesBool", the
301 underlying RMimage data will be deleted (using rmImageDelete). If the
302 underlying RMimage's share management of the pixel data with the
303 application (specified using RM_DONT_COPY_DATA with
304 rmImageSetPixelData), the application-supplied callback will be
305 invoked at this time to release the image pixel data.
306
307 This routine also deletes the underlying OpenGL texture object.
308
309 @dend
310 * ----------------------------------------------------
311 */
312 RMenum
rmTextureDelete(RMtexture * t,RMenum delete_images_bool)313 rmTextureDelete (RMtexture *t,
314 RMenum delete_images_bool)
315 {
316 if (RM_ASSERT(t, "rmTextureDelete() error: the input texture object is NULL. \n") == RM_WHACKED)
317 return(RM_WHACKED);
318
319 /* 11/21/03 - don't permit texture deletion if the RMtexture is used
320 as a shared texture scene parameter at some RMnode. */
321 if (t->refCount > 0)
322 {
323 #if 0
324 rmWarning("rmTextureDelete() warning: cannot delete the texture because its reference count is > 0. That means that it is being used as a scene parameter by some RMnode.");
325 #endif
326 return RM_WHACKED;
327 }
328
329 /* free the texture images? */
330 if (delete_images_bool == RM_TRUE)
331 {
332 int i;
333 RMimage *ri;
334
335 for (i = 0; i < private_rmTextureGetNMipMaps(t); i++)
336 {
337 ri = t->images[i];
338 rmImageDelete(ri);
339 }
340 }
341
342 #if 0
343 /* we need an RMpipe to properly delete an OpenGL texture.
344 at this point (10/2000) we have no way to explicitly remove
345 OpenGL textures once they have been created, except via
346 rmFinish(). */
347
348 /* release opengl resources - this is deprecated code */
349 if (glIsTexture(t->tname) == GL_TRUE)
350 glDeleteTextures(1, (GLuint *)&(t->tname));
351 #endif
352
353 /* finally, delete the texture itself */
354 private_rmTextureDelete(t);
355
356 return(RM_CHILL);
357 }
358
359
360 /*
361 * ----------------------------------------------------
362 * @Name rmTextureSetImages
363 @pstart
364 RMenum rmTextureSetImages (RMtexture *toModify,
365 RMimage **imageArray,
366 int nimages,
367 int borderWidth)
368 @pend
369
370
371 @astart
372 RMtexture *toModify - a handle to the RMtexture object to which image
373 texture data will be assigned (modified).
374
375 RMimage **imageArray - a handle to an array of RMimage objects that
376 will be assigned to the RMtexture object as texture data. This
377 list will not be modified by this routine.
378
379 int nimages - an integer value indicating both the length or size of
380 the imageArray parameter.
381
382 int borderWidth - an integer value specifying the texture border
383 width. May be either 1 or 0.
384 @aend
385
386 @dstart
387
388 Use this routine to assign texture image data to an RMtexture object.
389 Returns RM_CHILL upon success, or RM_WHACKED upon failure.
390
391 In OpenGL, all images that are used as textures MUST BE and even
392 power of 2 in size, although image width and height need not be
393 equal. Thus, one may have image data which is 512 pixels wide by 64
394 pixels high. Use rmImageResize or gluScaleImage to resize an image
395 if needed to honor the power-of-two size restriction.
396
397 One or more images may be assigned to a single texture object. The
398 practice of assigning multiple images to a single texture object is
399 called "Mip-mapping." The basic idea behind mip-mapping is that when
400 a single texel (pixel from the texture data) covers very few screen
401 pixels, one can use a low-resolution version of the texture data
402 since the high-frequency texture components are lost by the
403 rasterization process. When a single texel covers many screen pixels,
404 a high-resolution version of the texture data is used in order to
405 preserve, as much as possible, the high-frequency component of the
406 texture data.
407
408 While mip-map construction is both a science and an art, for the most
409 part, applications may simply use scaled down versions of a
410 high-resolution texture for each mipmap level.
411
412 When mipmapping is used (nImages > 1), the "proper" number of mipmaps
413 to create and use is 1+log2(largest dimension size of source
414 texture). So, if the original texture is 256x64, a total of 8 images
415 are needed to make a complete mipmap. The eight images will be sized:
416 256x64 (the original image), 128x32, 64x16, 32x8, 16x4, 8x2, 4x1,
417 2x1, 1x1 for a total of 9 images (log2(256)+1). In other words, you
418 must specify all images that are sized from the original image down
419 to a 1x1 representation.
420
421 Inside this routine, each image of the RMimage array is COPIED into
422 the texture object using the routine rmImageDup. A fine point to be
423 aware of is the fact that rmImageDup does not necessarily duplicate
424 the underlying pixel data, so duplication of the imageArray does not
425 necessarily result in a significant use of memory. Whether or not the
426 image pixel data is copied is a function of whether or not the pixel
427 data is assigned to the RMimage using RM_COPY_DATA or
428 RM_DONT_COPY_DATA.
429
430 The border width parameter (either 0 or 1) indicates whether or not
431 the "edge" pixels of the texture image data are to be treated as
432 border pixels. Above, we mentioned that OpenGL textures must be an
433 even power of two in size. More precisely, for a two-dimensional
434 texture, the size of the input image data is (2^n + 2b, 2^m + 2b)
435 where n,m are positive integers, and "b" is the borderWidth
436 parameter. The treatment of border pixels is more fully described in
437 the OpenGL Red Book.
438
439 Note that the borderWidth parameter applies to ALL images in a set of
440 Mipmaps, not just the first image.
441
442 @dend
443 * ----------------------------------------------------
444 */
445 RMenum
rmTextureSetImages(RMtexture * t,RMimage ** imagearray,int nimages,int borderWidth)446 rmTextureSetImages (RMtexture *t,
447 RMimage **imagearray,
448 int nimages,
449 int borderWidth)
450 {
451 int i;
452
453 if (RM_ASSERT(t, "rmTextureSetImages() error: the input texture is NULL.") == RM_WHACKED)
454 return(RM_WHACKED);
455
456 /* first, free up any existing RMimage objects */
457 for (i = 0; i < private_rmTextureGetNMipMaps(t); i++)
458 {
459 RMimage *img;
460 img = t->images[i];
461 if (img != NULL)
462 rmImageDelete(img);
463 t->images[i] = NULL;
464 }
465
466 private_rmTextureSetNMipMaps(t, nimages);
467
468 t->borderWidth = borderWidth;
469
470 for (i = 0; i < private_rmTextureGetNMipMaps(t); i++)
471 {
472 RMimage *img;
473 img = rmImageDup(imagearray[i]);
474 t->images[i] = img;
475 }
476
477 private_rmTextureSetDataCacheKey(t);
478
479 return(RM_CHILL);
480 }
481
482
483 /*
484 * ----------------------------------------------------
485 * @Name rmTextureGetImages
486 @pstart
487 RMenum rmTextureGetImages (RMtexture *toQuery,
488 RMimage **imageArray,
489 int *nimages,
490 int *borderWidth)
491 @pend
492
493 @astart
494 RMtexture *toQuery - a handle to the RMtexture object to which image
495 texture data will be assigned (input).
496
497 RMimage **imageArray - a handle to an array of RMimage objects that
498 will be assigned to the RMtexture object as texture data. This
499 list will not be modified by this routine.
500
501 int *nimages, *borderWidth - handles to an integers (results).
502 @aend
503
504 @dstart
505
506 This routine is currently only a stub.
507
508 @dend
509 Use this routine to read back the textures assigned to an RMtexture
510 object.
511
512 Upon successful completion, RM_CHILL is returned and the number of
513 mipmaps, border width, and copies of the actual texture images are
514 returned to the caller. Otherwise, RM_WHACKED is returned.
515
516 * ----------------------------------------------------
517 */
518 RMenum
rmTextureGetImages(const RMtexture * t,RMimage *** imagearray,int * nimages,int * borderWidth)519 rmTextureGetImages (const RMtexture *t,
520 RMimage ***imagearray,
521 int *nimages,
522 int *borderWidth)
523 {
524 /* stub - implement! */
525 rmWarning("rmTextureGetImages is not yet implemented. \n");
526
527 /* foil compiler warning */
528 t = NULL;
529 imagearray = NULL;
530 nimages = borderWidth = NULL;
531
532 return(RM_CHILL);
533 }
534
535
536 /*
537 * ----------------------------------------------------
538 * @Name rmTextureSetFilterMode
539 @pstart
540 RMenum rmTextureSetFilterMode (RMtexture *toModify,
541 GLenum minMode,
542 GLenum magMode)
543 @pend
544
545 @astart
546 RMtexture *toModify - handle to an RMtexture object (modified).
547
548 GLenum minMode - a GLenum value specifying a texture minification
549 filter. May be one of GL_NEAREST, GL_LINEAR,
550 GL_NEAREST_MIPMAP_NEAREST, GL_NEAREST_MIPMAP_LINEAR,
551 GL_LINEAR_MIPMAP_NEAREST, GL_LINEAR_MIPMAP_LINEAR.
552
553 GLenum magMode - a GLenum value specifying a texture magnification
554 filter. May be one of GL_NEAREST or GL_LINEAR.
555 @aend
556
557 @dstart
558
559 Use this routine to set the texture filtering mode at of an RMtexture
560 object. Returns RM_CHILL upon success, or RM_WHACKED upon
561 failure. Note that the filter does not take effect until the texture
562 object has been placed into the scene graph using either
563 rmNodeSetSceneTexture or rmNodeUpdateSceneTexture.
564
565 When texels project to screen pixels, they rarely cover an integral
566 number of pixels. The texture filtering mode is used to control how
567 texels are interpolated to screen pixels. When a screen pixel covers
568 a very small portion of the texture, the texture is said to be
569 magnified. Conversely, when the screen pixel covers multiple texels,
570 the texture is said to be minified.
571
572 By default, the RMtexture object uses the minification and
573 magnification filters of GL_NEAREST, GL_NEAREST, respectively. These
574 filters favor performance over quality. The minification filter
575 modes, GL_NEAREST, GL_LINEAR, ... , GL_LINEAR_MIPMAP_LINEAR represent
576 increasing levels of interpolation quality, but at increasing
577 performance cost. Only two magnification filters, GL_NEAREST and
578 GL_LINEAR, are available inside OpenGL. Please see the OpenGL red
579 book for more information about texture filtering.
580
581 @dend
582 * ----------------------------------------------------
583 */
584 RMenum
rmTextureSetFilterMode(RMtexture * t,GLenum min_mode,GLenum mag_mode)585 rmTextureSetFilterMode (RMtexture *t,
586 GLenum min_mode,
587 GLenum mag_mode)
588 {
589 if (RM_ASSERT(t, "rmTextureSetFilterMode() error: input texture is NULL. ") == RM_WHACKED)
590 return(RM_WHACKED);
591
592 t->min_filter_mode = min_mode;
593 t->mag_filter_mode = mag_mode;
594
595 return(RM_CHILL);
596 }
597
598
599 /*
600 * ----------------------------------------------------
601 * @Name rmTextureGetFilterMode
602 @pstart
603 RMenum rmTextureGetFilterMode (const RMtexture *toQuery,
604 GLenum *minModeReturn,
605 GLenum *magModeReturn)
606 @pend
607
608 @astart
609 const RMtexture *toQuery - a handle to an RMtexture object to query
610 (input).
611
612 GLenum *minModeReturn, *magModeReturn - handles to GLenum's
613 (modified, return).
614 @aend
615
616 @dstart
617
618 Use this routine to get the texture filtering modes from an RMtexture
619 object. Upon success, RM_CHILL is returned and the filtering modes
620 are copied from the RMtexture object into caller-supplied
621 memory. Otherwise, RM_WHACKED is returned.
622
623 @dend
624 * ----------------------------------------------------
625 */
626 RMenum
rmTextureGetFilterMode(const RMtexture * t,GLenum * min_mode,GLenum * mag_mode)627 rmTextureGetFilterMode (const RMtexture *t,
628 GLenum *min_mode,
629 GLenum *mag_mode)
630 {
631 if (RM_ASSERT(t, "rmTextureGetFilterMode() error: input texture is NULL. ") == RM_WHACKED)
632 return(RM_WHACKED);
633
634 if (min_mode != NULL)
635 *min_mode = t->min_filter_mode;
636
637 if (mag_mode != NULL)
638 *mag_mode = t->mag_filter_mode;
639
640 return(RM_CHILL);
641 }
642
643
644 /*
645 * ----------------------------------------------------
646 * @Name rmTextureSetWrapMode
647 @pstart
648 RMenum rmTextureSetWrapMode (RMtexture *toModify,
649 GLenum wrapMode)
650 @pend
651
652 @astart
653 RMtexture *toModify - a handle to an RMtexture object to modify
654 (modified).
655
656 GLenum wrapMode - a GLenum specifying a texture wrap mode
657 (input). May be one of GL_CLAMP or GL_REPEAT (OpenGL 1.2 adds the
658 new texture wrap mode of GL_CLAMP_TO_EDGE).
659 @aend
660
661 @dstart
662
663 Use this routine to set the "wrap mode" of an RMtexture
664 object. Returns RM_CHILL upon success, or RM_WHACKED upon failure.
665
666 By definition, texture coordinates range from 0.0 to 1.0, and define
667 a parametric index into a texture. The texture wrap mode comes into
668 play when texture coordinates go outside the range 0..1.
669
670 When GL_CLAMP is used, texture coordinates greater than 1.0 are
671 clamped to 1.0, and those less than 0.0 are clamped to 0.0. Texture
672 coordinates within the range 0..1 remain unmodified.
673
674 When GL_REPEAT is used, texture coordinates outside the range 0..1
675 are treated as if they were inside the range 0..1. The exact method
676 used to implement this interpretation is platform-dependent, but a
677 safe assumption is that most implementations ingore all but the
678 fractional part of the texture coordinate.
679
680 Note that when GL_REPEAT is used, the texture border color is always
681 ignored (rmTextureSetEnv). Similarly, when the GL_NEAREST filtering
682 mode is used, the border color is also always ignored.
683
684 Please refer to the OpenGL red book for more information about
685 texture wrapping.
686
687 Note that the RM implementation allows specification of onlye a
688 single wrap mode. The one wrap mode is used for all texture
689 dimensions. In this API, it is not possible to specify different wrap
690 policies for each texture axis, although OpenGL does allow for this
691 possibility. This RM policy reflects a simplification to the OpenGL
692 API.
693
694 @dend
695 * ----------------------------------------------------
696 */
697 RMenum
rmTextureSetWrapMode(RMtexture * t,GLenum wrap_mode)698 rmTextureSetWrapMode (RMtexture *t,
699 GLenum wrap_mode)
700 {
701 if (RM_ASSERT(t, "rmTextureSetWrapMode() error: input texture is NULL. ") == RM_WHACKED)
702 return(RM_WHACKED);
703
704 t->wrap_mode = wrap_mode;
705 return(RM_CHILL);
706 }
707
708
709 /*
710 * ----------------------------------------------------
711 * @Name rmTextureGetWrapMode
712 @pstart
713 RMenum rmTextureGetWrapMode (const RMtexture *toQuery,
714 GLenum *wrapModeReturn)
715 @pend
716
717 @astart
718 const RMtexture *toQuery - a handle to an RMtexture object that will
719 be queried (input).
720
721 GLenum *wrapModeReturn - a handle to a GLenum (result).
722 @aend
723
724 @dstart
725
726 Use this routine to obtain the texture wrap mode of an RMtexture
727 object. Upon success, RM_CHILL is returned, and the texture wrap
728 mode is copied from the RMtexture object into the caller-supplied
729 GLenum. Otherwise, RM_WHACKED is returned.
730
731 @dend
732 * ----------------------------------------------------
733 */
734 RMenum
rmTextureGetWrapMode(const RMtexture * t,GLenum * wrap_mode)735 rmTextureGetWrapMode (const RMtexture *t,
736 GLenum *wrap_mode)
737 {
738 if (RM_ASSERT(t, "rmTextureGetWrapMode() error: input texture is NULL. ") == RM_WHACKED)
739 return(RM_WHACKED);
740
741 if (wrap_mode != NULL)
742 *wrap_mode = t->wrap_mode;
743
744 return(RM_CHILL);
745 }
746
747
748 /*
749 * ----------------------------------------------------
750 * @Name rmTextureSetEnv
751 @pstart
752 RMenum rmTextureSetEnv (RMtexture *toModify,
753 GLenum envMode,
754 const RMcolor4D *blendColor)
755 @pend
756
757 @astart
758 RMtexture *toModify - a handle to an RMtexture object to modify
759 (modified).
760
761 GLenum envMode - a GLenum value specifying one of several texture
762 mapping modes. May be one of GL_DECAL, GL_REPLACE, GL_MODULATE or
763 GL_BLEND (input).
764
765 const RMcolor4D *blendColor - an handle to an RMcolor4D object (NULL
766 is acceptable) (input).
767 @aend
768
769 @dstart
770
771 Sets texture environment parameters in an RMtexture object. Returns
772 RM_CHILL upon success, or RM_WHACKED upon failure.
773
774 The "texture environment" specifies how, precisely, the color of a
775 texture is combined with the color of a pixel fragment. Please refer
776 to the OpenGL Red Book for more information about the effect of each
777 of the texture environment modes GL_DECAL, GL_REPLACE, GL_MODULATE
778 and GL_BLEND.
779
780 The blendColor parameter is optional, and takes effect only when
781 GL_BLEND is used for the texturing method. The default value for
782 blendColor when left unspecified by the application is (0,0,0,0). If
783 blendColor is NULL, the existing blendColor in the RMtexture object,
784 if any, remains unmodified.
785
786 @dend
787 * ----------------------------------------------------
788 */
789 RMenum
rmTextureSetEnv(RMtexture * t,GLenum envMode,const RMcolor4D * blendColor)790 rmTextureSetEnv (RMtexture *t,
791 GLenum envMode,
792 const RMcolor4D *blendColor)
793 {
794 if (RM_ASSERT(t, "rmTextureSetEnv() error: the input texture is NULL") == RM_WHACKED)
795 return(RM_WHACKED);
796
797 t->envMode = envMode;
798
799 if (blendColor != NULL)
800 {
801 if (t->blendColor != NULL)
802 {
803 rmColor4DDelete(t->blendColor);
804 t->blendColor = NULL;
805 }
806
807 t->blendColor = rmColor4DNew(1);
808 *(t->blendColor) = *blendColor;
809 }
810 return(RM_CHILL);
811 }
812
813
814 /*
815 * ----------------------------------------------------
816 * @Name rmTextureGetEnv
817 @pstart
818 RMenum rmTextureGetEnv (const RMtexture *toQuery,
819 GLenum *envModeReturn,
820 RMcolor4D *blendColorReturn)
821 @pend
822
823 @astart
824 const RMtexture *toQuery - a handle to an RMtexture object (input).
825
826 GLenum *envModeReturn - a handle to a GLenum (return).
827
828 RMcolor4D *blendColorReturn - a handle to an RMcolor4D object
829 (return).
830 @aend
831
832 @dstart
833
834 Use this routine to obtain the texture environment parameters of an
835 RMtexture object. Upon success, RM_CHILL is returned, and the texture
836 environment mode and blend color are copied into caller-supplied
837 memory. Otherwise, RM_WHACKED is returned.
838
839 @dend
840 * ----------------------------------------------------
841 */
842 RMenum
rmTextureGetEnv(const RMtexture * t,GLenum * envMode,RMcolor4D * blendColor)843 rmTextureGetEnv (const RMtexture *t,
844 GLenum *envMode,
845 RMcolor4D *blendColor)
846 {
847 if (RM_ASSERT(t, "rmTextureGetEnv() error: the input texture is NULL") == RM_WHACKED)
848 return(RM_WHACKED);
849
850 if (envMode != NULL)
851 *envMode = t->envMode;
852
853 if (blendColor != NULL && t->blendColor != NULL)
854 *blendColor = *(t->blendColor);
855
856 return(RM_CHILL);
857 }
858
859
860 /*
861 * ----------------------------------------------------
862 * @Name rmTextureSetGLTexelFormat
863 @pstart
864 RMenum rmTextureSetGLTexelFormat (RMtexture *toModify,
865 GLenum internalTexelFormat)
866 @pend
867
868 @astart
869 RMtexture *toModify - a handle to an RMtexture object (modified).
870
871 GLenum internalTexelFormat - a GLenum pixel format descriptor. See
872 below for acceptable values (input).
873 @aend
874
875 @dstart
876
877 Use this routine to tell OpenGL how texture pixel data will be stored
878 in OpenGL texture memory. Returns RM_CHILL upon success, or
879 RM_WHACKED upon failure.
880
881 The permissible values for internalTexelFormat are a function of the
882 particular OpenGL implementation that you are using. The set of
883 GL_LUMINANCE, GL_LUMINANCE_ALPHA, GL_RGB, GL_RGBA are supported
884 across all implementations. Some implementations support more
885 specific values, such as GL_RGBA4, meaning that 4 bits of space are
886 used for each of the R, G, B and A components of the texture.
887
888 OpenGL converts from the source image format (in the RMimage object)
889 to the format requested by this routine. The application need not be
890 concerned with performing this pixel reformatting.
891
892 By default, RM uses GL_RGBA unless overridden by the application's
893 use of this routine.
894
895 @dend
896 * ----------------------------------------------------
897 */
898 RMenum
rmTextureSetGLTexelFormat(RMtexture * t,GLenum texelFormat)899 rmTextureSetGLTexelFormat (RMtexture *t,
900 GLenum texelFormat)
901 {
902 if (RM_ASSERT(t, "rmTextureSetGLTexelFormat error: the input RMtexture pointer is NULL") == RM_WHACKED)
903 return(RM_WHACKED);
904
905 if (t->oglTexelFormat == NULL)
906 t->oglTexelFormat = (GLenum *)malloc(sizeof(GLenum));
907
908 *(t->oglTexelFormat) = texelFormat;
909
910 return(RM_CHILL);
911 }
912
913
914 /*
915 * ----------------------------------------------------
916 * @Name rmTextureGetGLTexelFormat
917 @pstart
918 RMenum rmTextureGetGLTexelFormat (const RMtexture *toQuery,
919 GLenum *returnTexelFormat)
920 @pend
921
922 @astart
923 const RMtexture *toQuery - a handle to an RMtexture object (input).
924
925 GLenum *returnTexelFormat - a handle to a GLenum value (return).
926 @aend
927
928 @dstart
929
930 Use this routine to obtain the texel storage format used by the
931 RMtexture object toQuery. Upon success, the texel storage format will
932 be copied into caller-supplied memory and RM_CHILL will be
933 returned. Otherwise, RM_WHACKED is returned.
934
935 @dend
936 * ----------------------------------------------------
937 */
938 RMenum
rmTextureGetGLTexelFormat(const RMtexture * t,GLenum * returnTexelFormat)939 rmTextureGetGLTexelFormat (const RMtexture *t,
940 GLenum *returnTexelFormat)
941 {
942 if ((RM_ASSERT(t, "rmTextureGetGLTexelFormat error: the input RMtexture pointer is NULL") == RM_WHACKED) ||
943 (RM_ASSERT(returnTexelFormat, "rmTextureGLGetTexelFormat error: the return texel format enumerator pointer is NULL.") == RM_WHACKED))
944 return(RM_WHACKED);
945
946 if (returnTexelFormat != NULL)
947 {
948 if (t->oglTexelFormat == NULL)
949 return(RM_WHACKED);
950 else
951 {
952 *returnTexelFormat = *(t->oglTexelFormat);
953 return(RM_CHILL);
954 }
955 }
956 return(RM_CHILL);
957 }
958
959 /*
960 * ----------------------------------------------------
961 * @Name rmTextureGetTextureID
962 @pstart
963 RMenum rmTextureGetTextureID (const RMtexture *toQuery,
964 GLuint *returnTextureID)
965 @pend
966
967 @astart
968 const RMtexture *toQuery - a handle to an RMtexture object (input).
969 GLuint *returnTetureID - a handle to a GLuint, application-provided memory (result).
970 @aend
971
972 @dstart
973
974 Use this routine to obtain the GL textureID handle associated with an
975 RMtexture as specified by an earlier call to rmTextureSetTextureID.
976 This routine does NOT return the GL textureID for textures built and
977 managed by OpenRM/RM.
978
979 Upon success, this routine returns RM_CHILL, and the value of the
980 application-supplied GL textureID will be copied into caller-supplied
981 memory. Upon failure, RM_WHACKED is returned, and caller-supplied memory
982 remains unmodified.
983
984 See the documentation for rmTextureSetTextureID for more information about
985 application-supplied textures.
986
987 @dend
988 * ----------------------------------------------------
989 */
990 RMenum
rmTextureGetTextureID(const RMtexture * toQuery,GLuint * returnTextureID)991 rmTextureGetTextureID (const RMtexture *toQuery,
992 GLuint *returnTextureID)
993 {
994 if ((RM_ASSERT(toQuery, "rmTextureGetTextureID error: the input RMtexture pointer is NULL") == RM_WHACKED) ||
995 (RM_ASSERT(returnTextureID, "rmTextureGetTextureID error: the returnTextureID parameter is NULL")))
996 return RM_WHACKED;
997
998 if (toQuery->appTextureID == NULL)
999 return RM_WHACKED;
1000
1001 *returnTextureID = *(toQuery->appTextureID);
1002
1003 return RM_CHILL;
1004 }
1005
1006 /*
1007 * ----------------------------------------------------
1008 * @Name rmTextureSetTextureID
1009 @pstart
1010 RMenum rmTextureSetTextureID (RMtexture *toModify,
1011 GLuint *textureID)
1012 @pend
1013
1014 @astart
1015 RMtexture *toModify - a handle to an RMtexture object (input).
1016 GLuint *textureID - a pointer to a GLuint texture ID (input).
1017 @aend
1018
1019 @dstart
1020
1021 Use this routine to assign an application-generated GL texture ID to an
1022 RMtexture object in lieu of providing RMimage texel data with
1023 rmTextureSetImages. The intent of this approach to texturing is to help
1024 support those applications that use third-party tools to create and
1025 load textures to OpenGL external to OpenRM.
1026
1027 You may specify a value of NULL for the textureID parameter, in which
1028 case the application-supplied textureID field will be removed from the
1029 RMtexture object "toModify."
1030
1031 This routine returns RM_CHILL upon success, and RM_WHACKED upon failure.
1032
1033 The procedure to use for texturing with application-supplied textures
1034 is as follows:
1035 1. (Required) Create the RMtexture with rmTextureNew(ndims). Use ndims=1
1036 for 1D textures, 2 for 2D textures or 3 for 3D textures.
1037 2. (Optional) Specify texturing environment parameters using rmTextureSet*
1038 routines.
1039 3. (Required) Assign the application-supplied GL texture ID with
1040 rmTextureSetTextureID.
1041 4. (Required) Assign the RMtexture as a scene parameter to an RMnode.
1042
1043 The application-supplied texture must be created only after OpenGL is
1044 active, which means that an OpenGL context has been created and made
1045 current. Usually, this set of conditions is met after the application
1046 makes a call to rmPipeMakeCurrent().
1047
1048 Also note that your RMprimitive must have texture coordinates of the
1049 "same species" as the GL texture. In other words, use 1D texture coordinates
1050 with 1D textures, and so forth.
1051
1052 @dend
1053 * ----------------------------------------------------
1054 */
1055 RMenum
rmTextureSetTextureID(RMtexture * toModify,GLuint * textureID)1056 rmTextureSetTextureID (RMtexture *toModify,
1057 GLuint *textureID)
1058 {
1059 if (RM_ASSERT(toModify, "rmTextureSetTextureID error: the input RMtexture pointer is NULL") == RM_WHACKED)
1060 return RM_WHACKED;
1061
1062 /*
1063 * While we can't check for a valid GL texture ID right now, since
1064 * we might not be the rendering thread or have an active, bound OpenGL
1065 * context, we can check for obviously bogus values.
1066 */
1067
1068 if ((textureID == NULL) || (*textureID <= 0))
1069 {
1070 rmError("rmTextureSetTextureID() error - the input textureID value is less than or equal to zero. ");
1071 return RM_WHACKED;
1072 }
1073
1074 if (toModify->appTextureID != NULL)
1075 {
1076 free((void *)(toModify->appTextureID));
1077 toModify->appTextureID = NULL;
1078 }
1079
1080 if (textureID != NULL)
1081 {
1082 if ((toModify->appTextureID = (GLuint *)private_rmMemDup((void *)textureID, sizeof(GLuint))) == NULL)
1083 return RM_WHACKED;
1084 }
1085
1086 return RM_CHILL;
1087 }
1088
1089 /*
1090 * PRIVATE
1091 * download 3D textures to OpenGL
1092 */
1093 void
private_rmTexture3DDownload(RMpipe * p,RMtexture * t,int isNew)1094 private_rmTexture3DDownload(RMpipe *p,
1095 RMtexture *t,
1096 int isNew)
1097 {
1098 RMvisMap *vmap=NULL;
1099 GLenum srcGLTexelFormat, dstGLTexelFormat;
1100 int i;
1101
1102 glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_S, t->wrap_mode);
1103 glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_T, t->wrap_mode);
1104 glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_R_EXT, t->wrap_mode);
1105 glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, t->mag_filter_mode);
1106 glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, t->min_filter_mode);
1107
1108 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, t->envMode);
1109
1110 if (t->blendColor != NULL)
1111 glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, (GLfloat *)(t->blendColor));
1112
1113 for (i = 0; i < private_rmTextureGetNMipMaps(t); i++)
1114 {
1115 int w,h,d;
1116
1117 if (t->images[i] == NULL)
1118 {
1119 char buf[128];
1120 sprintf(buf," the RMimage at mipmap level %d for a 3D texture is missing. The texture download likely did not succeed, and your texturing will not be correct. \n",i);
1121 rmError(buf);
1122 break; /* exit the loop over mipmaps */
1123 }
1124
1125 vmap = private_rmImageGetVismap(t->images[i]);
1126
1127 /* convert between RM and OpenGL type enumerators */
1128 srcGLTexelFormat = private_rmImageGetOGLFormat(t->images[i]);
1129 rmTextureGetGLTexelFormat(t, &dstGLTexelFormat);
1130
1131 if (vmap != NULL)
1132 private_rmSetPixelTransferMode(vmap);
1133 else
1134 private_rmUnsetPixelTransferMode();
1135
1136 rmImageGetImageSize(t->images[i], NULL, &w, &h, &d, NULL, NULL);
1137
1138 /* updates to allow for non-byte input texel data 2/19/02 */
1139 if (isNew == 1)
1140 {
1141 if (p->caps->rm_glTexImage3D != NULL)
1142 (*(p->caps->rm_glTexImage3D))(GL_TEXTURE_3D, i, dstGLTexelFormat, w, h, d, t->borderWidth, srcGLTexelFormat, private_rmImageGetOGLType(t->images[i]), (const GLvoid *)(private_rmImageGetPixelData(t->images[i])));
1143 #if 0
1144 glTexImage3D(GL_TEXTURE_3D, i, dstGLTexelFormat, w, h, d, t->borderWidth, srcGLTexelFormat, private_rmImageGetOGLType(t->images[i]), (const GLvoid *)(private_rmImageGetPixelData(t->images[i])));
1145 #else
1146 #endif
1147 rmGLGetError(" while loading 3D texture(s) ");
1148 }
1149 else
1150 {
1151 #if 0
1152 glTexSubImage3D(GL_TEXTURE_3D, i, 0, 0, 0, w, h, d, srcGLTexelFormat, private_rmImageGetOGLType(t->images[0]), (const GLvoid *)(private_rmImageGetPixelData(t->images[i])));
1153 #else
1154 #endif
1155 rmGLGetError(" while loading 3D subtexture(s) ");
1156 }
1157 }
1158
1159 private_rmUnsetPixelTransferMode();
1160 }
1161
1162 /*
1163 * PRIVATE
1164 * download 2D textures to OpenGL
1165 */
1166 void
private_rmTexture2DDownload(RMtexture * t,int isNew)1167 private_rmTexture2DDownload(RMtexture *t,
1168 int isNew)
1169 {
1170 RMvisMap *vmap=NULL;
1171 GLenum srcGLTexelFormat, dstGLTexelFormat;
1172 int i;
1173
1174 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, t->wrap_mode);
1175 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, t->wrap_mode);
1176
1177 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, t->mag_filter_mode);
1178 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, t->min_filter_mode);
1179
1180 /* glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, t->envMode); */
1181
1182 if (t->blendColor != NULL)
1183 glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, (GLfloat *)(t->blendColor));
1184
1185 for (i = 0; i < private_rmTextureGetNMipMaps(t); i++)
1186 {
1187 int w,h;
1188
1189 if (t->images[i] == NULL)
1190 {
1191 char buf[128];
1192 sprintf(buf," the RMimage at mipmap level %d for a 2D texture is missing. The texture download likely did not succeed, and your texturing will not be correct. \n",i);
1193 rmError(buf);
1194 break; /* exit the loop over mipmaps */
1195 }
1196
1197 vmap = private_rmImageGetVismap(t->images[i]);
1198
1199 /* convert between RM and OpenGL type enumerators */
1200 srcGLTexelFormat = private_rmImageGetOGLFormat(t->images[i]);
1201 rmTextureGetGLTexelFormat(t, &dstGLTexelFormat);
1202
1203 if (vmap != NULL)
1204 private_rmSetPixelTransferMode(vmap);
1205 #if 1
1206 else
1207 private_rmUnsetPixelTransferMode();
1208 #else
1209 fprintf(stderr,"private_rmTexture2DDownload() - temporarily disabling rmUnsetPixelTransferMode prior to texel download.");
1210 fflush(stderr);
1211 #endif
1212
1213 rmImageGetImageSize(t->images[i], NULL, &w, &h, NULL, NULL, NULL);
1214
1215 if (isNew == 1)
1216 {
1217 glTexImage2D(GL_TEXTURE_2D, i, dstGLTexelFormat, w, h, t->borderWidth, srcGLTexelFormat, private_rmImageGetOGLType(t->images[i]), (const GLvoid *)(private_rmImageGetPixelData(t->images[i])));
1218 rmGLGetError(" while loading 2D texture(s) ");
1219 }
1220 else
1221 {
1222 glTexSubImage2D(GL_TEXTURE_2D, i, 0, 0, w, h, srcGLTexelFormat, private_rmImageGetOGLType(t->images[0]), (const GLvoid *)(private_rmImageGetPixelData(t->images[i])));
1223 rmGLGetError(" while loading 2D subtexture(s) ");
1224 }
1225 }
1226
1227 private_rmUnsetPixelTransferMode();
1228 }
1229
1230 /*
1231 * PRIVATE
1232 * download 1D textures to OpenGL
1233 */
1234 void
private_rmTexture1DDownload(RMtexture * t,int isNew)1235 private_rmTexture1DDownload(RMtexture *t,
1236 int isNew)
1237 {
1238 RMvisMap *vmap=NULL;
1239 GLenum srcGLTexelFormat, dstGLTexelFormat;
1240 int i;
1241
1242 glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_WRAP_S, t->wrap_mode);
1243
1244 glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, t->mag_filter_mode);
1245 glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, t->min_filter_mode);
1246
1247
1248 if (t->blendColor != NULL)
1249 glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, (GLfloat *)(t->blendColor));
1250
1251 for (i = 0; i < private_rmTextureGetNMipMaps(t); i++)
1252 {
1253 int w;
1254
1255 if (t->images[i] == NULL)
1256 {
1257 char buf[128];
1258 sprintf(buf," the RMimage at mipmap level %d for a 2D texture is missing. The texture download likely did not succeed, and your texturing will not be correct. \n",i);
1259 rmError(buf);
1260 break; /* exit the loop over mipmaps */
1261 }
1262
1263 vmap = private_rmImageGetVismap(t->images[i]);
1264
1265 /* convert between RM and OpenGL type enumerators */
1266 srcGLTexelFormat = private_rmImageGetOGLFormat(t->images[i]);
1267 rmTextureGetGLTexelFormat(t, &dstGLTexelFormat);
1268
1269 if (vmap != NULL)
1270 private_rmSetPixelTransferMode(vmap);
1271 #if 1
1272 else
1273 private_rmUnsetPixelTransferMode();
1274 #else
1275 fprintf(stderr,"private_rmTexture2DDownload() - temporarily disabling rmUnsetPixelTransferMode prior to texel download.");
1276 fflush(stderr);
1277 #endif
1278
1279 rmImageGetImageSize(t->images[i], NULL, &w, NULL, NULL, NULL, NULL);
1280
1281 if (isNew == 1)
1282 {
1283 glTexImage1D(GL_TEXTURE_1D, i, dstGLTexelFormat, w, t->borderWidth, srcGLTexelFormat, private_rmImageGetOGLType(t->images[i]), (const GLvoid *)(private_rmImageGetPixelData(t->images[i])));
1284 rmGLGetError(" while loading 1D texture(s) ");
1285 }
1286 else
1287 {
1288 glTexSubImage1D(GL_TEXTURE_2D, i, 0, w, srcGLTexelFormat, private_rmImageGetOGLType(t->images[0]), (const GLvoid *)(private_rmImageGetPixelData(t->images[i])));
1289 rmGLGetError(" while loading 2D subtexture(s) ");
1290 }
1291 }
1292
1293 private_rmUnsetPixelTransferMode();
1294 }
1295
1296 /* PRIVATE
1297 *
1298 * internal routine to push texture data over to OpenGL
1299 */
1300 void
private_rmTextureToOGL(RMpipe * p,RMtexture * t,int isNew)1301 private_rmTextureToOGL (RMpipe *p,
1302 RMtexture *t,
1303 int isNew)
1304 {
1305 if (RM_ASSERT(t->images[0], "an RMtexture was encountered for which no RMimage data has been assigned.") == RM_WHACKED)
1306 return;
1307
1308 switch(private_rmTextureGetDims(t))
1309 {
1310 case 3:
1311 private_rmTexture3DDownload(p, t, isNew);
1312 break;
1313
1314 case 2:
1315 private_rmTexture2DDownload(t, isNew);
1316 break;
1317
1318 case 1:
1319 private_rmTexture1DDownload(t, isNew);
1320 break;
1321
1322 default:
1323 rmError("private_rmTextureToOGL error - the input RMtexture is not 1D, 2D or 3D.");
1324 break;
1325 }
1326 }
1327
1328
1329 /* PRIVATE */
1330 void
private_rmSetPixelTransferMode(const RMvisMap * vm)1331 private_rmSetPixelTransferMode (const RMvisMap *vm)
1332 {
1333 int n;
1334
1335 if (RM_ASSERT(vm, "private_rmSetPixelTranserMode error: the input colormap is NULL.") == RM_WHACKED)
1336 return;
1337
1338 glPixelTransferi(GL_MAP_COLOR, GL_TRUE);
1339
1340 n = rmVismapGetSize(vm);
1341
1342 glPixelMapfv(GL_PIXEL_MAP_R_TO_R, n, vm->r);
1343 glPixelMapfv(GL_PIXEL_MAP_G_TO_G, n, vm->g);
1344 glPixelMapfv(GL_PIXEL_MAP_B_TO_B, n, vm->b);
1345 glPixelMapfv(GL_PIXEL_MAP_A_TO_A, n, vm->a);
1346
1347 }
1348
1349
1350 /* PRIVATE */
1351 void
private_rmUnsetPixelTransferMode(void)1352 private_rmUnsetPixelTransferMode (void)
1353 {
1354 glPixelTransferi(GL_MAP_COLOR, GL_FALSE);
1355
1356 #if 0
1357 /* 1/26/03 - just turn off pixel transfer. No need to set the
1358 map sizes to zero with NULL values, because doing so can cause
1359 an OpenGL error */
1360 glPixelMapfv(GL_PIXEL_MAP_R_TO_R, 0, NULL);
1361 glPixelMapfv(GL_PIXEL_MAP_G_TO_G, 0, NULL);
1362 glPixelMapfv(GL_PIXEL_MAP_B_TO_B, 0, NULL);
1363 glPixelMapfv(GL_PIXEL_MAP_A_TO_A, 0, NULL);
1364 #endif
1365 }
1366
1367 /* PRIVATE */
1368 /*
1369 * an RMtexture's "reference count" indicates the number of times a given
1370 * RMtexture is used as a shared texture scene parameter at an RMnode.
1371 * When an RMtexture is added as a shared texture scene parameter, the
1372 * RMtexture's reference counter is automatically incremented, and when
1373 * the shared RMtexture scene parameter is removed, it is decremented.
1374 * Deleting RMtextures is prohibited when the RMtexture's reference count
1375 * is a positive integer.
1376 */
1377 void
private_rmTextureSetRefCount(RMtexture * t,int newVal)1378 private_rmTextureSetRefCount(RMtexture *t,
1379 int newVal)
1380 {
1381 t->refCount = newVal;
1382 }
1383
1384 /* PRIVATE */
1385 int
private_rmTextureGetRefCount(const RMtexture * t)1386 private_rmTextureGetRefCount(const RMtexture *t)
1387 {
1388 return t->refCount;
1389 }
1390
1391
1392 /* EOF */
1393