OSDN Git Service

Updates to 3D gallery source.
[android-x86/packages-apps-Gallery2.git] / src / com / cooliris / media / GridDrawManager.java
1 package com.cooliris.media;
2
3 import java.util.Arrays;
4 import java.util.Comparator;
5 import java.util.HashMap;
6
7 import javax.microedition.khronos.opengles.GL10;
8 import javax.microedition.khronos.opengles.GL11;
9
10 import android.content.Context;
11
12 public final class GridDrawManager {
13     public static final int PASS_THUMBNAIL_CONTENT = 0;
14     public static final int PASS_FOCUS_CONTENT = 1;
15     public static final int PASS_FRAME = 2;
16     public static final int PASS_PLACEHOLDER = 3;
17     public static final int PASS_FRAME_PLACEHOLDER = 4;
18     public static final int PASS_TEXT_LABEL = 5;
19     public static final int PASS_SELECTION_LABEL = 6;
20     public static final int PASS_VIDEO_LABEL = 7;
21     public static final int PASS_LOCATION_LABEL = 8;
22     public static final int PASS_MEDIASET_SOURCE_LABEL = 9;
23
24     private static final MediaItemTexture.Config sThumbnailConfig = new MediaItemTexture.Config();
25     private final DisplayItem[] mDisplayItems;
26     private final DisplaySlot[] mDisplaySlots;
27     private final DisplayList mDisplayList;
28     private final GridCamera mCamera;
29     private final GridDrawables mDrawables;
30     private IndexRange mBufferedVisibleRange;
31     private IndexRange mVisibleRange;
32     private int mSelectedSlot;
33     private int mCurrentFocusSlot;
34     private DisplayItem[] mItemsDrawn;
35     private int mDrawnCounter;
36     private float mTargetFocusMixRatio = 0.0f;
37     private float mFocusMixRatio = 0.0f;
38     private final FloatAnim mSelectedMixRatio = new FloatAnim(0f);
39     private float mCurrentFocusItemWidth;
40     private float mCurrentFocusItemHeight;
41     private boolean mCurrentFocusIsPressed;
42     private final Texture mNoItemsTexture;
43
44     private static final Comparator<DisplayItem> sDisplayItemComparator = new Comparator<DisplayItem>() {
45         public int compare(DisplayItem a, DisplayItem b) {
46             if (a == null || b == null) {
47                 return 0;
48             }
49             float delta = (a.mAnimatedPosition.z - b.mAnimatedPosition.z);
50             if (delta > 0) {
51                 return 1;
52             } else if (delta < 0) {
53                 return -1;
54             } else {
55                 return 0;
56             }
57         }
58     };
59
60     public GridDrawManager(Context context, GridCamera camera, GridDrawables drawables, DisplayList displayList,
61             DisplayItem[] displayItems, DisplaySlot[] displaySlots) {
62         sThumbnailConfig.thumbnailWidth = 128;
63         sThumbnailConfig.thumbnailHeight = 96;
64         mDisplayItems = displayItems;
65         mDisplaySlots = displaySlots;
66         mDisplayList = displayList;
67         mDrawables = drawables;
68         mCamera = camera;
69         mItemsDrawn = new DisplayItem[GridLayer.MAX_ITEMS_DRAWABLE];
70
71         StringTexture.Config stc = new StringTexture.Config();
72         stc.bold = true;
73         stc.fontSize = 16 * Gallery.PIXEL_DENSITY;
74         stc.sizeMode = StringTexture.Config.SIZE_EXACT;
75         stc.overflowMode = StringTexture.Config.OVERFLOW_FADE;
76         mNoItemsTexture = new StringTexture(context.getResources().getString(R.string.no_items), stc);
77
78     }
79
80     public void prepareDraw(IndexRange bufferedVisibleRange, IndexRange visibleRange, int selectedSlot, int currentFocusSlot,
81             boolean currentFocusIsPressed) {
82         mBufferedVisibleRange = bufferedVisibleRange;
83         mVisibleRange = visibleRange;
84         mSelectedSlot = selectedSlot;
85         mCurrentFocusSlot = currentFocusSlot;
86         mCurrentFocusIsPressed = currentFocusIsPressed;
87     }
88
89     public boolean update(float timeElapsed) {
90         mFocusMixRatio = FloatUtils.animate(mFocusMixRatio, mTargetFocusMixRatio, timeElapsed);
91         mTargetFocusMixRatio = 0.0f;
92         if (mFocusMixRatio != mTargetFocusMixRatio || mSelectedMixRatio.isAnimating()) {
93             return true;
94         }
95         return false;
96     }
97
98     public void drawThumbnails(RenderView view, GL11 gl, int state) {
99         final GridDrawables drawables = mDrawables;
100         final DisplayList displayList = mDisplayList;
101         final DisplayItem[] displayItems = mDisplayItems;
102         final int firstBufferedVisibleSlot = mBufferedVisibleRange.begin;
103         final int lastBufferedVisibleSlot = mBufferedVisibleRange.end;
104         final int firstVisibleSlot = mVisibleRange.begin;
105         final int lastVisibleSlot = mVisibleRange.end;
106         final int selectedSlotIndex = mSelectedSlot;
107         final int currentFocusSlot = mCurrentFocusSlot;
108         final DisplayItem[] itemsDrawn = mItemsDrawn;
109         itemsDrawn[0] = null; // No items drawn yet.
110         int drawnCounter = 0;
111         final GridQuad grid = GridDrawables.sGrid;
112         grid.bindArrays(gl);
113         int numTexturesQueued = 0;
114         Context context = view.getContext();
115         for (int itrSlotIndex = firstBufferedVisibleSlot; itrSlotIndex <= lastBufferedVisibleSlot; ++itrSlotIndex) {
116             int index = itrSlotIndex;
117             boolean priority = !(index < firstVisibleSlot || index > lastVisibleSlot);
118             int startSlotIndex = 0;
119             for (int j = GridLayer.MAX_DISPLAYED_ITEMS_PER_SLOT - 1; j >= 0; --j) {
120                 DisplayItem displayItem = displayItems[(index - firstBufferedVisibleSlot) * GridLayer.MAX_ITEMS_PER_SLOT + j];
121                 if (displayItem == null) {
122                     continue;
123                 } else {
124                     Texture texture = displayItem.getThumbnailImage(context, sThumbnailConfig);
125                     if (texture != null && texture.isLoaded() == false) {
126                         startSlotIndex = j;
127                         break;
128                     }
129                 }
130             }
131             // Prime the textures in the reverse order.
132             for (int j = 0; j < GridLayer.MAX_DISPLAYED_ITEMS_PER_SLOT; ++j) {
133                 DisplayItem displayItem = displayItems[(index - firstBufferedVisibleSlot) * GridLayer.MAX_ITEMS_PER_SLOT + j];
134                 if (displayItem == null) {
135                     continue;
136                 } else {
137                     if (selectedSlotIndex != Shared.INVALID && (index <= selectedSlotIndex - 2 || index >= selectedSlotIndex + 2)) {
138                         displayItem.clearScreennailImage();
139                     }
140                     Texture texture = displayItem.getThumbnailImage(context, sThumbnailConfig);
141                     if (texture != null && !texture.isLoaded() && numTexturesQueued <= 6) {
142                         boolean isCached = texture.isCached();
143                         if (isCached)
144                             view.prime(texture, priority);
145                         view.bind(texture);
146                         if (priority && isCached && texture.mState != Texture.STATE_ERROR)
147                             ++numTexturesQueued;
148                     }
149                 }
150             }
151             if (itrSlotIndex == selectedSlotIndex) {
152                 continue;
153             }
154             view.prime(drawables.mTexturePlaceholder, true);
155             Texture placeholder = (state == GridLayer.STATE_GRID_VIEW) ? drawables.mTexturePlaceholder : null;
156             final boolean pushDown = (state == GridLayer.STATE_GRID_VIEW || state == GridLayer.STATE_FULL_SCREEN) ? false : true;
157             for (int j = startSlotIndex; j < GridLayer.MAX_DISPLAYED_ITEMS_PER_SLOT; ++j) {
158                 DisplayItem displayItem = displayItems[(index - firstBufferedVisibleSlot) * GridLayer.MAX_ITEMS_PER_SLOT + j];
159                 if (displayItem == null) {
160                     break;
161                 } else {
162                     if (currentFocusSlot == index) {
163                         displayList.setHasFocus(displayItem, true, pushDown);
164                         mTargetFocusMixRatio = 1.0f;
165                     } else {
166                         displayList.setHasFocus(displayItem, false, pushDown);
167                     }
168                     Texture texture = displayItem.getThumbnailImage(view.getContext(), sThumbnailConfig);
169                     if (texture != null) {
170                         if ((!displayItem.isAnimating() || !texture.isLoaded())
171                                 && displayItem.getStackIndex() > GridLayer.MAX_ITEMS_PER_SLOT) {
172                             displayItem.mAlive = true;
173                             continue;
174                         }
175                         if (index < firstVisibleSlot || index > lastVisibleSlot) {
176                             if (view.bind(texture)) {
177                                 mDisplayList.setAlive(displayItem, true);
178                             }
179                             continue;
180                         }
181                         drawDisplayItem(view, gl, displayItem, texture, PASS_THUMBNAIL_CONTENT, placeholder,
182                                 displayItem.mAnimatedPlaceholderFade);
183                     } else {
184                         // Move on to the next stack.
185                         break;
186                     }
187                     if (drawnCounter >= GridLayer.MAX_ITEMS_DRAWABLE - 1 || drawnCounter < 0) {
188                         break;
189                     }
190                     // Insert in order of z.
191                     itemsDrawn[drawnCounter++] = displayItem;
192                     itemsDrawn[drawnCounter] = null;
193                 }
194             }
195         }
196         mDrawnCounter = drawnCounter;
197         grid.unbindArrays(gl);
198     }
199
200     public float getFocusQuadWidth() {
201         return mCurrentFocusItemWidth;
202     }
203
204     public float getFocusQuadHeight() {
205         return mCurrentFocusItemHeight;
206     }
207
208     public void drawFocusItems(RenderView view, GL11 gl, float zoomValue, boolean slideshowMode, float timeElapsedSinceView) {
209         int selectedSlotIndex = mSelectedSlot;
210         GridDrawables drawables = mDrawables;
211         GridCamera camera = mCamera;
212         DisplayItem[] displayItems = mDisplayItems;
213         int firstBufferedVisibleSlot = mBufferedVisibleRange.begin;
214         int lastBufferedVisibleSlot = mBufferedVisibleRange.end;
215         boolean isCameraZAnimating = mCamera.isZAnimating();
216         for (int i = firstBufferedVisibleSlot; i <= lastBufferedVisibleSlot; ++i) {
217             if (selectedSlotIndex != Shared.INVALID && (i >= selectedSlotIndex - 2 && i <= selectedSlotIndex + 2)) {
218                 continue;
219             }
220             DisplayItem displayItem = displayItems[(i - firstBufferedVisibleSlot) * GridLayer.MAX_ITEMS_PER_SLOT];
221             if (displayItem != null) {
222                 displayItem.clearScreennailImage();
223             }
224         }
225         if (selectedSlotIndex != Shared.INVALID) {
226             float camX = camera.mLookAtX * camera.mScale;
227             int centerIndexInDrawnArray = (selectedSlotIndex - firstBufferedVisibleSlot) * GridLayer.MAX_ITEMS_PER_SLOT;
228             if (centerIndexInDrawnArray < 0 || centerIndexInDrawnArray >= displayItems.length) {
229                 return;
230             }
231             DisplayItem centerDisplayItem = displayItems[centerIndexInDrawnArray];
232             if (centerDisplayItem == null || centerDisplayItem.mItemRef.mId == Shared.INVALID) {
233                 return;
234             }
235             boolean focusItemTextureLoaded = false;
236             Texture centerTexture = centerDisplayItem.getScreennailImage(view.getContext());
237             if (centerTexture != null && centerTexture.isLoaded()) {
238                 focusItemTextureLoaded = true;
239             }
240             float centerTranslateX = centerDisplayItem.mAnimatedPosition.x;
241             final boolean skipPrevious = centerTranslateX < camX;
242             view.setAlpha(1.0f);
243             gl.glEnable(GL11.GL_BLEND);
244             gl.glBlendFunc(GL11.GL_ONE, GL11.GL_ONE);
245             float backupImageTheta = 0.0f;
246             for (int i = -1; i <= 1; ++i) {
247                 if (slideshowMode && timeElapsedSinceView > 1.0f && i != 0)
248                     continue;
249                 float viewAspect = camera.mAspectRatio;
250                 int selectedSlotToUse = selectedSlotIndex + i;
251                 if (selectedSlotToUse >= 0 && selectedSlotToUse <= lastBufferedVisibleSlot) {
252                     int indexInDrawnArray = (selectedSlotToUse - firstBufferedVisibleSlot) * GridLayer.MAX_ITEMS_PER_SLOT;
253                     if (indexInDrawnArray < 0 || indexInDrawnArray >= displayItems.length) {
254                         return;
255                     }
256                     DisplayItem displayItem = displayItems[indexInDrawnArray];
257                     MediaItem item = displayItem.mItemRef;
258                     final Texture thumbnailTexture = displayItem.getThumbnailImage(view.getContext(), sThumbnailConfig);
259                     Texture texture = displayItem.getScreennailImage(view.getContext());
260                     if (isCameraZAnimating && (texture == null || !texture.isLoaded())) {
261                         texture = thumbnailTexture;
262                         mSelectedMixRatio.setValue(0f);
263                         mSelectedMixRatio.animateValue(1f, 0.75f, view.getFrameTime());
264                     }
265                     Texture hiRes = (zoomValue != 1.0f && i == 0 && item.getMediaType() != MediaItem.MEDIA_TYPE_VIDEO) ? displayItem
266                             .getHiResImage(view.getContext())
267                             : null;
268                     if (Gallery.PIXEL_DENSITY > 1.0f) {
269                         hiRes = texture;
270                     }
271                     if (i != 0) {
272                         displayItem.clearHiResImage();
273                     }
274                     if (hiRes != null) {
275                         if (!hiRes.isLoaded()) {
276                             view.bind(hiRes);
277                             view.prime(hiRes, true);
278                         } else {
279                             texture = hiRes;
280                         }
281                     }
282                     final Texture fsTexture = texture;
283                     if (texture == null || !texture.isLoaded()) {
284                         if (Math.abs(centerTranslateX - camX) < 0.1f) {
285                             if (focusItemTextureLoaded && i != 0) {
286                                 view.bind(texture);
287                             }
288                             if (i == 0) {
289                                 view.bind(texture);
290                                 view.prime(texture, true);
291                             }
292                         }
293                         texture = thumbnailTexture;
294                         if (i == 0) {
295                             mSelectedMixRatio.setValue(0f);
296                             mSelectedMixRatio.animateValue(1f, 0.75f, view.getFrameTime());
297                         }
298                     }
299                     if (mCamera.isAnimating() || slideshowMode) {
300                         if (!slideshowMode && skipPrevious && i == -1) {
301                             continue;
302                         }
303                         if (!skipPrevious && i == 1) {
304                             continue;
305                         }
306                     }
307                     int theta = (int) displayItem.getImageTheta();
308                     // If it is in slideshow mode, we draw the previous item in
309                     // the next item's position.
310                     if (slideshowMode && timeElapsedSinceView < 1.0f && timeElapsedSinceView != 0) {
311                         if (i == -1) {
312                             int nextSlotToUse = selectedSlotToUse + 1;
313                             if (nextSlotToUse >= 0 && nextSlotToUse <= lastBufferedVisibleSlot) {
314                                 int nextIndexInDrawnArray = (nextSlotToUse - firstBufferedVisibleSlot)
315                                         * GridLayer.MAX_ITEMS_PER_SLOT;
316                                 if (nextIndexInDrawnArray >= 0 && nextIndexInDrawnArray < displayItems.length) {
317                                     float currentImageTheta = displayItem.mAnimatedImageTheta;
318                                     displayItem = displayItems[nextIndexInDrawnArray];
319                                     backupImageTheta = displayItem.mAnimatedImageTheta;
320                                     displayItem.mAnimatedImageTheta = currentImageTheta;
321                                     view.setAlpha(1.0f - timeElapsedSinceView);
322                                 }
323                             }
324                         } else if (i == 0) {
325                             displayItem.mAnimatedImageTheta = backupImageTheta;
326                             view.setAlpha(timeElapsedSinceView);
327                         }
328                     }
329                     if (texture != null) {
330                         int vboIndex = i + 1;
331                         float alpha = view.getAlpha();
332                         float selectedMixRatio = mSelectedMixRatio.getValue(view.getFrameTime());
333                         if (selectedMixRatio != 1f) {
334                             texture = thumbnailTexture;
335                             view.setAlpha(alpha * (1.0f - selectedMixRatio));
336                         }
337                         GridQuad quad = GridDrawables.sFullscreenGrid[vboIndex];
338                         float u = texture.getNormalizedWidth();
339                         float v = texture.getNormalizedHeight();
340                         float imageWidth = texture.getWidth();
341                         float imageHeight = texture.getHeight();
342                         boolean portrait = ((theta / 90) % 2 == 1);
343                         if (portrait) {
344                             viewAspect = 1.0f / viewAspect;
345                         }
346                         quad.resizeQuad(viewAspect, u, v, imageWidth, imageHeight);
347                         quad.bindArrays(gl);
348                         drawDisplayItem(view, gl, displayItem, texture, PASS_FOCUS_CONTENT, null, 0.0f);
349                         quad.unbindArrays(gl);
350                         if (selectedMixRatio != 0.0f && selectedMixRatio != 1.0f) {
351                             texture = fsTexture;
352                             if (texture != null) {
353                                 float drawAlpha = selectedMixRatio;
354                                 view.setAlpha(alpha * drawAlpha);
355                                 u = texture.getNormalizedWidth();
356                                 v = texture.getNormalizedHeight();
357                                 imageWidth = texture.getWidth();
358                                 imageHeight = texture.getHeight();
359                                 quad.resizeQuad(viewAspect, u, v, imageWidth, imageHeight);
360                                 quad.bindArrays(gl);
361                                 drawDisplayItem(view, gl, displayItem, fsTexture, PASS_FOCUS_CONTENT, null, 1.0f);
362                                 quad.unbindArrays(gl);
363                             }
364                         }
365                         if (i == 0 || slideshowMode) {
366                             mCurrentFocusItemWidth = quad.getWidth();
367                             mCurrentFocusItemHeight = quad.getHeight();
368                             if (portrait) {
369                                 // Swap these values.
370                                 float itemWidth = mCurrentFocusItemWidth;
371                                 mCurrentFocusItemWidth = mCurrentFocusItemHeight;
372                                 mCurrentFocusItemHeight = itemWidth;
373                             }
374                         }
375                         view.setAlpha(alpha);
376                         if (item.getMediaType() == MediaItem.MEDIA_TYPE_VIDEO) {
377                             // The play graphic overlay.
378                             GridDrawables.sVideoGrid.bindArrays(gl);
379                             drawDisplayItem(view, gl, displayItem, drawables.mTextureVideo, PASS_VIDEO_LABEL, null, 0);
380                             GridDrawables.sVideoGrid.unbindArrays(gl);
381                         }
382                     }
383                 }
384             }
385         }
386     }
387
388     public void drawBlendedComponents(RenderView view, GL11 gl, float alpha, int state, int hudMode, float stackMixRatio,
389             float gridMixRatio, MediaBucketList bucketList, boolean isFeedLoading) {
390         int firstBufferedVisibleSlot = mBufferedVisibleRange.begin;
391         int lastBufferedVisibleSlot = mBufferedVisibleRange.end;
392         int firstVisibleSlot = mVisibleRange.begin;
393         int lastVisibleSlot = mVisibleRange.end;
394         DisplayItem[] displayItems = mDisplayItems;
395         GridDrawables drawables = mDrawables;
396
397         // We draw the frames around the drawn items.
398         boolean currentFocusIsPressed = mCurrentFocusIsPressed;
399         if (state != GridLayer.STATE_FULL_SCREEN) {
400             GridDrawables.sFrame.bindArrays(gl);
401             Texture texturePlaceHolder = (state == GridLayer.STATE_GRID_VIEW) ? drawables.mTextureGridFrame
402                     : drawables.mTextureFrame;
403             for (int i = firstBufferedVisibleSlot; i <= lastBufferedVisibleSlot; ++i) {
404                 if (i < firstVisibleSlot || i > lastVisibleSlot) {
405                     continue;
406                 }
407                 boolean slotIsAlive = false;
408                 if (state != GridLayer.STATE_MEDIA_SETS && state != GridLayer.STATE_TIMELINE) {
409                     for (int j = 0; j < GridLayer.MAX_DISPLAYED_ITEMS_PER_SLOT; ++j) {
410                         DisplayItem displayItem = displayItems[(i - firstBufferedVisibleSlot) * GridLayer.MAX_ITEMS_PER_SLOT + j];
411                         if (displayItem != null) {
412                             slotIsAlive |= displayItem.mAlive;
413                         }
414                     }
415                     if (!slotIsAlive) {
416                         DisplayItem displayItem = displayItems[(i - firstBufferedVisibleSlot) * GridLayer.MAX_ITEMS_PER_SLOT];
417                         if (displayItem != null) {
418                             drawDisplayItem(view, gl, displayItem, texturePlaceHolder, PASS_FRAME_PLACEHOLDER, null, 0);
419                         }
420                     }
421                 }
422             }
423             Texture texturePressed = drawables.mTextureFramePressed;
424             Texture textureFocus = drawables.mTextureFrameFocus;
425             Texture textureGrid = drawables.mTextureGridFrame;
426             Texture texture = drawables.mTextureFrame;
427
428             int drawnCounter = mDrawnCounter;
429             DisplayItem[] itemsDrawn = mItemsDrawn;
430             if (texture != null) {
431                 if (drawnCounter > 0) {
432                     Arrays.sort(itemsDrawn, 0, drawnCounter, sDisplayItemComparator);
433                     float timeElapsedSinceGridView = gridMixRatio;
434                     float timeElapsedSinceStackView = stackMixRatio;
435                     for (int i = drawnCounter - 1; i >= 0; --i) {
436                         DisplayItem itemDrawn = itemsDrawn[i];
437                         if (itemDrawn == null) {
438                             continue;
439                         }
440                         boolean displayItemPresentInSelectedItems = bucketList.find(itemDrawn.mItemRef);
441                         Texture previousTexture = (displayItemPresentInSelectedItems) ? texturePressed : texture;
442                         Texture textureToUse = (itemDrawn.getHasFocus()) ? (currentFocusIsPressed ? texturePressed : textureFocus)
443                                 : ((displayItemPresentInSelectedItems) ? texturePressed : textureGrid);
444                         float ratio = timeElapsedSinceGridView;
445                         if (itemDrawn.mAlive) {
446                             if (state != GridLayer.STATE_GRID_VIEW) {
447                                 previousTexture = (displayItemPresentInSelectedItems) ? texturePressed : texture;
448                                 textureToUse = (itemDrawn.getHasFocus()) ? (currentFocusIsPressed ? texturePressed : textureFocus)
449                                         : previousTexture;
450                                 if (timeElapsedSinceStackView == 1.0f) {
451                                     ratio = mFocusMixRatio;
452                                 } else {
453                                     ratio = timeElapsedSinceStackView;
454                                     previousTexture = textureGrid;
455                                 }
456                             }
457                             drawDisplayItem(view, gl, itemDrawn, textureToUse, PASS_FRAME, previousTexture, ratio);
458                         }
459                     }
460                 }
461             }
462             GridDrawables.sFrame.unbindArrays(gl);
463             gl.glDepthFunc(GL10.GL_ALWAYS);
464             if (state == GridLayer.STATE_MEDIA_SETS || state == GridLayer.STATE_TIMELINE) {
465                 DisplaySlot[] displaySlots = mDisplaySlots;
466                 GridDrawables.sTextGrid.bindArrays(gl);
467                 final float textOffsetY = 0.82f;
468                 gl.glTranslatef(0.0f, -textOffsetY, 0.0f);
469                 HashMap<String, StringTexture> stringTextureTable = GridDrawables.sStringTextureTable;
470                 ReverseGeocoder reverseGeocoder = ((Gallery) view.getContext()).getReverseGeocoder();
471
472                 boolean itemsPresent = false;
473
474                 for (int i = firstBufferedVisibleSlot; i <= lastBufferedVisibleSlot; ++i) {
475                     itemsPresent = true;
476                     DisplayItem displayItem = displayItems[(i - firstBufferedVisibleSlot) * GridLayer.MAX_ITEMS_PER_SLOT];
477                     if (displayItem != null) {
478                         DisplaySlot displaySlot = displaySlots[i - firstBufferedVisibleSlot];
479                         Texture textureString = displaySlot.getTitleImage(stringTextureTable);
480                         view.loadTexture(textureString);
481                         if (textureString != null) {
482                             if (i < firstVisibleSlot || i > lastVisibleSlot) {
483                                 continue;
484                             }
485                             drawDisplayItem(view, gl, displayItem, textureString, PASS_TEXT_LABEL, null, 0);
486                         }
487
488                     }
489                 }
490
491                 if (!itemsPresent && !isFeedLoading) {
492                     // Draw the no items texture.
493                     int wWidth = view.getWidth();
494                     int wHeight = view.getHeight();
495
496                     // Size this to be 40 pxls less than screen width
497                     mNoItemsTexture.mWidth = wWidth - 40;
498
499                     int x = (int) Math.floor((wWidth / 2) - (mNoItemsTexture.getWidth() / 2));
500                     int y = (int) Math.floor((wHeight / 2) - (mNoItemsTexture.getHeight() / 2));
501                     view.draw2D(mNoItemsTexture, x, y);
502                 }
503
504                 float yLocOffset = 0.2f;
505                 gl.glTranslatef(0.0f, -yLocOffset, 0.0f);
506                 for (int i = firstBufferedVisibleSlot; i <= lastBufferedVisibleSlot; ++i) {
507                     DisplayItem displayItem = displayItems[(i - firstBufferedVisibleSlot) * GridLayer.MAX_ITEMS_PER_SLOT];
508                     if (displayItem != null) {
509                         DisplaySlot displaySlot = displaySlots[i - firstBufferedVisibleSlot];
510                         StringTexture textureString = displaySlot.getLocationImage(reverseGeocoder, stringTextureTable);
511                         if (textureString != null) {
512                             drawDisplayItem(view, gl, displayItem, textureString, PASS_TEXT_LABEL, null, 0);
513                         }
514                     }
515                 }
516                 if (state == GridLayer.STATE_TIMELINE) {
517                     GridDrawables.sLocationGrid.bindArrays(gl);
518                     Texture locationTexture = drawables.mTextureLocation;
519                     final float yLocationLabelOffset = 0.19f;
520                     for (int i = firstBufferedVisibleSlot; i <= lastBufferedVisibleSlot; ++i) {
521                         DisplayItem displayItem = displayItems[(i - firstBufferedVisibleSlot) * GridLayer.MAX_ITEMS_PER_SLOT];
522                         if (displayItem != null) {
523                             if (displayItem.mAlive == true) {
524                                 DisplaySlot displaySlot = displaySlots[i - firstBufferedVisibleSlot];
525                                 if (displaySlot.hasValidLocation()) {
526                                     StringTexture textureString = displaySlot.getLocationImage(reverseGeocoder, stringTextureTable);
527                                     float textWidth = (textureString != null) ? textureString.computeTextWidth() : 0;
528                                     textWidth *= (mCamera.mOneByScale * 0.5f);
529                                     if (textWidth == 0.0f) {
530                                         textWidth -= 0.18f;
531                                     }
532                                     textWidth += 0.1f;
533                                     gl.glTranslatef(textWidth, -yLocationLabelOffset, 0.0f);
534                                     drawDisplayItem(view, gl, displayItem, locationTexture, PASS_LOCATION_LABEL, null, 0);
535                                     gl.glTranslatef(-textWidth, yLocationLabelOffset, 0.0f);
536                                 }
537                             }
538                         }
539                     }
540
541                     GridDrawables.sLocationGrid.unbindArrays(gl);
542                 } else if (state == GridLayer.STATE_MEDIA_SETS && stackMixRatio > 0.0f) {
543                     GridDrawables.sSourceIconGrid.bindArrays(gl);
544                     Texture transparentTexture = drawables.mTextureTransparent;
545                     for (int i = firstBufferedVisibleSlot; i <= lastBufferedVisibleSlot; ++i) {
546                         DisplayItem displayItem = displayItems[(i - firstBufferedVisibleSlot) * GridLayer.MAX_ITEMS_PER_SLOT];
547                         if (displayItem != null) {
548                             if (displayItem.mAlive == true) {
549                                 DisplaySlot displaySlot = displaySlots[i - firstBufferedVisibleSlot];
550                                 Texture locationTexture = view.getResource(drawables
551                                         .getIconForSet(displaySlot.getMediaSet(), false), false);
552
553                                 // Draw the icon at 0.85 alpha over the top item in the stack.
554                                 gl.glTranslatef(0.24f, 0.5f, 0);
555                                 drawDisplayItem(view, gl, displayItem, locationTexture, PASS_MEDIASET_SOURCE_LABEL,
556                                         transparentTexture, 0.85f);
557                                 gl.glTranslatef(-0.24f, -0.5f, 0);
558                             }
559                         }
560                     }
561                     GridDrawables.sSourceIconGrid.unbindArrays(gl);
562                 }
563                 gl.glTranslatef(0.0f, yLocOffset, 0.0f);
564                 gl.glTranslatef(0.0f, textOffsetY, 0.0f);
565                 GridDrawables.sTextGrid.unbindArrays(gl);
566             }
567             if (hudMode == HudLayer.MODE_SELECT && state != GridLayer.STATE_FULL_SCREEN) {
568                 Texture textureSelectedOn = drawables.mTextureCheckmarkOn;
569                 Texture textureSelectedOff = drawables.mTextureCheckmarkOff;
570                 view.prime(textureSelectedOn, true);
571                 view.prime(textureSelectedOff, true);
572                 GridDrawables.sSelectedGrid.bindArrays(gl);
573                 for (int i = firstBufferedVisibleSlot; i <= lastBufferedVisibleSlot; ++i) {
574                     DisplayItem displayItem = displayItems[(i - firstBufferedVisibleSlot) * GridLayer.MAX_ITEMS_PER_SLOT];
575                     if (displayItem != null) {
576                         Texture textureToUse = bucketList.find(displayItem.mItemRef) ? textureSelectedOn : textureSelectedOff;
577                         drawDisplayItem(view, gl, displayItem, textureToUse, PASS_SELECTION_LABEL, null, 0);
578                     }
579                 }
580                 GridDrawables.sSelectedGrid.unbindArrays(gl);
581             }
582             GridDrawables.sVideoGrid.bindArrays(gl);
583             Texture videoTexture = drawables.mTextureVideo;
584             for (int i = firstBufferedVisibleSlot; i <= lastBufferedVisibleSlot; ++i) {
585                 DisplayItem displayItem = displayItems[(i - firstBufferedVisibleSlot) * GridLayer.MAX_ITEMS_PER_SLOT];
586                 if (displayItem != null && displayItem.mAlive) {
587                     if (displayItem.mItemRef.getMediaType() == MediaItem.MEDIA_TYPE_VIDEO) {
588                         drawDisplayItem(view, gl, displayItem, videoTexture, PASS_VIDEO_LABEL, null, 0);
589                     }
590                 }
591             }
592             GridDrawables.sVideoGrid.unbindArrays(gl);
593             gl.glDepthFunc(GL10.GL_LEQUAL);
594         }
595     }
596
597     private void drawDisplayItem(RenderView view, GL11 gl, DisplayItem displayItem, Texture texture, int pass,
598             Texture previousTexture, float mixRatio) {
599         GridCamera camera = mCamera;
600         Vector3f animatedPosition = displayItem.mAnimatedPosition;
601         float translateXf = animatedPosition.x * camera.mOneByScale;
602         float translateYf = animatedPosition.y * camera.mOneByScale;
603         float translateZf = -animatedPosition.z;
604         int stackId = displayItem.getStackIndex();
605         if (pass == PASS_PLACEHOLDER || pass == PASS_FRAME_PLACEHOLDER) {
606             translateZf = -0.04f;
607         } else {
608             if (pass == PASS_FRAME)
609                 translateZf += 0.02f;
610             if ((pass == PASS_TEXT_LABEL || pass == PASS_LOCATION_LABEL || pass == PASS_SELECTION_LABEL) && !displayItem.isAlive()) {
611                 translateZf = 0.0f;
612             }
613             if (pass == PASS_TEXT_LABEL) {
614                 translateZf = 0.0f;
615             }
616         }
617         boolean usingMixedTextures = false;
618         boolean bind = false;
619         if ((pass != PASS_THUMBNAIL_CONTENT)
620                 || (stackId < GridLayer.MAX_DISPLAYED_ITEMS_PER_SLOT && texture.isLoaded() && (previousTexture == null || previousTexture
621                         .isLoaded()))) {
622             if (mixRatio == 1.0f || previousTexture == null || texture == previousTexture) {
623                 bind = view.bind(texture);
624             } else if (mixRatio != 0.0f) {
625                 if (!texture.isLoaded() || !previousTexture.isLoaded()) {
626                     // Submit the previous texture to the load queue
627                     view.bind(previousTexture);
628                     bind = view.bind(texture);
629                 } else {
630                     usingMixedTextures = true;
631                     bind = view.bindMixed(previousTexture, texture, mixRatio);
632                 }
633             } else {
634                 bind = view.bind(previousTexture);
635             }
636         } else if (stackId >= GridLayer.MAX_DISPLAYED_ITEMS_PER_SLOT && pass == PASS_THUMBNAIL_CONTENT) {
637             mDisplayList.setAlive(displayItem, true);
638         }
639         if (!texture.isLoaded() || !bind) {
640             if (pass == PASS_THUMBNAIL_CONTENT) {
641                 if (previousTexture != null && previousTexture.isLoaded() && translateZf == 0.0f) {
642                     translateZf = -0.08f;
643                     bind |= view.bind(previousTexture);
644                 }
645                 if (!bind) {
646                     return;
647                 }
648             } else {
649                 return;
650             }
651         } else {
652             if (pass == PASS_THUMBNAIL_CONTENT || pass == PASS_FOCUS_CONTENT) {
653                 if (!displayItem.mAlive) {
654                     mDisplayList.setAlive(displayItem, true);
655                 }
656             }
657         }
658         gl.glTranslatef(-translateXf, -translateYf, -translateZf);
659         float theta = (pass == PASS_FOCUS_CONTENT) ? displayItem.mAnimatedImageTheta + displayItem.mAnimatedTheta
660                 : displayItem.mAnimatedTheta;
661         if (theta != 0.0f) {
662             gl.glRotatef(theta, 0.0f, 0.0f, 1.0f);
663         }
664         float orientation = 0.0f;
665         if (pass == PASS_THUMBNAIL_CONTENT && displayItem.mAnimatedImageTheta != 0.0f) {
666             orientation = displayItem.mAnimatedImageTheta;
667         }
668         if (pass == PASS_FRAME || pass == PASS_FRAME_PLACEHOLDER) {
669             GridQuadFrame.draw(gl);
670         } else {
671             GridQuad.draw(gl, orientation);
672         }
673         if (theta != 0.0f) {
674             gl.glRotatef(-theta, 0.0f, 0.0f, 1.0f);
675         }
676         gl.glTranslatef(translateXf, translateYf, translateZf);
677         if (usingMixedTextures) {
678             view.unbindMixed();
679         }
680     }
681 }