// Copyright 2008 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package com.google.android.stardroid.renderer.util; import android.util.Log; import java.io.PrintWriter; import java.io.StringWriter; import java.nio.Buffer; import javax.microedition.khronos.opengles.GL11; /** * This is a utility class which encapsulates and OpenGL buffer object. Several other classes * need to be able to lazily create OpenGL buffers, so this class takes care of the work of lazily * creating and updating them. * * @author jpowell * */ public class GLBuffer { // TODO(jpowell): This is ugly, we should have a buffer factory which knows // this rather than a static constant. I should refactor this accordingly // when I get a chance. private static boolean sCanUseVBO = false; private Buffer mBuffer = null; private int mBufferSize = 0; private int mGLBufferID = -1; private int mBufferType; private boolean mHasLoggedStackTraceOnError = false; GLBuffer(int bufferType) { mBufferType = bufferType; } public static void setCanUseVBO(boolean canUseVBO) { sCanUseVBO = canUseVBO; } // A caller should verify that this returns true before using a GLBuffer. // If this returns false, any operation using the VBO will be a no-op. public static boolean canUseVBO() { return sCanUseVBO; } // Unset any GL buffer which is set on the device. You need to call this if you want to render // without VBOs. Otherwise it will try to use whatever buffer is currently set. public static void unbind(GL11 gl) { if (canUseVBO()) { gl.glBindBuffer(GL11.GL_ARRAY_BUFFER, 0); gl.glBindBuffer(GL11.GL_ELEMENT_ARRAY_BUFFER, 0); } } public void bind(GL11 gl, Buffer buffer, int bufferSize) { if (canUseVBO()) { maybeRegenerateBuffer(gl, buffer, bufferSize); gl.glBindBuffer(mBufferType, mGLBufferID); } else { Log.e("GLBuffer", "Trying to use a VBO, but they are unsupported"); // Log a stack trace the first time we see this for any given buffer. if (!mHasLoggedStackTraceOnError) { StringWriter writer = new StringWriter(); new Throwable().printStackTrace(new PrintWriter(writer)); Log.e("SkyRenderer", writer.toString()); mHasLoggedStackTraceOnError = true; } } } public void reload() { // Just reset all of the values so we'll reload on the next call // to maybeRegenerateBuffer. mBuffer = null; mBufferSize = 0; mGLBufferID = -1; } private void maybeRegenerateBuffer(GL11 gl, Buffer buffer, int bufferSize) { if (buffer != mBuffer || bufferSize != mBufferSize) { mBuffer = buffer; mBufferSize = bufferSize; // Allocate the buffer ID if we don't already have one. if (mGLBufferID == -1) { int[] buffers = new int[1]; gl.glGenBuffers(1, buffers, 0); mGLBufferID = buffers[0]; } gl.glBindBuffer(mBufferType, mGLBufferID); gl.glBufferData(mBufferType, bufferSize, buffer, GL11.GL_STATIC_DRAW); } } }