1 /*
2  * Copyright (C) 2012 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.ide.eclipse.gltrace.views.detail;
18 
19 import com.android.ide.eclipse.gltrace.state.GLCompositeProperty;
20 import com.android.ide.eclipse.gltrace.state.GLSparseArrayProperty;
21 import com.android.ide.eclipse.gltrace.state.GLStateType;
22 import com.android.ide.eclipse.gltrace.state.GLStringProperty;
23 import com.android.ide.eclipse.gltrace.state.IGLProperty;
24 import com.android.ide.eclipse.gltrace.views.FitToCanvasAction;
25 import com.android.ide.eclipse.gltrace.views.SaveImageAction;
26 import com.android.ide.eclipse.gltrace.widgets.ImageCanvas;
27 
28 import org.eclipse.jface.action.ActionContributionItem;
29 import org.eclipse.jface.action.IContributionItem;
30 import org.eclipse.swt.graphics.Image;
31 import org.eclipse.swt.widgets.Composite;
32 import org.eclipse.swt.widgets.Control;
33 import org.eclipse.swt.widgets.Display;
34 
35 import java.util.Arrays;
36 import java.util.List;
37 
38 public class TextureImageDetailsProvider implements IStateDetailProvider {
39     private ImageCanvas mImageCanvas;
40     private FitToCanvasAction mFitToCanvasAction;
41     private SaveImageAction mSaveImageAction;
42     private List<IContributionItem> mToolBarItems;
43 
44     @Override
isApplicable(IGLProperty state)45     public boolean isApplicable(IGLProperty state) {
46         return getTextureImageProperty(state) != null;
47     }
48 
49     @Override
createControl(Composite parent)50     public void createControl(Composite parent) {
51         mImageCanvas = new ImageCanvas(parent);
52         mImageCanvas.setFitToCanvas(false);
53 
54         mFitToCanvasAction = new FitToCanvasAction(false, mImageCanvas);
55         mSaveImageAction = new SaveImageAction(mImageCanvas);
56 
57         mToolBarItems = Arrays.asList(
58                 (IContributionItem) new ActionContributionItem(mFitToCanvasAction),
59                 (IContributionItem) new ActionContributionItem(mSaveImageAction));
60     }
61 
62     @Override
disposeControl()63     public void disposeControl() {
64         mImageCanvas.dispose();
65         mImageCanvas = null;
66     }
67 
68     @Override
getControl()69     public Control getControl() {
70         return mImageCanvas;
71     }
72 
73     @Override
updateControl(IGLProperty state)74     public void updateControl(IGLProperty state) {
75         IGLProperty imageProperty = getTextureImageProperty(state);
76         if (imageProperty == null) {
77             return;
78         }
79 
80         String texturePath = ((GLStringProperty) imageProperty).getStringValue();
81         if (texturePath != null) {
82             mImageCanvas.setImage(new Image(Display.getDefault(), texturePath));
83             mImageCanvas.setFitToCanvas(false);
84             return;
85         }
86     }
87 
88     /**
89      * Get the {@link GLStateType#TEXTURE_IMAGE} property given a node in
90      * the state hierarchy.
91      * @param state any node in the GL state hierarchy
92      * @return The {@link GLStateType#TEXTURE_IMAGE} property if a unique instance
93      *         of it can be accessed from the given node. A unique instance can be
94      *         accessed if the given node is either the requested node itself, or
95      *         its parent or sibling. In cases where a unique instance cannot be
96      *         accessed, but one of the texture mipmap levels can be accessed, then
97      *         return the first texture mipmap level. This happens if the selected
98      *         state is a child of {@link GLStateType#PER_TEXTURE_STATE}. Returns
99      *         null otherwise.
100      */
getTextureImageProperty(IGLProperty state)101     private IGLProperty getTextureImageProperty(IGLProperty state) {
102         if (state.getType() == GLStateType.TEXTURE_IMAGE) {
103             // given node is the requested node
104             return state;
105         }
106 
107         IGLProperty img = getImageFromPerTextureLevelState(state);
108         if (img != null) {
109             return img;
110         }
111 
112         return getFirstMipmapImage(state);
113     }
114 
115     /**
116      * Returns the {@link GLStateType#TEXTURE_IMAGE} if the provided state is either
117      * {@link GLStateType#PER_TEXTURE_LEVEL_STATE} or one of its children. Returns null otherwise.
118      */
getImageFromPerTextureLevelState(IGLProperty state)119     private IGLProperty getImageFromPerTextureLevelState(IGLProperty state) {
120         if (state != null && state.getType() != GLStateType.PER_TEXTURE_LEVEL_STATE) {
121             state = state.getParent();
122         }
123 
124         if (state == null || state.getType() != GLStateType.PER_TEXTURE_LEVEL_STATE) {
125             return null;
126         }
127 
128         return ((GLCompositeProperty) state).getProperty(GLStateType.TEXTURE_IMAGE);
129     }
130 
131     /**
132      * Returns the first mipmap level's image entry if the provided state is either
133      * {@link GLStateType#PER_TEXTURE_STATE} or one of its immediate children, null otherwise.
134      */
getFirstMipmapImage(IGLProperty state)135     private IGLProperty getFirstMipmapImage(IGLProperty state) {
136         if (state != null && state.getType() != GLStateType.PER_TEXTURE_STATE) {
137             state = state.getParent();
138         }
139 
140         if (state == null || state.getType() != GLStateType.PER_TEXTURE_STATE) {
141             return null;
142         }
143 
144         IGLProperty mipmaps =
145                 ((GLCompositeProperty) state).getProperty(GLStateType.TEXTURE_MIPMAPS);
146         if (!(mipmaps instanceof GLSparseArrayProperty)) {
147             return null;
148         }
149 
150         IGLProperty perTextureLevelState = ((GLSparseArrayProperty) mipmaps).getProperty(0);
151         return getImageFromPerTextureLevelState(perTextureLevelState);
152     }
153 
154     @Override
getToolBarItems()155     public List<IContributionItem> getToolBarItems() {
156         return mToolBarItems;
157     }
158 }
159