Source Code Cross Referenced for TextureRetained.java in  » 6.0-JDK-Modules » java-3d » javax » media » j3d » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » 6.0 JDK Modules » java 3d » javax.media.j3d 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:         * $RCSfile: TextureRetained.java,v $
0003:         *
0004:         * Copyright 1998-2008 Sun Microsystems, Inc.  All Rights Reserved.
0005:         * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
0006:         *
0007:         * This code is free software; you can redistribute it and/or modify it
0008:         * under the terms of the GNU General Public License version 2 only, as
0009:         * published by the Free Software Foundation.  Sun designates this
0010:         * particular file as subject to the "Classpath" exception as provided
0011:         * by Sun in the LICENSE file that accompanied this code.
0012:         *
0013:         * This code is distributed in the hope that it will be useful, but WITHOUT
0014:         * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
0015:         * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
0016:         * version 2 for more details (a copy is included in the LICENSE file that
0017:         * accompanied this code).
0018:         *
0019:         * You should have received a copy of the GNU General Public License version
0020:         * 2 along with this work; if not, write to the Free Software Foundation,
0021:         * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
0022:         *
0023:         * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
0024:         * CA 95054 USA or visit www.sun.com if you need additional information or
0025:         * have any questions.
0026:         *
0027:         * $Revision: 1.17 $
0028:         * $Date: 2008/02/28 20:17:32 $
0029:         * $State: Exp $
0030:         */
0031:
0032:        package javax.media.j3d;
0033:
0034:        import java.util.*;
0035:        import javax.vecmath.*;
0036:        import java.awt.image.DataBufferByte;
0037:        import java.awt.image.RenderedImage;
0038:
0039:        /**
0040:         * The Texture object is a component object of an Appearance object
0041:         * that defines the texture properties used when texture mapping is
0042:         * enabled. Texture object is an abstract class and all texture 
0043:         * objects must be created as either a Texture2D object or a
0044:         * Texture3D object.
0045:         */
0046:        abstract class TextureRetained extends NodeComponentRetained {
0047:            // A list of pre-defined bits to indicate which component
0048:            // in this Texture object changed.
0049:            static final int ENABLE_CHANGED = 0x001;
0050:            static final int COLOR_CHANGED = 0x002;
0051:            static final int IMAGE_CHANGED = 0x004;
0052:            static final int STATE_CHANGED = 0x008;
0053:            static final int UPDATE_IMAGE = 0x010;
0054:            static final int IMAGES_CHANGED = 0x020;
0055:            static final int BASE_LEVEL_CHANGED = 0x040;
0056:            static final int MAX_LEVEL_CHANGED = 0x080;
0057:            static final int MIN_LOD_CHANGED = 0x100;
0058:            static final int MAX_LOD_CHANGED = 0x200;
0059:            static final int LOD_OFFSET_CHANGED = 0x400;
0060:
0061:            // constants for min and mag filter
0062:            static final int MIN_FILTER = 0;
0063:            static final int MAG_FILTER = 1;
0064:
0065:            // Boundary width
0066:            int boundaryWidth = 0;
0067:
0068:            // Boundary modes (wrap, clamp, clamp_to_edge, clamp_to_boundary)
0069:            int boundaryModeS = Texture.WRAP;
0070:            int boundaryModeT = Texture.WRAP;
0071:
0072:            // Filter modes
0073:            int minFilter = Texture.BASE_LEVEL_POINT;
0074:            int magFilter = Texture.BASE_LEVEL_POINT;
0075:
0076:            // Integer flag that contains bitset to indicate 
0077:            // which field changed.
0078:            int isDirty = 0xffff;
0079:
0080:            // Texture boundary color
0081:            Color4f boundaryColor = new Color4f(0.0f, 0.0f, 0.0f, 0.0f);
0082:
0083:            // Texture Object Id used by native code.
0084:            int objectId = -1;
0085:
0086:            int mipmapMode = Texture.BASE_LEVEL; // Type of mip-mapping 
0087:            int format = Texture.RGB; // Texture format
0088:            int width = 1; // Width in pixels (2**n)
0089:            int height = 1; // Height in pixels (2**m)
0090:
0091:            // true if width or height is non power of two    
0092:            private boolean widthOrHeightIsNPOT = false;
0093:            // Array of images (one for each mipmap level)    
0094:            ImageComponentRetained images[][];
0095:            // maximum number of levels needed for the mipmapMode of this texture
0096:            int maxLevels = 0;
0097:            // maximum number of mipmap levels that can be defined for this texture
0098:            private int maxMipMapLevels = 0;
0099:
0100:            int numFaces = 1; // For CubeMap, it is 6
0101:            int baseLevel = 0;
0102:            int maximumLevel = 0;
0103:            float minimumLod = -1000.0f;
0104:            float maximumLod = 1000.0f;
0105:            Point3f lodOffset = null;
0106:
0107:            private boolean useAsRaster = false; // true if used by Raster or Background.
0108:
0109:            // Texture mapping enable switch
0110:            // This enable is derived from the user specified enable
0111:            // and whether the buf image in the imagecomp is null
0112:            boolean enable = true;
0113:
0114:            // User specified enable
0115:            boolean userSpecifiedEnable = true;
0116:
0117:            // true if alpha channel need update during rendering
0118:            boolean isAlphaNeedUpdate = false;
0119:
0120:            // sharpen texture info
0121:            int numSharpenTextureFuncPts = 0;
0122:            float sharpenTextureFuncPts[] = null; // array of pairs of floats
0123:            // first value for LOD
0124:            // second value for the fcn value	
0125:
0126:            // filter4 info
0127:            float filter4FuncPts[] = null;
0128:
0129:            // anisotropic filter info
0130:            int anisotropicFilterMode = Texture.ANISOTROPIC_NONE;
0131:            float anisotropicFilterDegree = 1.0f;
0132:
0133:            // Each bit corresponds to a unique renderer if shared context
0134:            // or a unique canvas otherwise.
0135:            // This mask specifies which renderer/canvas has loaded the
0136:            // texture images. 0 means no renderer/canvas has loaded the texture.
0137:            // 1 at the particular bit means that renderer/canvas has loaded the
0138:            // texture. 0 means otherwise.
0139:            int resourceCreationMask = 0x0;
0140:
0141:            // Each bit corresponds to a unique renderer if shared context
0142:            // or a unique canvas otherwise
0143:            // This mask specifies if texture images are up-to-date.
0144:            // 0 at a particular bit means texture images are not up-to-date.
0145:            // 1 means otherwise. If it specifies 0, then it needs to go
0146:            // through the imageUpdateInfo to update the images accordingly.
0147:            // 
0148:            int resourceUpdatedMask = 0x0;
0149:
0150:            // Each bit corresponds to a unique renderer if shared context
0151:            // or a unique canvas otherwise
0152:            // This mask specifies if texture lod info is up-to-date.
0153:            // 0 at a particular bit means texture lod info is not up-to-date.
0154:            // 1 means otherwise. 
0155:            // 
0156:            int resourceLodUpdatedMask = 0x0;
0157:
0158:            // Each bit corresponds to a unique renderer if shared context
0159:            // or a unique canvas otherwise
0160:            // This mask specifies if texture is in the resource reload list
0161:            // 0 at a particular bit means texture is not in reload list
0162:            // 1 means otherwise. 
0163:            // 
0164:            int resourceInReloadList = 0x0;
0165:
0166:            // image update info
0167:            ArrayList imageUpdateInfo[][];
0168:
0169:            int imageUpdatePruneMask[];
0170:
0171:            // Issue 357 - we need a separate reference counter per RenderBin, since
0172:            // each RenderBin keeps an independent list of Texture objects to be freed.
0173:            // Since this is accessed infrequently, we will use a HashMap for the
0174:            // textureBin reference counter
0175:            private HashMap<RenderBin, Integer> textureBinRefCount = new HashMap<RenderBin, Integer>();
0176:
0177:            // This is used for D3D only to check whether texture need to
0178:            // resend down
0179:            private int texTimestamp = 0;
0180:
0181:            // need to synchronize access from multiple rendering threads 
0182:            Object resourceLock = new Object();
0183:
0184:            private static boolean isPowerOfTwo(int val) {
0185:                return ((val & (val - 1)) == 0);
0186:            }
0187:
0188:            void initialize(int format, int width, int widLevels, int height,
0189:                    int heiLevels, int mipmapMode, int boundaryWidth) {
0190:
0191:                this .mipmapMode = mipmapMode;
0192:                this .format = format;
0193:                this .width = width;
0194:                this .height = height;
0195:                this .boundaryWidth = boundaryWidth;
0196:
0197:                if (!isPowerOfTwo(width) || !isPowerOfTwo(height)) {
0198:                    this .widthOrHeightIsNPOT = true;
0199:                }
0200:
0201:                // determine the maximum number of mipmap levels that can be
0202:                // defined from the specified dimension
0203:
0204:                if (widLevels > heiLevels) {
0205:                    maxMipMapLevels = widLevels + 1;
0206:                } else {
0207:                    maxMipMapLevels = heiLevels + 1;
0208:                }
0209:
0210:                // determine the maximum number of mipmap levels that will be
0211:                // needed with the current mipmapMode
0212:
0213:                if (mipmapMode != Texture.BASE_LEVEL) {
0214:                    baseLevel = 0;
0215:                    maximumLevel = maxMipMapLevels - 1;
0216:                    maxLevels = maxMipMapLevels;
0217:                } else {
0218:                    baseLevel = 0;
0219:                    maximumLevel = 0;
0220:                    maxLevels = 1;
0221:                }
0222:
0223:                images = new ImageComponentRetained[numFaces][maxLevels];
0224:
0225:                for (int j = 0; j < numFaces; j++) {
0226:                    for (int i = 0; i < maxLevels; i++) {
0227:                        images[j][i] = null;
0228:                    }
0229:                }
0230:            }
0231:
0232:            final int getFormat() {
0233:                return this .format;
0234:            }
0235:
0236:            final int getWidth() {
0237:                return this .width;
0238:            }
0239:
0240:            final int getHeight() {
0241:                return this .height;
0242:            }
0243:
0244:            final int numMipMapLevels() {
0245:                return (maximumLevel - baseLevel + 1);
0246:            }
0247:
0248:            /**
0249:             * Sets the boundary mode for the S coordinate in this texture object.
0250:             * @param boundaryModeS the boundary mode for the S coordinate,
0251:             * one of: CLAMP or WRAP.
0252:             * @exception RestrictedAccessException if the method is called
0253:             * when this object is part of live or compiled scene graph.
0254:             */
0255:            final void initBoundaryModeS(int boundaryModeS) {
0256:                this .boundaryModeS = boundaryModeS;
0257:            }
0258:
0259:            /**
0260:             * Retrieves the boundary mode for the S coordinate.
0261:             * @return the current boundary mode for the S coordinate.
0262:             * @exception RestrictedAccessException if the method is called
0263:             * when this object is part of live or compiled scene graph.
0264:             */
0265:            final int getBoundaryModeS() {
0266:                return boundaryModeS;
0267:            }
0268:
0269:            /**
0270:             * Sets the boundary mode for the T coordinate in this texture object.
0271:             * @param boundaryModeT the boundary mode for the T coordinate,
0272:             * one of: CLAMP or WRAP.
0273:             * @exception RestrictedAccessException if the method is called
0274:             * when this object is part of live or compiled scene graph.
0275:             */
0276:            final void initBoundaryModeT(int boundaryModeT) {
0277:                this .boundaryModeT = boundaryModeT;
0278:            }
0279:
0280:            /**
0281:             * Retrieves the boundary mode for the T coordinate.
0282:             * @return the current boundary mode for the T coordinate.
0283:             * @exception RestrictedAccessException if the method is called
0284:             * when this object is part of live or compiled scene graph.
0285:             */
0286:            final int getBoundaryModeT() {
0287:                return boundaryModeT;
0288:            }
0289:
0290:            /**
0291:             * Retrieves the boundary width.
0292:             * @return the boundary width of this texture.
0293:             */
0294:            final int getBoundaryWidth() {
0295:                return boundaryWidth;
0296:            }
0297:
0298:            /**
0299:             * Sets the minification filter function.  This
0300:             * function is used when the pixel being rendered maps to an area
0301:             * greater than one texel.
0302:             * @param minFilter the minification filter, one of:
0303:             * FASTEST, NICEST, BASE_LEVEL_POINT, BASE_LEVEL_LINEAR, 
0304:             * MULTI_LEVEL_POINT, MULTI_LEVEL_LINEAR.
0305:             * @exception RestrictedAccessException if the method is called
0306:             * when this object is part of live or compiled scene graph.
0307:             */
0308:            final void initMinFilter(int minFilter) {
0309:                this .minFilter = minFilter;
0310:            }
0311:
0312:            /**
0313:             * Retrieves the minification filter.
0314:             * @return the current minification filter function.
0315:             * @exception RestrictedAccessException if the method is called
0316:             * when this object is part of live or compiled scene graph.
0317:             */
0318:            final int getMinFilter() {
0319:                return minFilter;
0320:            }
0321:
0322:            /**
0323:             * Sets the magnification filter function.  This
0324:             * function is used when the pixel being rendered maps to an area
0325:             * less than or equal to one texel.
0326:             * @param magFilter the magnification filter, one of:
0327:             * FASTEST, NICEST, BASE_LEVEL_POINT, or BASE_LEVEL_LINEAR.
0328:             * @exception RestrictedAccessException if the method is called
0329:             * when this object is part of live or compiled scene graph.
0330:             */
0331:            final void initMagFilter(int magFilter) {
0332:                this .magFilter = magFilter;
0333:            }
0334:
0335:            /**
0336:             * Retrieves the magnification filter.
0337:             * @return the current magnification filter function.
0338:             * @exception RestrictedAccessException if the method is called
0339:             * when this object is part of live or compiled scene graph.
0340:             */
0341:            final int getMagFilter() {
0342:                return magFilter;
0343:            }
0344:
0345:            /**
0346:             * Sets a specified mipmap level.
0347:             * @param level mipmap level to set: 0 is the base level
0348:             * @param image pixel array object containing the texture image
0349:             * @exception RestrictedAccessException if the method is called
0350:             * when this object is part of live or compiled scene graph.
0351:             * @exception IllegalArgumentException if an ImageComponent3D
0352:             * is used in a Texture2D or ImageComponent2D in Texture3D
0353:             * power of 2 OR invalid format/mipmapMode is specified.
0354:             */
0355:            void initImage(int level, ImageComponent image) {
0356:
0357:                // Issue 172 : call checkImageSize even for non-live setImage calls
0358:                checkImageSize(level, image);
0359:
0360:                if (this .images == null) {
0361:                    throw new IllegalArgumentException(J3dI18N
0362:                            .getString("TextureRetained0"));
0363:                }
0364:
0365:                if (this .source instanceof  Texture2D) {
0366:                    if (image instanceof  ImageComponent3D)
0367:                        throw new IllegalArgumentException(J3dI18N
0368:                                .getString("Texture8"));
0369:                } else {
0370:
0371:                    if (image instanceof  ImageComponent2D)
0372:                        throw new IllegalArgumentException(J3dI18N
0373:                                .getString("Texture14"));
0374:                }
0375:
0376:                if (this .source.isLive()) {
0377:
0378:                    if (this .images[0][level] != null) {
0379:                        this .images[0][level].clearLive(refCount);
0380:                    }
0381:
0382:                    if (image != null) {
0383:                        ((ImageComponentRetained) image.retained).setLive(
0384:                                inBackgroundGroup, refCount);
0385:                    }
0386:                }
0387:
0388:                if (image != null) {
0389:                    this .images[0][level] = (ImageComponentRetained) image.retained;
0390:
0391:                } else {
0392:                    this .images[0][level] = null;
0393:                }
0394:            }
0395:
0396:            final void checkImageSize(int level, ImageComponent image) {
0397:                if (image != null) {
0398:                    int imgWidth = ((ImageComponentRetained) image.retained).width;
0399:                    int imgHeight = ((ImageComponentRetained) image.retained).height;
0400:
0401:                    int wdh = width;
0402:                    int hgt = height;
0403:                    for (int i = 0; i < level; i++) {
0404:                        wdh >>= 1;
0405:                        hgt >>= 1;
0406:                    }
0407:
0408:                    if (wdh < 1)
0409:                        wdh = 1;
0410:                    if (hgt < 1)
0411:                        hgt = 1;
0412:
0413:                    if ((wdh != (imgWidth - 2 * boundaryWidth))
0414:                            || (hgt != (imgHeight - 2 * boundaryWidth))) {
0415:                        throw new IllegalArgumentException(J3dI18N
0416:                                .getString("TextureRetained1"));
0417:                    }
0418:                }
0419:            }
0420:
0421:            final void checkSizes(ImageComponentRetained images[]) {
0422:                // Issue 172 : this method is now redundant
0423:
0424:                // Assertion check that the image at each level is the correct size
0425:                // This shouldn't be needed since we already should have checked the
0426:                // size at each level, and verified that all levels are set.
0427:                if (images != null) {
0428:                    int hgt = height;
0429:                    int wdh = width;
0430:                    for (int level = 0; level < images.length; level++) {
0431:                        int imgWidth = images[level].width;
0432:                        int imgHeight = images[level].height;
0433:
0434:                        assert (wdh == (imgWidth - 2 * boundaryWidth))
0435:                                && (hgt == (imgHeight - 2 * boundaryWidth));
0436:
0437:                        wdh /= 2;
0438:                        hgt /= 2;
0439:                        if (wdh < 1)
0440:                            wdh = 1;
0441:                        if (hgt < 1)
0442:                            hgt = 1;
0443:                    }
0444:                }
0445:            }
0446:
0447:            final void setImage(int level, ImageComponent image) {
0448:                initImage(level, image);
0449:
0450:                Object arg[] = new Object[3];
0451:                arg[0] = new Integer(level);
0452:                arg[1] = image;
0453:                arg[2] = new Integer(0);
0454:                sendMessage(IMAGE_CHANGED, arg);
0455:
0456:                // If the user has set enable to true, then if the image is null
0457:                // turn off texture enable
0458:
0459:                if (userSpecifiedEnable) {
0460:                    enable = userSpecifiedEnable;
0461:                    if (image != null && level >= baseLevel
0462:                            && level <= maximumLevel) {
0463:                        ImageComponentRetained img = (ImageComponentRetained) image.retained;
0464:                        if (img.isByReference()) {
0465:                            if (img.getRefImage(0) == null) {
0466:                                enable = false;
0467:                            }
0468:                        } else {
0469:                            if (img.getImageData(isUseAsRaster()).get() == null) {
0470:                                enable = false;
0471:                            }
0472:                        }
0473:                        if (!enable)
0474:                            sendMessage(ENABLE_CHANGED, Boolean.FALSE);
0475:                    }
0476:                }
0477:            }
0478:
0479:            void initImages(ImageComponent[] images) {
0480:
0481:                if (images.length != maxLevels)
0482:                    throw new IllegalArgumentException(J3dI18N
0483:                            .getString("Texture20"));
0484:
0485:                for (int i = 0; i < images.length; i++) {
0486:                    initImage(i, images[i]);
0487:                }
0488:            }
0489:
0490:            final void setImages(ImageComponent[] images) {
0491:
0492:                int i;
0493:
0494:                initImages(images);
0495:
0496:                ImageComponent[] imgs = new ImageComponent[images.length];
0497:                for (i = 0; i < images.length; i++) {
0498:                    imgs[i] = images[i];
0499:                }
0500:
0501:                Object arg[] = new Object[2];
0502:                arg[0] = imgs;
0503:                arg[1] = new Integer(0);
0504:
0505:                sendMessage(IMAGES_CHANGED, arg);
0506:
0507:                // If the user has set enable to true, then if the image is null
0508:                // turn off texture enable
0509:
0510:                if (userSpecifiedEnable) {
0511:                    enable = userSpecifiedEnable;
0512:                    for (i = baseLevel; i <= maximumLevel && enable; i++) {
0513:                        if (images[i] != null) {
0514:                            ImageComponentRetained img = (ImageComponentRetained) images[i].retained;
0515:                            if (img.isByReference()) {
0516:                                if (img.getRefImage(0) == null) {
0517:                                    enable = false;
0518:                                }
0519:                            } else {
0520:                                if (img.getImageData(isUseAsRaster()).get() == null) {
0521:                                    enable = false;
0522:                                }
0523:                            }
0524:                        }
0525:                    }
0526:                    if (!enable) {
0527:                        sendMessage(ENABLE_CHANGED, Boolean.FALSE);
0528:                    }
0529:                }
0530:            }
0531:
0532:            /**
0533:             * Gets a specified mipmap level.
0534:             * @param level mipmap level to get: 0 is the base level
0535:             * @return the pixel array object containing the texture image
0536:             * @exception RestrictedAccessException if the method is called
0537:             * when this object is part of live or compiled scene graph.
0538:             */
0539:            final ImageComponent getImage(int level) {
0540:                return (((images != null) && (images[0][level] != null)) ? (ImageComponent) images[0][level].source
0541:                        : null);
0542:            }
0543:
0544:            final ImageComponent[] getImages() {
0545:                if (images == null)
0546:                    return null;
0547:
0548:                ImageComponent[] rImages = new ImageComponent[images[0].length];
0549:                for (int i = 0; i < images[0].length; i++) {
0550:                    if (images[0][i] != null)
0551:                        rImages[i] = (ImageComponent) images[0][i].source;
0552:                    else
0553:                        rImages[i] = null;
0554:                }
0555:                return rImages;
0556:            }
0557:
0558:            /**
0559:             * Sets mipmap mode for texture mapping for this texture object.  
0560:             * @param mipMapMode the new mipmap mode for this object.  One of:
0561:             * BASE_LEVEL or MULTI_LEVEL_MIPMAP.
0562:             * @exception RestrictedAccessException if the method is called
0563:             */
0564:            final void initMipMapMode(int mipmapMode) {
0565:
0566:                if (this .mipmapMode == mipmapMode)
0567:                    return;
0568:
0569:                int prevMaxLevels = maxLevels; // previous maxLevels
0570:
0571:                this .mipmapMode = mipmapMode;
0572:
0573:                if (mipmapMode != Texture.BASE_LEVEL) {
0574:                    maxLevels = maxMipMapLevels;
0575:                } else {
0576:                    baseLevel = 0;
0577:                    maximumLevel = 0;
0578:                    maxLevels = 1;
0579:                }
0580:
0581:                ImageComponentRetained[][] newImages = new ImageComponentRetained[numFaces][maxLevels];
0582:
0583:                if (prevMaxLevels < maxLevels) {
0584:                    for (int f = 0; f < numFaces; f++) {
0585:                        for (int i = 0; i < prevMaxLevels; i++) {
0586:                            newImages[f][i] = images[f][i];
0587:                        }
0588:
0589:                        for (int j = prevMaxLevels; j < maxLevels; j++) {
0590:                            newImages[f][j] = null;
0591:                        }
0592:                    }
0593:                } else {
0594:                    for (int f = 0; f < numFaces; f++) {
0595:                        for (int i = 0; i < maxLevels; i++)
0596:                            newImages[f][i] = images[f][i];
0597:                    }
0598:                }
0599:                images = newImages;
0600:            }
0601:
0602:            /**
0603:             * Retrieves current mipmap mode.
0604:             * @return current mipmap mode of this texture object.
0605:             * @exception RestrictedAccessException if the method is called
0606:             */
0607:            final int getMipMapMode() {
0608:                return this .mipmapMode;
0609:            }
0610:
0611:            /**
0612:             * Enables or disables texture mapping for this
0613:             * appearance component object.
0614:             * @param state true or false to enable or disable texture mapping
0615:             */
0616:            final void initEnable(boolean state) {
0617:                userSpecifiedEnable = state;
0618:            }
0619:
0620:            /**
0621:             * Enables or disables texture mapping for this
0622:             * appearance component object and sends a 
0623:             * message notifying the interested structures of the change.
0624:             * @param state true or false to enable or disable texture mapping
0625:             */
0626:            final void setEnable(boolean state) {
0627:
0628:                initEnable(state);
0629:
0630:                if (state == enable) {
0631:                    // if enable flag is same as user specified one
0632:                    // this is only possible when enable is false
0633:                    // because one of the images is null and user specifies false
0634:                    return;
0635:                }
0636:
0637:                enable = state;
0638:
0639:                for (int j = 0; j < numFaces && enable; j++) {
0640:                    for (int i = baseLevel; i <= maximumLevel && enable; i++) {
0641:                        if (images[j][i].isByReference()) {
0642:                            if (images[j][i].getRefImage(0) == null) {
0643:                                enable = false;
0644:                            }
0645:                        } else {
0646:                            if (images[j][i].getImageData(isUseAsRaster())
0647:                                    .get() == null) {
0648:                                enable = false;
0649:                            }
0650:                        }
0651:                    }
0652:                }
0653:                sendMessage(ENABLE_CHANGED, (enable ? Boolean.TRUE
0654:                        : Boolean.FALSE));
0655:            }
0656:
0657:            /**
0658:             * Retrieves the state of the texture enable flag.
0659:             * @return true if texture mapping is enabled,
0660:             * false if texture mapping is disabled
0661:             */
0662:            final boolean getEnable() {
0663:                return userSpecifiedEnable;
0664:            }
0665:
0666:            final void initBaseLevel(int level) {
0667:                if ((level < 0) || (level > maximumLevel)) {
0668:                    throw new IllegalArgumentException(J3dI18N
0669:                            .getString("Texture36"));
0670:                }
0671:                baseLevel = level;
0672:            }
0673:
0674:            final void setBaseLevel(int level) {
0675:
0676:                if (level == baseLevel)
0677:                    return;
0678:
0679:                initBaseLevel(level);
0680:                sendMessage(BASE_LEVEL_CHANGED, new Integer(level));
0681:            }
0682:
0683:            final int getBaseLevel() {
0684:                return baseLevel;
0685:            }
0686:
0687:            final void initMaximumLevel(int level) {
0688:                if ((level < baseLevel) || (level >= maxMipMapLevels)) {
0689:                    throw new IllegalArgumentException(J3dI18N
0690:                            .getString("Texture37"));
0691:                }
0692:                if ((mipmapMode == Texture.BASE_LEVEL) && (level != 0)) {
0693:                    throw new IllegalArgumentException(J3dI18N
0694:                            .getString("Texture48"));
0695:                }
0696:
0697:                maximumLevel = level;
0698:            }
0699:
0700:            final void setMaximumLevel(int level) {
0701:
0702:                if (level == maximumLevel)
0703:                    return;
0704:
0705:                initMaximumLevel(level);
0706:                sendMessage(MAX_LEVEL_CHANGED, new Integer(level));
0707:            }
0708:
0709:            final int getMaximumLevel() {
0710:                return maximumLevel;
0711:            }
0712:
0713:            final void initMinimumLOD(float lod) {
0714:                if (lod > maximumLod) {
0715:                    throw new IllegalArgumentException(J3dI18N
0716:                            .getString("Texture42"));
0717:                }
0718:                minimumLod = lod;
0719:            }
0720:
0721:            final void setMinimumLOD(float lod) {
0722:                initMinimumLOD(lod);
0723:                sendMessage(MIN_LOD_CHANGED, new Float(lod));
0724:            }
0725:
0726:            final float getMinimumLOD() {
0727:                return minimumLod;
0728:            }
0729:
0730:            final void initMaximumLOD(float lod) {
0731:                if (lod < minimumLod) {
0732:                    throw new IllegalArgumentException(J3dI18N
0733:                            .getString("Texture42"));
0734:                }
0735:                maximumLod = lod;
0736:            }
0737:
0738:            final void setMaximumLOD(float lod) {
0739:                initMaximumLOD(lod);
0740:                sendMessage(MAX_LOD_CHANGED, new Float(lod));
0741:            }
0742:
0743:            final float getMaximumLOD() {
0744:                return maximumLod;
0745:            }
0746:
0747:            final void initLodOffset(float s, float t, float r) {
0748:                if (lodOffset == null) {
0749:                    lodOffset = new Point3f(s, t, r);
0750:                } else {
0751:                    lodOffset.set(s, t, r);
0752:                }
0753:            }
0754:
0755:            final void setLodOffset(float s, float t, float r) {
0756:                initLodOffset(s, t, r);
0757:                sendMessage(LOD_OFFSET_CHANGED, new Point3f(s, t, r));
0758:            }
0759:
0760:            final void getLodOffset(Tuple3f offset) {
0761:                if (lodOffset == null) {
0762:                    offset.set(0.0f, 0.0f, 0.0f);
0763:                } else {
0764:                    offset.set(lodOffset);
0765:                }
0766:            }
0767:
0768:            /**
0769:             * Sets the texture boundary color for this texture object.  The
0770:             * texture boundary color is used when boundaryModeS or boundaryModeT
0771:             * is set to CLAMP.
0772:             * @param boundaryColor the new texture boundary color.
0773:             */
0774:            final void initBoundaryColor(Color4f boundaryColor) {
0775:                this .boundaryColor.set(boundaryColor);
0776:            }
0777:
0778:            /**
0779:             * Sets the texture boundary color for this texture object.  The
0780:             * texture boundary color is used when boundaryModeS or boundaryModeT
0781:             * is set to CLAMP.
0782:             * @param r the red component of the color.
0783:             * @param g the green component of the color.
0784:             * @param b the blue component of the color.
0785:             * @param a the alpha component of the color.
0786:             */
0787:            final void initBoundaryColor(float r, float g, float b, float a) {
0788:                this .boundaryColor.set(r, g, b, a);
0789:            }
0790:
0791:            /**
0792:             * Retrieves the texture boundary color for this texture object.
0793:             * @param boundaryColor the vector that will receive the
0794:             * current texture boundary color.
0795:             */
0796:            final void getBoundaryColor(Color4f boundaryColor) {
0797:                boundaryColor.set(this .boundaryColor);
0798:            }
0799:
0800:            /**
0801:             * Set Anisotropic Filter
0802:             */
0803:            final void initAnisotropicFilterMode(int mode) {
0804:                anisotropicFilterMode = mode;
0805:            }
0806:
0807:            final int getAnisotropicFilterMode() {
0808:                return anisotropicFilterMode;
0809:            }
0810:
0811:            final void initAnisotropicFilterDegree(float degree) {
0812:                anisotropicFilterDegree = degree;
0813:            }
0814:
0815:            final float getAnisotropicFilterDegree() {
0816:                return anisotropicFilterDegree;
0817:            }
0818:
0819:            /**
0820:             * Set Sharpen Texture function
0821:             */
0822:            final void initSharpenTextureFunc(float[] lod, float[] pts) {
0823:                if (lod == null) { // pts will be null too.
0824:                    sharpenTextureFuncPts = null;
0825:                    numSharpenTextureFuncPts = 0;
0826:                } else {
0827:                    numSharpenTextureFuncPts = lod.length;
0828:                    if ((sharpenTextureFuncPts == null)
0829:                            || (sharpenTextureFuncPts.length != lod.length * 2)) {
0830:                        sharpenTextureFuncPts = new float[lod.length * 2];
0831:                    }
0832:                    for (int i = 0, j = 0; i < lod.length; i++) {
0833:                        sharpenTextureFuncPts[j++] = lod[i];
0834:                        sharpenTextureFuncPts[j++] = pts[i];
0835:                    }
0836:                }
0837:            }
0838:
0839:            final void initSharpenTextureFunc(Point2f[] pts) {
0840:                if (pts == null) {
0841:                    sharpenTextureFuncPts = null;
0842:                    numSharpenTextureFuncPts = 0;
0843:                } else {
0844:                    numSharpenTextureFuncPts = pts.length;
0845:                    if ((sharpenTextureFuncPts == null)
0846:                            || (sharpenTextureFuncPts.length != pts.length * 2)) {
0847:                        sharpenTextureFuncPts = new float[pts.length * 2];
0848:                    }
0849:                    for (int i = 0, j = 0; i < pts.length; i++) {
0850:                        sharpenTextureFuncPts[j++] = pts[i].x;
0851:                        sharpenTextureFuncPts[j++] = pts[i].y;
0852:                    }
0853:                }
0854:            }
0855:
0856:            final void initSharpenTextureFunc(float[] pts) {
0857:                if (pts == null) {
0858:                    sharpenTextureFuncPts = null;
0859:                    numSharpenTextureFuncPts = 0;
0860:                } else {
0861:                    numSharpenTextureFuncPts = pts.length / 2;
0862:                    if ((sharpenTextureFuncPts == null)
0863:                            || (sharpenTextureFuncPts.length != pts.length)) {
0864:                        sharpenTextureFuncPts = new float[pts.length];
0865:                    }
0866:                    for (int i = 0; i < pts.length; i++) {
0867:                        sharpenTextureFuncPts[i] = pts[i];
0868:                    }
0869:                }
0870:            }
0871:
0872:            /**
0873:             * Get number of points in the sharpen texture LOD function
0874:             */
0875:            final int getSharpenTextureFuncPointsCount() {
0876:                return numSharpenTextureFuncPts;
0877:            }
0878:
0879:            /**
0880:             * Copies the array of sharpen texture LOD function points into the
0881:             * specified arrays
0882:             */
0883:            final void getSharpenTextureFunc(float[] lod, float[] pts) {
0884:                if (sharpenTextureFuncPts != null) {
0885:                    for (int i = 0, j = 0; i < numSharpenTextureFuncPts; i++) {
0886:                        lod[i] = sharpenTextureFuncPts[j++];
0887:                        pts[i] = sharpenTextureFuncPts[j++];
0888:                    }
0889:                }
0890:            }
0891:
0892:            final void getSharpenTextureFunc(Point2f[] pts) {
0893:                if (sharpenTextureFuncPts != null) {
0894:                    for (int i = 0, j = 0; i < numSharpenTextureFuncPts; i++) {
0895:                        pts[i].x = sharpenTextureFuncPts[j++];
0896:                        pts[i].y = sharpenTextureFuncPts[j++];
0897:                    }
0898:                }
0899:            }
0900:
0901:            final void initFilter4Func(float[] weights) {
0902:                if (weights == null) {
0903:                    filter4FuncPts = null;
0904:                } else {
0905:                    if ((filter4FuncPts == null)
0906:                            || (filter4FuncPts.length != weights.length)) {
0907:                        filter4FuncPts = new float[weights.length];
0908:                    }
0909:                    for (int i = 0; i < weights.length; i++) {
0910:                        filter4FuncPts[i] = weights[i];
0911:                    }
0912:                }
0913:            }
0914:
0915:            final int getFilter4FuncPointsCount() {
0916:                if (filter4FuncPts == null) {
0917:                    return 0;
0918:                } else {
0919:                    return filter4FuncPts.length;
0920:                }
0921:            }
0922:
0923:            final void getFilter4Func(float[] weights) {
0924:                if (filter4FuncPts != null) {
0925:                    for (int i = 0; i < filter4FuncPts.length; i++) {
0926:                        weights[i] = filter4FuncPts[i];
0927:                    }
0928:                }
0929:            }
0930:
0931:            /**
0932:             * internal method only -- returns internal function points
0933:             */
0934:            final float[] getSharpenTextureFunc() {
0935:                return sharpenTextureFuncPts;
0936:            }
0937:
0938:            final float[] getFilter4Func() {
0939:                return filter4FuncPts;
0940:            }
0941:
0942:            void setLive(boolean backgroundGroup, int refCount) {
0943:
0944:                // This line should be assigned before calling doSetLive, so that
0945:                // the mirror object's enable is assigned correctly!
0946:                enable = userSpecifiedEnable;
0947:
0948:                super .doSetLive(backgroundGroup, refCount);
0949:
0950:                // XXXX: for now, do setLive for all the defined images.
0951:                // But in theory, we only need to setLive those within the
0952:                // baseLevel and maximumLevel range. But then we'll need
0953:                // setLive and clearLive image when the range changes.
0954:
0955:                if (images != null) {
0956:
0957:                    for (int j = 0; j < numFaces; j++) {
0958:                        for (int i = 0; i < maxLevels; i++) {
0959:                            if (images[j][i] == null) {
0960:                                throw new IllegalArgumentException(J3dI18N
0961:                                        .getString("TextureRetained3")
0962:                                        + i);
0963:                            }
0964:                            images[j][i].setLive(backgroundGroup, refCount);
0965:                        }
0966:                    }
0967:                }
0968:
0969:                // Issue 172 : assertion check the sizes of the images after we have
0970:                // checked for all mipmap levels being set
0971:                if (images != null) {
0972:                    for (int j = 0; j < numFaces; j++) {
0973:                        checkSizes(images[j]);
0974:                    }
0975:                }
0976:
0977:                // Send a message to Rendering Attr stucture to update the resourceMask
0978:                J3dMessage createMessage = new J3dMessage();
0979:                createMessage.threads = J3dThread.UPDATE_RENDERING_ATTRIBUTES;
0980:                createMessage.type = J3dMessage.TEXTURE_CHANGED;
0981:                createMessage.args[0] = this ;
0982:                createMessage.args[1] = new Integer(UPDATE_IMAGE);
0983:                createMessage.args[2] = null;
0984:                createMessage.args[3] = new Integer(changedFrequent);
0985:                VirtualUniverse.mc.processMessage(createMessage);
0986:
0987:                // If the user has set enable to true, then if the image is null
0988:                // turn off texture enable
0989:                if (userSpecifiedEnable) {
0990:                    if (images != null) {
0991:                        for (int j = 0; j < numFaces && enable; j++) {
0992:                            for (int i = baseLevel; i <= maximumLevel && enable; i++) {
0993:                                if (images[j][i].isByReference()) {
0994:                                    if (images[j][i].getRefImage(0) == null) {
0995:                                        enable = false;
0996:                                    }
0997:                                } else {
0998:                                    if (images[j][i].getImageData(
0999:                                            isUseAsRaster()).get() == null) {
1000:                                        enable = false;
1001:                                    }
1002:                                }
1003:                            }
1004:                        }
1005:                    } else {
1006:                        enable = false;
1007:                    }
1008:                    if (!enable)
1009:                        sendMessage(ENABLE_CHANGED, Boolean.FALSE);
1010:                }
1011:
1012:                super .markAsLive();
1013:            }
1014:
1015:            void clearLive(int refCount) {
1016:                super .clearLive(refCount);
1017:
1018:                if (images != null) {
1019:                    for (int j = 0; j < numFaces; j++) {
1020:                        for (int i = 0; i < maxLevels; i++) {
1021:                            images[j][i].clearLive(refCount);
1022:                            images[j][i].removeUser(mirror);
1023:                        }
1024:                    }
1025:                }
1026:            }
1027:
1028:            /*
1029:             * The following methods update the native context.
1030:             * The implementation for Texture2D happens here.
1031:             * Texture3D and TextureCubeMap implement their own versions.
1032:             */
1033:
1034:            void bindTexture(Context ctx, int objectId, boolean enable) {
1035:                Pipeline.getPipeline().bindTexture2D(ctx, objectId, enable);
1036:            }
1037:
1038:            void updateTextureBoundary(Context ctx, int boundaryModeS,
1039:                    int boundaryModeT, float boundaryRed, float boundaryGreen,
1040:                    float boundaryBlue, float boundaryAlpha) {
1041:
1042:                Pipeline.getPipeline().updateTexture2DBoundary(ctx,
1043:                        boundaryModeS, boundaryModeT, boundaryRed,
1044:                        boundaryGreen, boundaryBlue, boundaryAlpha);
1045:            }
1046:
1047:            void updateTextureFilterModes(Context ctx, int minFilter,
1048:                    int magFilter) {
1049:
1050:                Pipeline.getPipeline().updateTexture2DFilterModes(ctx,
1051:                        minFilter, magFilter);
1052:            }
1053:
1054:            void updateTextureSharpenFunc(Context ctx,
1055:                    int numSharpenTextureFuncPts, float[] sharpenTextureFuncPts) {
1056:
1057:                Pipeline.getPipeline().updateTexture2DSharpenFunc(ctx,
1058:                        numSharpenTextureFuncPts, sharpenTextureFuncPts);
1059:            }
1060:
1061:            void updateTextureFilter4Func(Context ctx, int numFilter4FuncPts,
1062:                    float[] filter4FuncPts) {
1063:
1064:                Pipeline.getPipeline().updateTexture2DFilter4Func(ctx,
1065:                        numFilter4FuncPts, filter4FuncPts);
1066:            }
1067:
1068:            void updateTextureAnisotropicFilter(Context ctx, float degree) {
1069:                Pipeline.getPipeline().updateTexture2DAnisotropicFilter(ctx,
1070:                        degree);
1071:            }
1072:
1073:            void updateTextureLodRange(Context ctx, int baseLevel,
1074:                    int maximumLevel, float minimumLod, float maximumLod) {
1075:
1076:                Pipeline.getPipeline().updateTexture2DLodRange(ctx, baseLevel,
1077:                        maximumLevel, minimumLod, maximumLod);
1078:            }
1079:
1080:            void updateTextureLodOffset(Context ctx, float lodOffsetX,
1081:                    float lodOffsetY, float lodOffsetZ) {
1082:
1083:                Pipeline.getPipeline().updateTexture2DLodOffset(ctx,
1084:                        lodOffsetX, lodOffsetY, lodOffsetZ);
1085:            }
1086:
1087:            // get an ID for Texture 2D 
1088:            int getTextureId() {
1089:                return (VirtualUniverse.mc.getTexture2DId());
1090:            }
1091:
1092:            // free a Texture2D id
1093:            void freeTextureId(int id) {
1094:                synchronized (resourceLock) {
1095:                    if (objectId == id) {
1096:                        objectId = -1;
1097:                        VirtualUniverse.mc.freeTexture2DId(id);
1098:                    }
1099:                }
1100:            }
1101:
1102:            private boolean isEnabled(Canvas3D cv) {
1103:                if (widthOrHeightIsNPOT
1104:                        && !isUseAsRaster()
1105:                        && ((cv.textureExtendedFeatures & Canvas3D.TEXTURE_NON_POWER_OF_TWO) == 0)) {
1106:                    return false;
1107:                }
1108:                return enable;
1109:            }
1110:
1111:            // bind a named texture to a texturing target
1112:            void bindTexture(Canvas3D cv) {
1113:
1114:                synchronized (resourceLock) {
1115:                    if (objectId == -1) {
1116:                        objectId = getTextureId();
1117:                    }
1118:                    cv.addTextureResource(objectId, this );
1119:                }
1120:                bindTexture(cv.ctx, objectId, isEnabled(cv));
1121:            }
1122:
1123:            /**
1124:             * load level 0 explicitly with null pointer to enable
1125:             * mipmapping when level 0 is not the base level
1126:             */
1127:            void updateTextureDimensions(Canvas3D cv) {
1128:                if (images[0][0] != null) {
1129:                    updateTextureImage(cv, 0, maxLevels, 0, format,
1130:                            images[0][0].getImageFormatTypeIntValue(false),
1131:                            width, height, boundaryWidth, images[0][0]
1132:                                    .getImageDataTypeIntValue(), null);
1133:                }
1134:            }
1135:
1136:            void updateTextureLOD(Canvas3D cv) {
1137:
1138:                if ((cv.textureExtendedFeatures & Canvas3D.TEXTURE_LOD_RANGE) != 0) {
1139:
1140:                    int max = 0;
1141:                    if (mipmapMode == Texture.BASE_LEVEL) {
1142:                        max = maxMipMapLevels;
1143:                    } else {
1144:                        max = maximumLevel;
1145:                    }
1146:
1147:                    updateTextureLodRange(cv.ctx, baseLevel, max, minimumLod,
1148:                            maximumLod);
1149:                }
1150:
1151:                if ((lodOffset != null)
1152:                        && ((cv.textureExtendedFeatures & Canvas3D.TEXTURE_LOD_OFFSET) != 0)) {
1153:                    updateTextureLodOffset(cv.ctx, lodOffset.x, lodOffset.y,
1154:                            lodOffset.z);
1155:                }
1156:            }
1157:
1158:            void updateTextureBoundary(Canvas3D cv) {
1159:                updateTextureBoundary(cv.ctx, boundaryModeS, boundaryModeT,
1160:                        boundaryColor.x, boundaryColor.y, boundaryColor.z,
1161:                        boundaryColor.w);
1162:            }
1163:
1164:            void updateTextureFields(Canvas3D cv) {
1165:
1166:                int magnificationFilter = magFilter;
1167:                int minificationFilter = minFilter;
1168:
1169:                // update sharpen texture function if applicable
1170:
1171:                if ((magnificationFilter >= Texture.LINEAR_SHARPEN)
1172:                        && (magnificationFilter <= Texture.LINEAR_SHARPEN_ALPHA)) {
1173:
1174:                    if ((cv.textureExtendedFeatures & Canvas3D.TEXTURE_SHARPEN) != 0) {
1175:
1176:                        // send down sharpen texture LOD function
1177:                        //
1178:                        updateTextureSharpenFunc(cv.ctx,
1179:                                numSharpenTextureFuncPts, sharpenTextureFuncPts);
1180:
1181:                    } else {
1182:
1183:                        // sharpen texture is not supported by the underlying
1184:                        // library, fallback to BASE_LEVEL_LINEAR
1185:
1186:                        magnificationFilter = Texture.BASE_LEVEL_LINEAR;
1187:                    }
1188:                } else if ((magnificationFilter >= Texture2D.LINEAR_DETAIL)
1189:                        && (magnificationFilter <= Texture2D.LINEAR_DETAIL_ALPHA)) {
1190:                    if ((cv.textureExtendedFeatures & Canvas3D.TEXTURE_DETAIL) == 0) {
1191:
1192:                        // detail texture is not supported by the underlying
1193:                        // library, fallback to BASE_LEVEL_LINEAR
1194:
1195:                        magnificationFilter = Texture.BASE_LEVEL_LINEAR;
1196:                    }
1197:                }
1198:
1199:                if (minificationFilter == Texture.FILTER4
1200:                        || magnificationFilter == Texture.FILTER4) {
1201:
1202:                    boolean noFilter4 = false;
1203:
1204:                    if ((cv.textureExtendedFeatures & Canvas3D.TEXTURE_FILTER4) != 0) {
1205:
1206:                        if (filter4FuncPts == null) {
1207:
1208:                            // filter4 function is not defined, 
1209:                            // fallback to BASE_LEVEL_LINEAR
1210:
1211:                            noFilter4 = true;
1212:                        } else {
1213:                            updateTextureFilter4Func(cv.ctx,
1214:                                    filter4FuncPts.length, filter4FuncPts);
1215:                        }
1216:                    } else {
1217:
1218:                        // filter4 is not supported by the underlying
1219:                        // library, fallback to BASE_LEVEL_LINEAR
1220:
1221:                        noFilter4 = true;
1222:                    }
1223:
1224:                    if (noFilter4) {
1225:                        if (minificationFilter == Texture.FILTER4) {
1226:                            minificationFilter = Texture.BASE_LEVEL_LINEAR;
1227:                        }
1228:                        if (magnificationFilter == Texture.FILTER4) {
1229:                            magnificationFilter = Texture.BASE_LEVEL_LINEAR;
1230:                        }
1231:                    }
1232:                }
1233:
1234:                // Fallback to BASE mode if hardware mipmap generation is not supported.
1235:                if ((mipmapMode == Texture.BASE_LEVEL)
1236:                        && ((cv.textureExtendedFeatures & Canvas3D.TEXTURE_AUTO_MIPMAP_GENERATION) == 0)) {
1237:
1238:                    if (minificationFilter == Texture.NICEST
1239:                            || minificationFilter == Texture.MULTI_LEVEL_LINEAR) {
1240:                        minificationFilter = Texture.BASE_LEVEL_LINEAR;
1241:                    } else if (minificationFilter == Texture.MULTI_LEVEL_POINT) {
1242:                        minificationFilter = Texture.BASE_LEVEL_POINT;
1243:                    }
1244:                }
1245:
1246:                // update texture filtering modes
1247:                updateTextureFilterModes(cv.ctx, minificationFilter,
1248:                        magnificationFilter);
1249:
1250:                if ((cv.textureExtendedFeatures & Canvas3D.TEXTURE_ANISOTROPIC_FILTER) != 0) {
1251:                    if (anisotropicFilterMode == Texture.ANISOTROPIC_NONE) {
1252:                        updateTextureAnisotropicFilter(cv.ctx, 1.0f);
1253:                    } else {
1254:                        updateTextureAnisotropicFilter(cv.ctx,
1255:                                anisotropicFilterDegree);
1256:                    }
1257:                }
1258:
1259:                // update texture boundary modes, boundary color
1260:
1261:                updateTextureBoundary(cv);
1262:
1263:            }
1264:
1265:            // Wrapper around the native call for 2D textures; overridden for
1266:            // TextureCureMap
1267:            void updateTextureImage(Canvas3D cv, int face, int numLevels,
1268:                    int level, int textureFormat, int imageFormat, int width,
1269:                    int height, int boundaryWidth, int imageDataType,
1270:                    Object data) {
1271:
1272:                Pipeline.getPipeline().updateTexture2DImage(cv.ctx, numLevels,
1273:                        level, textureFormat, imageFormat, width, height,
1274:                        boundaryWidth, imageDataType, data,
1275:                        useAutoMipMapGeneration(cv));
1276:            }
1277:
1278:            // Wrapper around the native call for 2D textures; overridden for
1279:            // TextureCureMap
1280:            void updateTextureSubImage(Canvas3D cv, int face, int level,
1281:                    int xoffset, int yoffset, int textureFormat,
1282:                    int imageFormat, int imgXOffset, int imgYOffset, int tilew,
1283:                    int width, int height, int imageDataType, Object data) {
1284:
1285:                Pipeline.getPipeline().updateTexture2DSubImage(cv.ctx, level,
1286:                        xoffset, yoffset, textureFormat, imageFormat,
1287:                        imgXOffset, imgYOffset, tilew, width, height,
1288:                        imageDataType, data, useAutoMipMapGeneration(cv));
1289:            }
1290:
1291:            /**
1292:             * reloadTextureImage is used to load a particular level of image
1293:             * This method needs to take care of RenderedImage as well as
1294:             * BufferedImage
1295:             */
1296:            void reloadTextureImage(Canvas3D cv, int face, int level,
1297:                    ImageComponentRetained image, int numLevels) {
1298:
1299:                boolean useAsRaster = isUseAsRaster();
1300:                ImageComponentRetained.ImageData imageData = image
1301:                        .getImageData(useAsRaster);
1302:
1303:                assert imageData != null;
1304:
1305:                updateTextureImage(cv, face, numLevels, level, format, image
1306:                        .getImageFormatTypeIntValue(useAsRaster), imageData
1307:                        .getWidth(), imageData.getHeight(), boundaryWidth,
1308:                        image.getImageDataTypeIntValue(), imageData.get());
1309:
1310:                // TODO : Dead code - need to clean up for 1.6
1311:                // Now take care of the RenderedImage (byRef and yUp) case. Note, if image
1312:                // is a RenderedImage ( byRef and yUp), then imageData will be null
1313:
1314:                if (imageData == null) {
1315:                    //		    System.err.println("==========. subImage");
1316:                    // Download all the tiles for this texture
1317:                    int xoffset = 0, yoffset = 0;
1318:                    int tmpw = image.width;
1319:                    int tmph = image.height;
1320:                    int endXTile = image.tilew;
1321:                    int endYTile = image.tileh;
1322:                    int curw = endXTile;
1323:                    int curh = endYTile;
1324:
1325:                    if (tmpw < curw) {
1326:                        curw = tmpw;
1327:                    }
1328:
1329:                    if (tmph < curh) {
1330:                        curh = tmph;
1331:                    }
1332:
1333:                    int startw = curw;
1334:                    int imageXOffset = image.tilew - curw;
1335:                    int imageYOffset = image.tileh - curh;
1336:                    for (int m = 0; m < image.numYTiles; m++) {
1337:                        xoffset = 0;
1338:                        tmpw = width;
1339:                        curw = startw;
1340:                        imageXOffset = image.tilew - curw;
1341:                        for (int n = 0; n < image.numXTiles; n++) {
1342:                            java.awt.image.Raster ras;
1343:                            ras = ((RenderedImage) image.getRefImage(0))
1344:                                    .getTile(n, m);
1345:                            byte[] data = ((DataBufferByte) ras.getDataBuffer())
1346:                                    .getData();
1347:                            updateTextureSubImage(
1348:                                    cv,
1349:                                    face,
1350:                                    level,
1351:                                    xoffset,
1352:                                    yoffset,
1353:                                    format,
1354:                                    image.getImageFormatTypeIntValue(false),
1355:                                    imageXOffset,
1356:                                    imageYOffset,
1357:                                    image.tilew,
1358:                                    curw,
1359:                                    curh,
1360:                                    ImageComponentRetained.IMAGE_DATA_TYPE_BYTE_ARRAY,
1361:                                    (Object) data);
1362:                            xoffset += curw;
1363:                            imageXOffset = 0;
1364:                            tmpw -= curw;
1365:                            if (tmpw < image.tilew)
1366:                                curw = tmpw;
1367:                            else
1368:                                curw = image.tilew;
1369:                        }
1370:                        yoffset += curh;
1371:                        imageYOffset = 0;
1372:                        tmph -= curh;
1373:                        if (tmph < image.tileh)
1374:                            curh = tmph;
1375:                        else
1376:                            curh = image.tileh;
1377:                    }
1378:                }
1379:            }
1380:
1381:            /**
1382:             * update a subregion of the texture image
1383:             * This method needs to take care of RenderedImage as well as
1384:             * BufferedImage
1385:             */
1386:            void reloadTextureSubImage(Canvas3D cv, int face, int level,
1387:                    ImageComponentUpdateInfo info, ImageComponentRetained image) {
1388:
1389:                int x = info.x, y = info.y, width = info.width, height = info.height;
1390:
1391:                //The x and y here specifies the subregion of the imageData of
1392:                //the associated RenderedImage.
1393:
1394:                //System.err.println("\nupdateTextureSubImage: x= " + x + " y= " + y +
1395:                //			" width= " + width + " height= " + height +
1396:                //			" format= " + format);
1397:
1398:                ImageComponentRetained.ImageData imageData = image
1399:                        .getImageData(isUseAsRaster());
1400:                if (imageData != null) {
1401:                    int xoffset = x;
1402:                    int yoffset = y;
1403:
1404:                    // TODO Check this logic : If !yUp adjust yoffset
1405:                    if (!image.yUp) {
1406:                        yoffset = image.height - yoffset - height;
1407:                    }
1408:
1409:                    updateTextureSubImage(cv, face, level, xoffset, yoffset,
1410:                            format, image.getImageFormatTypeIntValue(false),
1411:                            xoffset, yoffset, image.width, width, height, image
1412:                                    .getImageDataTypeIntValue(), imageData
1413:                                    .get());
1414:
1415:                } else {
1416:
1417:                    assert false;
1418:
1419:                    // TODO : Dead code - need to clean up for 1.6
1420:                    // System.err.println("RenderedImage subImage update");
1421:                    // determine the first tile of the image
1422:
1423:                    float mt;
1424:                    int minTileX, minTileY;
1425:
1426:                    int rx = x;
1427:                    int ry = y;
1428:
1429:                    mt = (float) (rx) / (float) image.tilew;
1430:                    if (mt < 0) {
1431:                        minTileX = (int) (mt - 1);
1432:                    } else {
1433:                        minTileX = (int) mt;
1434:                    }
1435:
1436:                    mt = (float) (ry) / (float) image.tileh;
1437:                    if (mt < 0) {
1438:                        minTileY = (int) (mt - 1);
1439:                    } else {
1440:                        minTileY = (int) mt;
1441:                    }
1442:
1443:                    // determine the pixel offset of the upper-left corner of the
1444:                    // first tile
1445:                    int startXTile = minTileX * image.tilew;
1446:                    int startYTile = minTileY * image.tilew;
1447:
1448:                    // image dimension in the first tile
1449:
1450:                    int curw = (startXTile + image.tilew - rx);
1451:                    int curh = (startYTile + image.tileh - ry);
1452:
1453:                    // check if the to-be-copied region is less than the tile image
1454:                    // if so, update the to-be-copied dimension of this tile
1455:
1456:                    if (curw > width) {
1457:                        curw = width;
1458:                    }
1459:
1460:                    if (curh > height) {
1461:                        curh = height;
1462:                    }
1463:
1464:                    // save the to-be-copied width of the left most tile
1465:
1466:                    int startw = curw;
1467:
1468:                    // temporary variable for dimension of the to-be-copied region
1469:
1470:                    int tmpw = width;
1471:                    int tmph = height;
1472:
1473:                    // offset of the first pixel of the tile to be copied; offset is
1474:                    // relative to the upper left corner of the title
1475:
1476:                    int imgX = rx - startXTile;
1477:                    int imgY = ry - startYTile;
1478:
1479:                    // determine the number of tiles in each direction that the
1480:                    // image spans
1481:
1482:                    int numXTiles = (width + imgX) / image.tilew;
1483:                    int numYTiles = (height + imgY) / image.tileh;
1484:
1485:                    if (((float) (width + imgX) % (float) image.tilew) > 0) {
1486:                        numXTiles += 1;
1487:                    }
1488:
1489:                    if (((float) (height + imgY) % (float) image.tileh) > 0) {
1490:                        numYTiles += 1;
1491:                    }
1492:
1493:                    java.awt.image.Raster ras;
1494:
1495:                    int textureX = x; // x offset in the texture 
1496:                    int textureY = y; // y offset in the texture 
1497:
1498:                    for (int yTile = minTileY; yTile < minTileY + numYTiles; yTile++) {
1499:
1500:                        tmpw = width;
1501:                        curw = startw;
1502:                        imgX = rx - startXTile;
1503:
1504:                        for (int xTile = minTileX; xTile < minTileX + numXTiles; xTile++) {
1505:                            ras = ((RenderedImage) image.getRefImage(0))
1506:                                    .getTile(xTile, yTile);
1507:                            byte[] data = ((DataBufferByte) ras.getDataBuffer())
1508:                                    .getData();
1509:
1510:                            updateTextureSubImage(
1511:                                    cv,
1512:                                    face,
1513:                                    level,
1514:                                    textureX,
1515:                                    textureY,
1516:                                    format,
1517:                                    image.getImageFormatTypeIntValue(false),
1518:                                    imgX,
1519:                                    imgY,
1520:                                    image.tilew,
1521:                                    curw,
1522:                                    curh,
1523:                                    ImageComponentRetained.IMAGE_DATA_TYPE_BYTE_ARRAY,
1524:                                    (Object) data);
1525:
1526:                            // move to the next tile in x direction
1527:
1528:                            textureX += curw;
1529:                            imgX = 0;
1530:
1531:                            // determine the width of copy region of the next tile
1532:
1533:                            tmpw -= curw;
1534:                            if (tmpw < image.tilew) {
1535:                                curw = tmpw;
1536:                            } else {
1537:                                curw = image.tilew;
1538:                            }
1539:                        }
1540:
1541:                        // move to the next set of tiles in y direction
1542:                        textureY += curh;
1543:                        imgY = 0;
1544:
1545:                        // determine the height of copy region for the next set
1546:                        // of tiles
1547:                        tmph -= curh;
1548:                        if (tmph < image.tileh) {
1549:                            curh = tmph;
1550:                        } else {
1551:                            curh = image.tileh;
1552:                        }
1553:                    }
1554:                }
1555:            }
1556:
1557:            // reload texture mipmap
1558:
1559:            void reloadTexture(Canvas3D cv) {
1560:
1561:                int blevel, mlevel;
1562:
1563:                //System.err.println("reloadTexture: baseLevel= " + baseLevel +
1564:                //			" maximumLevel= " + maximumLevel);
1565:
1566:                if ((cv.textureExtendedFeatures & Canvas3D.TEXTURE_LOD_RANGE) == 0) {
1567:                    blevel = 0;
1568:                    mlevel = maxLevels - 1;
1569:                } else {
1570:                    blevel = baseLevel;
1571:                    mlevel = maximumLevel;
1572:                }
1573:
1574:                if (blevel != 0) {
1575:                    // level 0 is not the base level, hence, need
1576:                    // to load level 0 explicitly with a null pointer in order 
1577:                    // for mipmapping to be active. 
1578:
1579:                    updateTextureDimensions(cv);
1580:                }
1581:
1582:                for (int j = 0; j < numFaces; j++) {
1583:                    for (int i = blevel; i <= mlevel; i++) {
1584:
1585:                        // it is possible to have null pointer if only a subset
1586:                        // of mipmap levels is defined but the canvas does not
1587:                        // support lod_range extension
1588:
1589:                        ImageComponentRetained image = images[j][i];
1590:                        if (image != null) {
1591:                            // Issue 366: call evaluateExtensions, since it may not
1592:                            // have been called yet in all cases
1593:                            image.evaluateExtensions(cv);
1594:                            reloadTextureImage(cv, j, i, image, maxLevels);
1595:                        }
1596:                    }
1597:                }
1598:            }
1599:
1600:            // update texture mipmap based on the imageUpdateInfo
1601:
1602:            void updateTexture(Canvas3D cv, int resourceBit) {
1603:
1604:                //System.err.println("updateTexture\n");
1605:
1606:                ImageComponentUpdateInfo info;
1607:
1608:                for (int k = 0; k < numFaces; k++) {
1609:                    for (int i = baseLevel; i <= maximumLevel; i++) {
1610:                        if (imageUpdateInfo[k][i] != null) {
1611:                            for (int j = 0; j < imageUpdateInfo[k][i].size(); j++) {
1612:
1613:                                info = (ImageComponentUpdateInfo) imageUpdateInfo[k][i]
1614:                                        .get(j);
1615:
1616:                                synchronized (resourceLock) {
1617:
1618:                                    // if this info is updated, move on to the next one
1619:
1620:                                    if ((info.updateMask & resourceBit) == 0)
1621:                                        continue;
1622:
1623:                                    // check if all canvases have processed this update
1624:                                    info.updateMask &= ~resourceBit;
1625:
1626:                                    // all the current resources have updated this
1627:                                    // info, so this info can be removed from the
1628:                                    // update list
1629:                                    if ((info.updateMask & resourceCreationMask) == 0) {
1630:                                        info.updateMask = 0; // mark this update as
1631:                                        // done
1632:
1633:                                        // mark the prune flag so as to prune the
1634:                                        // update list next time when the update 
1635:                                        // list is to be modified.
1636:                                        // Don't want to clean up the list at 
1637:                                        // rendering time because (1) MT issue,
1638:                                        // other renderer could be processing
1639:                                        // the update list now;
1640:                                        // (2) takes up rendering time.
1641:                                        if (imageUpdatePruneMask == null) {
1642:                                            imageUpdatePruneMask = new int[numFaces];
1643:                                        }
1644:                                        imageUpdatePruneMask[k] = 1 << i;
1645:                                    }
1646:                                }
1647:
1648:                                if (info.entireImage == true) {
1649:                                    reloadTextureImage(cv, k, i, images[k][i],
1650:                                            maxLevels);
1651:                                } else {
1652:                                    reloadTextureSubImage(cv, k, i, info,
1653:                                            images[k][i]);
1654:                                }
1655:
1656:                            }
1657:                        }
1658:                    }
1659:                }
1660:            }
1661:
1662:            /**
1663:             * reloadTextureSharedContext is called to reload texture
1664:             * on a shared context. It is invoked from the Renderer
1665:             * before traversing the RenderBin. The idea is to reload
1666:             * all necessary textures up front for all shared contexts
1667:             * in order to minimize the context switching overhead.
1668:             */
1669:            void reloadTextureSharedContext(Canvas3D cv) {
1670:
1671:                // if texture is not enabled, don't bother downloading the
1672:                // the texture state
1673:
1674:                if (!isEnabled(cv)) {
1675:                    return;
1676:                }
1677:
1678:                bindTexture(cv);
1679:
1680:                // reload all levels of texture image
1681:
1682:                // update texture parameters such as boundary modes, filtering
1683:
1684:                updateTextureFields(cv);
1685:
1686:                // update texture Lod parameters
1687:
1688:                updateTextureLOD(cv);
1689:
1690:                // update all texture images
1691:
1692:                reloadTexture(cv);
1693:
1694:                synchronized (resourceLock) {
1695:                    resourceCreationMask |= cv.screen.renderer.rendererBit;
1696:                    resourceUpdatedMask |= cv.screen.renderer.rendererBit;
1697:                    resourceLodUpdatedMask |= cv.screen.renderer.rendererBit;
1698:                    resourceInReloadList &= ~cv.screen.renderer.rendererBit;
1699:                }
1700:            }
1701:
1702:            /**
1703:             * updateNative is called while traversing the RenderBin to 
1704:             * update the texture state
1705:             */
1706:            void updateNative(Canvas3D cv) {
1707:                boolean reloadTexture = false; // true - reload all levels of texture
1708:                boolean updateTexture = false; // true - update a portion of texture
1709:                boolean updateTextureLod = false; // true - update texture Lod info
1710:
1711:                //System.err.println("Texture/updateNative: " + this + "object= " + objectId + " enable= " + enable);
1712:
1713:                bindTexture(cv);
1714:
1715:                // if texture is not enabled, don't bother downloading the
1716:                // the texture state
1717:
1718:                if (!isEnabled(cv)) {
1719:                    return;
1720:                }
1721:
1722:                if (cv.useSharedCtx && cv.screen.renderer.sharedCtx != null) {
1723:
1724:                    if ((resourceCreationMask & cv.screen.renderer.rendererBit) == 0) {
1725:                        reloadTexture = true;
1726:                    } else {
1727:                        if (((resourceUpdatedMask & cv.screen.renderer.rendererBit) == 0)
1728:                                && (imageUpdateInfo != null)) {
1729:                            updateTexture = true;
1730:                        }
1731:
1732:                        if ((resourceLodUpdatedMask & cv.screen.renderer.rendererBit) == 0) {
1733:                            updateTextureLod = true;
1734:                        }
1735:                    }
1736:                    if (reloadTexture || updateTexture || updateTextureLod) {
1737:                        cv.makeCtxCurrent(cv.screen.renderer.sharedCtx);
1738:                        bindTexture(cv);
1739:                    }
1740:                } else {
1741:                    if ((resourceCreationMask & cv.canvasBit) == 0) {
1742:                        reloadTexture = true;
1743:                    } else {
1744:                        if (((resourceUpdatedMask & cv.canvasBit) == 0)
1745:                                && (imageUpdateInfo != null)) {
1746:                            updateTexture = true;
1747:                        }
1748:
1749:                        if ((resourceLodUpdatedMask & cv.canvasBit) == 0) {
1750:                            updateTextureLod = true;
1751:                        }
1752:                    }
1753:                }
1754:
1755:                if (VirtualUniverse.mc.isD3D()) {
1756:                    if (texTimestamp != VirtualUniverse.mc.resendTexTimestamp) {
1757:                        texTimestamp = VirtualUniverse.mc.resendTexTimestamp;
1758:                        reloadTexture = true;
1759:                    }
1760:
1761:                    if (!reloadTexture) {
1762:                        // D3D didn't store texture properties during Texture binding
1763:                        updateTextureFields(cv);
1764:                    }
1765:                }
1766:
1767:                //System.err.println("......... reloadTexture= " + reloadTexture +
1768:                //		 " updateTexture= " + updateTexture + 
1769:                //		 " updateTextureLod= " + updateTextureLod);
1770:
1771:                //System.err.println("......... resourceCreationMask= " + resourceCreationMask +
1772:                //		   " resourceUpdatedMask= " + resourceUpdatedMask);
1773:
1774:                if (reloadTexture) {
1775:
1776:                    // reload all levels of texture image
1777:
1778:                    // update texture parameters such as boundary modes, filtering
1779:
1780:                    updateTextureFields(cv);
1781:
1782:                    // update texture Lod parameters
1783:
1784:                    updateTextureLOD(cv);
1785:
1786:                    // update all texture images
1787:
1788:                    reloadTexture(cv);
1789:
1790:                    if (cv.useSharedCtx) {
1791:                        cv.makeCtxCurrent(cv.ctx);
1792:                        synchronized (resourceLock) {
1793:                            resourceCreationMask |= cv.screen.renderer.rendererBit;
1794:                            resourceUpdatedMask |= cv.screen.renderer.rendererBit;
1795:                            resourceLodUpdatedMask |= cv.screen.renderer.rendererBit;
1796:                        }
1797:                    } else {
1798:                        synchronized (resourceLock) {
1799:                            resourceCreationMask |= cv.canvasBit;
1800:                            resourceUpdatedMask |= cv.canvasBit;
1801:                            resourceLodUpdatedMask |= cv.canvasBit;
1802:                        }
1803:                    }
1804:                } else if (updateTextureLod || updateTexture) {
1805:
1806:                    if (updateTextureLod) {
1807:                        updateTextureLOD(cv);
1808:                    }
1809:
1810:                    if (updateTexture) {
1811:
1812:                        // update texture image
1813:
1814:                        int resourceBit = 0;
1815:
1816:                        if (cv.useSharedCtx) {
1817:                            resourceBit = cv.screen.renderer.rendererBit;
1818:                        } else {
1819:                            resourceBit = cv.canvasBit;
1820:                        }
1821:
1822:                        // update texture based on the imageComponent update info
1823:
1824:                        updateTexture(cv, resourceBit);
1825:                    }
1826:
1827:                    // set the appropriate bit in the resource update masks showing
1828:                    // that the resource is up-to-date
1829:
1830:                    if (cv.useSharedCtx) {
1831:                        cv.makeCtxCurrent(cv.ctx);
1832:                        synchronized (resourceLock) {
1833:                            resourceUpdatedMask |= cv.screen.renderer.rendererBit;
1834:                            resourceLodUpdatedMask |= cv.screen.renderer.rendererBit;
1835:                        }
1836:                    } else {
1837:                        synchronized (resourceLock) {
1838:                            resourceUpdatedMask |= cv.canvasBit;
1839:                            resourceLodUpdatedMask |= cv.canvasBit;
1840:                        }
1841:                    }
1842:                }
1843:            }
1844:
1845:            synchronized void createMirrorObject() {
1846:                if (mirror == null) {
1847:                    if (this  instanceof  Texture3DRetained) {
1848:                        Texture3DRetained t3d = (Texture3DRetained) this ;
1849:                        Texture3D tex = new Texture3D(t3d.mipmapMode,
1850:                                t3d.format, t3d.width, t3d.height, t3d.depth,
1851:                                t3d.boundaryWidth);
1852:                        mirror = (Texture3DRetained) tex.retained;
1853:                        ;
1854:
1855:                    } else if (this  instanceof  TextureCubeMapRetained) {
1856:                        TextureCubeMap tex = new TextureCubeMap(mipmapMode,
1857:                                format, width, boundaryWidth);
1858:                        mirror = (TextureCubeMapRetained) tex.retained;
1859:
1860:                    } else {
1861:                        Texture2D tex = new Texture2D(mipmapMode, format,
1862:                                width, height, boundaryWidth);
1863:                        mirror = (Texture2DRetained) tex.retained;
1864:                    }
1865:
1866:                    ((TextureRetained) mirror).objectId = -1;
1867:                }
1868:                initMirrorObject();
1869:            }
1870:
1871:            /**
1872:             * Initializes a mirror object, point the mirror object to the retained
1873:             * object if the object is not editable
1874:             */
1875:            synchronized void initMirrorObject() {
1876:                mirror.source = source;
1877:                if (this  instanceof  Texture3DRetained) {
1878:                    Texture3DRetained t3d = (Texture3DRetained) this ;
1879:
1880:                    ((Texture3DRetained) mirror).boundaryModeR = t3d.boundaryModeR;
1881:                    ((Texture3DRetained) mirror).depth = t3d.depth;
1882:                }
1883:                TextureRetained mirrorTexture = (TextureRetained) mirror;
1884:
1885:                mirrorTexture.boundaryModeS = boundaryModeS;
1886:                mirrorTexture.boundaryModeT = boundaryModeT;
1887:                mirrorTexture.minFilter = minFilter;
1888:                mirrorTexture.magFilter = magFilter;
1889:                mirrorTexture.boundaryColor.set(boundaryColor);
1890:                mirrorTexture.enable = enable;
1891:                mirrorTexture.userSpecifiedEnable = enable;
1892:                mirrorTexture.enable = enable;
1893:                mirrorTexture.numFaces = numFaces;
1894:                mirrorTexture.resourceCreationMask = 0x0;
1895:                mirrorTexture.resourceUpdatedMask = 0x0;
1896:                mirrorTexture.resourceLodUpdatedMask = 0x0;
1897:                mirrorTexture.resourceInReloadList = 0x0;
1898:
1899:                // LOD information
1900:                mirrorTexture.baseLevel = baseLevel;
1901:                mirrorTexture.maximumLevel = maximumLevel;
1902:                mirrorTexture.minimumLod = minimumLod;
1903:                mirrorTexture.maximumLod = maximumLod;
1904:                mirrorTexture.lodOffset = lodOffset;
1905:
1906:                // sharpen texture LOD function
1907:
1908:                mirrorTexture.numSharpenTextureFuncPts = numSharpenTextureFuncPts;
1909:                if (sharpenTextureFuncPts == null) {
1910:                    mirrorTexture.sharpenTextureFuncPts = null;
1911:                } else {
1912:                    if ((mirrorTexture.sharpenTextureFuncPts == null)
1913:                            || (mirrorTexture.sharpenTextureFuncPts.length != sharpenTextureFuncPts.length)) {
1914:                        mirrorTexture.sharpenTextureFuncPts = new float[sharpenTextureFuncPts.length];
1915:                    }
1916:                    for (int i = 0; i < sharpenTextureFuncPts.length; i++) {
1917:                        mirrorTexture.sharpenTextureFuncPts[i] = sharpenTextureFuncPts[i];
1918:                    }
1919:                }
1920:
1921:                // filter4 function
1922:                if (filter4FuncPts == null) {
1923:                    mirrorTexture.filter4FuncPts = null;
1924:                } else {
1925:                    if ((mirrorTexture.filter4FuncPts == null)
1926:                            || (mirrorTexture.filter4FuncPts.length != filter4FuncPts.length)) {
1927:                        mirrorTexture.filter4FuncPts = new float[filter4FuncPts.length];
1928:                    }
1929:                    for (int i = 0; i < filter4FuncPts.length; i++) {
1930:                        mirrorTexture.filter4FuncPts[i] = filter4FuncPts[i];
1931:                    }
1932:                }
1933:
1934:                // Anisotropic Filter
1935:                mirrorTexture.anisotropicFilterMode = anisotropicFilterMode;
1936:                mirrorTexture.anisotropicFilterDegree = anisotropicFilterDegree;
1937:
1938:                mirrorTexture.maxLevels = maxLevels;
1939:                if (images != null) {
1940:
1941:                    for (int j = 0; j < numFaces; j++) {
1942:                        for (int i = 0; i < maxLevels; i++) {
1943:                            mirrorTexture.images[j][i] = images[j][i];
1944:
1945:                            // add texture to the userList of the images
1946:                            if (images[j][i] != null) {
1947:                                images[j][i].addUser(mirrorTexture);
1948:                            }
1949:                        }
1950:                    }
1951:                }
1952:            }
1953:
1954:            boolean useAutoMipMapGeneration(Canvas3D cv) {
1955:                if (mipmapMode == Texture.BASE_LEVEL
1956:                        && (minFilter == Texture.NICEST
1957:                                || minFilter == Texture.MULTI_LEVEL_POINT || minFilter == Texture.MULTI_LEVEL_LINEAR)
1958:                        && ((cv.textureExtendedFeatures & Canvas3D.TEXTURE_AUTO_MIPMAP_GENERATION) != 0)) {
1959:                    return true;
1960:                }
1961:
1962:                return false;
1963:            }
1964:
1965:            /**
1966:             * Go through the image update info list
1967:             * and remove those that are already done
1968:             * by all the resources
1969:             */
1970:            void pruneImageUpdateInfo() {
1971:                ImageComponentUpdateInfo info;
1972:
1973:                //System.err.println("Texture.pruneImageUpdateInfo");
1974:
1975:                for (int k = 0; k < numFaces; k++) {
1976:                    for (int i = baseLevel; i <= maximumLevel; i++) {
1977:                        if ((imageUpdatePruneMask[k] & (1 << i)) != 0) {
1978:                            if (imageUpdateInfo[k][i] != null) {
1979:                                for (int j = 0; j < imageUpdateInfo[k][i]
1980:                                        .size(); j++) {
1981:                                    info = (ImageComponentUpdateInfo) imageUpdateInfo[k][i]
1982:                                            .get(j);
1983:                                    if (info.updateMask == 0) {
1984:                                        // this update info is done, remove it
1985:                                        // from the update list
1986:                                        imageUpdateInfo[k][i].remove(j);
1987:                                    }
1988:                                }
1989:                            }
1990:                            imageUpdatePruneMask[k] &= ~(1 << i);
1991:                        }
1992:                    }
1993:                }
1994:            }
1995:
1996:            /**
1997:             * addImageUpdateInfo(int level) is to update a particular level.
1998:             * In this case, it supercedes all the subImage update for this level,
1999:             * and all those update info can be removed from the update list.
2000:             *
2001:             * Note: this method is called from mirror only
2002:             */
2003:            void addImageUpdateInfo(int level, int face,
2004:                    ImageComponentUpdateInfo arg) {
2005:
2006:                ImageComponentUpdateInfo info;
2007:
2008:                if (imageUpdateInfo == null) {
2009:                    imageUpdateInfo = new ArrayList[numFaces][maxLevels];
2010:                }
2011:
2012:                if (imageUpdateInfo[face][level] == null) {
2013:                    imageUpdateInfo[face][level] = new ArrayList();
2014:                }
2015:
2016:                info = new ImageComponentUpdateInfo();
2017:
2018:                if (arg == null) {
2019:                    // no subimage info, so the entire image is to be updated
2020:                    info.entireImage = true;
2021:                    // Fix issue 117 using ogl subimage always
2022:                    //	} else if ((arg.width >= width/2) && (arg.height >= height/2)) {
2023:                    //
2024:                    //	    // if the subimage dimension is close to the complete dimension,
2025:                    //            // use the full update (it's more efficient)
2026:                    //	    info.entireImage = true;
2027:                } else {
2028:                    info.entireImage = false;
2029:                }
2030:
2031:                if (info.entireImage) {
2032:                    // the entire image update supercedes all the subimage update;
2033:                    // hence, remove all the existing updates from the list
2034:                    imageUpdateInfo[face][level].clear();
2035:
2036:                    // reset the update prune mask for this level
2037:                    if (imageUpdatePruneMask != null) {
2038:                        imageUpdatePruneMask[face] &= ~(1 << level);
2039:                    }
2040:
2041:                } else {
2042:                    // subimage update, needs to save the subimage info
2043:                    info.x = arg.x;
2044:                    info.y = arg.y;
2045:                    info.z = arg.z;
2046:                    info.width = arg.width;
2047:                    info.height = arg.height;
2048:                }
2049:
2050:                // save the mask which shows the canvases that have created resources
2051:                // for this image, aka, these are the resources that need to be
2052:                // updated.
2053:                info.updateMask = resourceCreationMask;
2054:
2055:                // add the image update to the list
2056:                imageUpdateInfo[face][level].add(info);
2057:
2058:                // check if the update list stills need to be pruned
2059:                if (imageUpdatePruneMask != null) {
2060:                    pruneImageUpdateInfo();
2061:                }
2062:            }
2063:
2064:            void validate() {
2065:                enable = true;
2066:                for (int j = 0; j < numFaces && enable; j++) {
2067:                    for (int i = baseLevel; i <= maximumLevel && enable; i++) {
2068:                        if (images[j][i] == null) {
2069:                            enable = false;
2070:                        }
2071:                    }
2072:                }
2073:            }
2074:
2075:            /**
2076:             * Update the "component" field of the mirror object with the 
2077:             *  given "value"
2078:             */
2079:            synchronized void updateMirrorObject(int component, Object value) {
2080:
2081:                TextureRetained mirrorTexture = (TextureRetained) mirror;
2082:
2083:                if ((component & ENABLE_CHANGED) != 0) {
2084:                    mirrorTexture.enable = ((Boolean) value).booleanValue();
2085:
2086:                } else if ((component & IMAGE_CHANGED) != 0) {
2087:
2088:                    Object[] arg = (Object[]) value;
2089:                    int level = ((Integer) arg[0]).intValue();
2090:                    ImageComponent image = (ImageComponent) arg[1];
2091:                    int face = ((Integer) arg[2]).intValue();
2092:
2093:                    // first remove texture from the userList of the current
2094:                    // referencing image and
2095:
2096:                    if (mirrorTexture.images[face][level] != null) {
2097:                        mirrorTexture.images[face][level].removeUser(mirror);
2098:                    }
2099:
2100:                    // assign the new image and add texture to the userList
2101:                    if (image == null) {
2102:                        mirrorTexture.images[face][level] = null;
2103:
2104:                    } else {
2105:                        mirrorTexture.images[face][level] = (ImageComponentRetained) image.retained;
2106:                        mirrorTexture.images[face][level].addUser(mirror);
2107:
2108:                    }
2109:
2110:                    // NOTE: the old image has to be removed from the
2111:                    // renderBins' NodeComponentList and new image has to be
2112:                    // added to the lists. This will be taken care of
2113:                    // in the RenderBin itself in response to the
2114:                    // IMAGE_CHANGED message
2115:
2116:                    // mark that texture images need to be updated
2117:                    mirrorTexture.resourceUpdatedMask = 0;
2118:
2119:                    // add update info to the update list
2120:                    mirrorTexture.addImageUpdateInfo(level, face, null);
2121:
2122:                } else if ((component & IMAGES_CHANGED) != 0) {
2123:
2124:                    Object[] arg = (Object[]) value;
2125:                    ImageComponent[] images = (ImageComponent[]) arg[0];
2126:                    int face = ((Integer) arg[1]).intValue();
2127:
2128:                    for (int i = 0; i < images.length; i++) {
2129:
2130:                        // first remove texture from the userList of the current
2131:                        // referencing image
2132:                        if (mirrorTexture.images[face][i] != null) {
2133:                            mirrorTexture.images[face][i].removeUser(mirror);
2134:                        }
2135:
2136:                        // assign the new image and add texture to the userList
2137:                        if (images[i] == null) {
2138:                            mirrorTexture.images[face][i] = null;
2139:                        } else {
2140:                            mirrorTexture.images[face][i] = (ImageComponentRetained) images[i].retained;
2141:                            mirrorTexture.images[face][i].addUser(mirror);
2142:                        }
2143:                    }
2144:                    mirrorTexture.updateResourceCreationMask();
2145:
2146:                    // NOTE: the old images have to be removed from the
2147:                    // renderBins' NodeComponentList and new image have to be
2148:                    // added to the lists. This will be taken care of
2149:                    // in the RenderBin itself in response to the
2150:                    // IMAGES_CHANGED message
2151:
2152:                } else if ((component & BASE_LEVEL_CHANGED) != 0) {
2153:                    int level = ((Integer) value).intValue();
2154:
2155:                    if (level < mirrorTexture.baseLevel) {
2156:
2157:                        // add texture to the userList of those new levels of 
2158:                        // enabling images
2159:
2160:                        for (int j = 0; j < numFaces; j++) {
2161:                            for (int i = level; i < mirrorTexture.baseLevel; i++) {
2162:
2163:                                if (mirrorTexture.images[j][i] == null) {
2164:                                    mirrorTexture.enable = false;
2165:                                } else {
2166:                                    mirrorTexture
2167:                                            .addImageUpdateInfo(i, j, null);
2168:                                }
2169:                            }
2170:                        }
2171:
2172:                        mirrorTexture.baseLevel = level;
2173:
2174:                        // mark that texture images need to be updated
2175:                        mirrorTexture.resourceUpdatedMask = 0;
2176:
2177:                    } else {
2178:
2179:                        mirrorTexture.baseLevel = level;
2180:
2181:                        if (userSpecifiedEnable
2182:                                && (mirrorTexture.enable == false)) {
2183:
2184:                            // if texture is to be enabled but is currently
2185:                            // disabled, it's probably disabled because
2186:                            // some of the images are missing. Now that
2187:                            // the baseLevel is modified, validate the
2188:                            // texture images again
2189:
2190:                            mirrorTexture.validate();
2191:                        }
2192:                    }
2193:
2194:                    // mark that texture lod info needs to be updated
2195:                    mirrorTexture.resourceLodUpdatedMask = 0;
2196:
2197:                } else if ((component & MAX_LEVEL_CHANGED) != 0) {
2198:                    int level = ((Integer) value).intValue();
2199:
2200:                    if (level > mirrorTexture.maximumLevel) {
2201:
2202:                        // add texture to the userList of those new levels of
2203:                        // enabling images
2204:
2205:                        for (int j = 0; j < numFaces; j++) {
2206:                            for (int i = mirrorTexture.maximumLevel; i < level; i++) {
2207:
2208:                                if (mirrorTexture.images[j][i] == null) {
2209:                                    mirrorTexture.enable = false;
2210:                                } else {
2211:                                    mirrorTexture
2212:                                            .addImageUpdateInfo(i, j, null);
2213:                                }
2214:                            }
2215:                        }
2216:
2217:                        mirrorTexture.maximumLevel = level;
2218:
2219:                        // mark that texture images need to be updated
2220:                        mirrorTexture.resourceUpdatedMask = 0;
2221:
2222:                    } else {
2223:
2224:                        mirrorTexture.maximumLevel = level;
2225:
2226:                        if (userSpecifiedEnable
2227:                                && (mirrorTexture.enable == false)) {
2228:
2229:                            // if texture is to be enabled but is currently
2230:                            // disabled, it's probably disabled because
2231:                            // some of the images are missing. Now that
2232:                            // the baseLevel is modified, validate the
2233:                            // texture images again
2234:
2235:                            mirrorTexture.validate();
2236:                        }
2237:                    }
2238:
2239:                    // mark that texture lod info needs to be updated
2240:                    mirrorTexture.resourceLodUpdatedMask = 0;
2241:
2242:                } else if ((component & MIN_LOD_CHANGED) != 0) {
2243:                    mirrorTexture.minimumLod = ((Float) value).floatValue();
2244:
2245:                    // mark that texture lod info needs to be updated
2246:                    mirrorTexture.resourceLodUpdatedMask = 0;
2247:
2248:                } else if ((component & MAX_LOD_CHANGED) != 0) {
2249:                    mirrorTexture.maximumLod = ((Float) value).floatValue();
2250:
2251:                    // mark that texture lod info needs to be updated
2252:                    mirrorTexture.resourceLodUpdatedMask = 0;
2253:
2254:                } else if ((component & LOD_OFFSET_CHANGED) != 0) {
2255:                    if ((mirrorTexture.lodOffset) == null) {
2256:                        mirrorTexture.lodOffset = new Point3f((Point3f) value);
2257:                    } else {
2258:                        mirrorTexture.lodOffset.set((Point3f) value);
2259:                    }
2260:
2261:                    // mark that texture lod info needs to be updated
2262:                    mirrorTexture.resourceLodUpdatedMask = 0;
2263:
2264:                } else if ((component & UPDATE_IMAGE) != 0) {
2265:                    mirrorTexture.updateResourceCreationMask();
2266:                }
2267:
2268:            }
2269:
2270:            // notifies the Texture mirror object that the image data in a referenced
2271:            // ImageComponent object is changed. Need to update the texture image
2272:            // accordingly.
2273:            // Note: this is called from mirror object only
2274:
2275:            void notifyImageComponentImageChanged(ImageComponentRetained image,
2276:                    ImageComponentUpdateInfo value) {
2277:
2278:                //System.err.println("Texture.notifyImageComponentImageChanged");
2279:
2280:                // if this texture is to be reloaded, don't bother to keep
2281:                // the update info
2282:
2283:                if (resourceCreationMask == 0) {
2284:
2285:                    if (imageUpdateInfo != null) {
2286:
2287:                        //remove all the existing updates from the list
2288:
2289:                        for (int face = 0; face < numFaces; face++) {
2290:                            for (int level = 0; level < maxLevels; level++) {
2291:                                if (imageUpdateInfo[face][level] != null) {
2292:                                    imageUpdateInfo[face][level].clear();
2293:                                }
2294:                            }
2295:
2296:                            // reset the update prune mask for this level
2297:                            if (imageUpdatePruneMask != null) {
2298:                                imageUpdatePruneMask[face] = 0;
2299:                            }
2300:                        }
2301:                    }
2302:
2303:                    return;
2304:                }
2305:
2306:                // first find which texture image is being affected
2307:
2308:                boolean done;
2309:
2310:                for (int j = 0; j < numFaces; j++) {
2311:
2312:                    done = false;
2313:                    for (int i = baseLevel; i <= maximumLevel && !done; i++) {
2314:                        if (images[j][i] == image) {
2315:
2316:                            // reset the resourceUpdatedMask to tell the
2317:                            // rendering method to update the resource
2318:                            resourceUpdatedMask = 0;
2319:
2320:                            // add update info to the update list
2321:                            addImageUpdateInfo(i, j, value);
2322:
2323:                            // set done to true for this face because no two levels
2324:                            // can reference the same ImageComponent object
2325:                            done = true;
2326:                        }
2327:                    }
2328:                }
2329:            }
2330:
2331:            // reset the resourceCreationMask
2332:            // Note: called from the mirror object only
2333:
2334:            void updateResourceCreationMask() {
2335:                resourceCreationMask = 0x0;
2336:            }
2337:
2338:            void incTextureBinRefCount(TextureBin tb) {
2339:
2340:                ImageComponentRetained image;
2341:
2342:                setTextureBinRefCount(tb, getTextureBinRefCount(tb) + 1);
2343:
2344:                // check to see if there is any modifiable images,
2345:                // if yes, add those images to nodeComponentList in RenderBin
2346:                // so that RenderBin can acquire a lock before rendering
2347:                // to prevent updating of image data while rendering
2348:
2349:                for (int j = 0; j < numFaces; j++) {
2350:                    for (int i = 0; i < maxLevels; i++) {
2351:                        image = images[j][i];
2352:
2353:                        // it is possible that image.source == null because
2354:                        // the mipmap could have been created by the library, and
2355:                        // hence don't have source and therefore they are
2356:                        // guaranteed not modifiable
2357:
2358:                        if (image != null
2359:                                && (image.isByReference() || (image.source != null && image.source
2360:                                        .getCapability(ImageComponent.ALLOW_IMAGE_WRITE)))) {
2361:                            tb.renderBin.addNodeComponent(image);
2362:                        }
2363:                    }
2364:                }
2365:            }
2366:
2367:            void decTextureBinRefCount(TextureBin tb) {
2368:
2369:                ImageComponentRetained image;
2370:
2371:                setTextureBinRefCount(tb, getTextureBinRefCount(tb) - 1);
2372:
2373:                // remove any modifiable images from RenderBin nodeComponentList
2374:
2375:                for (int j = 0; j < numFaces; j++) {
2376:                    for (int i = 0; i < maxLevels; i++) {
2377:                        image = images[j][i];
2378:                        if (image != null
2379:                                && (image.isByReference() || (image.source != null && image.source
2380:                                        .getCapability(ImageComponent.ALLOW_IMAGE_WRITE)))) {
2381:                            tb.renderBin.removeNodeComponent(image);
2382:                        }
2383:                    }
2384:                }
2385:            }
2386:
2387:            final void sendMessage(int attrMask, Object attr) {
2388:
2389:                ArrayList univList = new ArrayList();
2390:                ArrayList gaList = Shape3DRetained.getGeomAtomsList(
2391:                        mirror.users, univList);
2392:
2393:                // Send to rendering attribute structure, regardless of
2394:                // whether there are users or not (alternate appearance case ..)
2395:                J3dMessage createMessage = new J3dMessage();
2396:                createMessage.threads = J3dThread.UPDATE_RENDERING_ATTRIBUTES;
2397:                createMessage.type = J3dMessage.TEXTURE_CHANGED;
2398:                createMessage.universe = null;
2399:                createMessage.args[0] = this ;
2400:                createMessage.args[1] = new Integer(attrMask);
2401:                createMessage.args[2] = attr;
2402:                createMessage.args[3] = new Integer(changedFrequent);
2403:                VirtualUniverse.mc.processMessage(createMessage);
2404:
2405:                // System.err.println("univList.size is " + univList.size());
2406:                for (int i = 0; i < univList.size(); i++) {
2407:                    createMessage = new J3dMessage();
2408:                    createMessage.threads = J3dThread.UPDATE_RENDER;
2409:                    createMessage.type = J3dMessage.TEXTURE_CHANGED;
2410:
2411:                    createMessage.universe = (VirtualUniverse) univList.get(i);
2412:                    createMessage.args[0] = this ;
2413:                    createMessage.args[1] = new Integer(attrMask);
2414:                    createMessage.args[2] = attr;
2415:
2416:                    ArrayList gL = (ArrayList) gaList.get(i);
2417:                    GeometryAtom[] gaArr = new GeometryAtom[gL.size()];
2418:                    gL.toArray(gaArr);
2419:                    createMessage.args[3] = gaArr;
2420:
2421:                    VirtualUniverse.mc.processMessage(createMessage);
2422:                }
2423:
2424:            }
2425:
2426:            void handleFrequencyChange(int bit) {
2427:                switch (bit) {
2428:                case Texture.ALLOW_ENABLE_WRITE:
2429:                case Texture.ALLOW_IMAGE_WRITE:
2430:                case Texture.ALLOW_LOD_RANGE_WRITE: {
2431:                    setFrequencyChangeMask(bit, bit);
2432:                }
2433:                default:
2434:                    break;
2435:                }
2436:            }
2437:
2438:            void setUseAsRaster(boolean useAsRaster) {
2439:                this .useAsRaster = useAsRaster;
2440:            }
2441:
2442:            boolean isUseAsRaster() {
2443:                return this .useAsRaster;
2444:            }
2445:
2446:            // Issue 357 - {get/set}TextureBinRefCount now uses a separate reference
2447:            // counter per RenderBin. The absence of the RenderBin key in the hash map
2448:            // is used to indicate a value of 0. This makes initialization easier, and
2449:            // prevents a small amount of garbage accumulating for inactive RenderBins.
2450:
2451:            int getTextureBinRefCount(TextureBin tb) {
2452:                Integer i = textureBinRefCount.get(tb.renderBin);
2453:                return i == null ? 0 : i.intValue();
2454:            }
2455:
2456:            private void setTextureBinRefCount(TextureBin tb, int refCount) {
2457:                if (refCount == 0) {
2458:                    textureBinRefCount.remove(tb.renderBin);
2459:                } else {
2460:                    textureBinRefCount.put(tb.renderBin, new Integer(refCount));
2461:                }
2462:            }
2463:
2464:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.