private void uploadToGL(GL11 gl) throws GLOutOfMemoryException { Bitmap bitmap = getBitmap(); int glError = GL11.GL_NO_ERROR; if (bitmap != null) { int[] textureId = new int[1]; try { // Define a vertically flipped crop rectangle for // OES_draw_texture. int width = bitmap.getWidth(); int height = bitmap.getHeight(); int[] cropRect = {0, height, width, -height}; // Upload the bitmap to a new texture. gl.glGenTextures(1, textureId, 0); gl.glBindTexture(GL11.GL_TEXTURE_2D, textureId[0]); gl.glTexParameteriv(GL11.GL_TEXTURE_2D, GL11Ext.GL_TEXTURE_CROP_RECT_OES, cropRect, 0); gl.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_S, GL11.GL_CLAMP_TO_EDGE); gl.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_T, GL11.GL_CLAMP_TO_EDGE); gl.glTexParameterf(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MIN_FILTER, GL11.GL_LINEAR); gl.glTexParameterf(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MAG_FILTER, GL11.GL_LINEAR); int widthExt = Util.nextPowerOf2(width); int heightExt = Util.nextPowerOf2(height); int format = GLUtils.getInternalFormat(bitmap); int type = GLUtils.getType(bitmap); mTextureWidth = widthExt; mTextureHeight = heightExt; gl.glTexImage2D(GL11.GL_TEXTURE_2D, 0, format, widthExt, heightExt, 0, format, type, null); GLUtils.texSubImage2D(GL11.GL_TEXTURE_2D, 0, 0, 0, bitmap, format, type); } finally { freeBitmap(bitmap); } if (glError == GL11.GL_OUT_OF_MEMORY) { throw new GLOutOfMemoryException(); } if (glError != GL11.GL_NO_ERROR) { mId = 0; mState = STATE_UNLOADED; throw new RuntimeException("Texture upload fail, glError " + glError); } else { // Update texture state. mGL = gl; mId = textureId[0]; mState = BitmapTexture.STATE_LOADED; } } else { mState = STATE_ERROR; throw new RuntimeException("Texture load fail, no bitmap"); } }
public void copyTexture2D(RawTexture texture, int x, int y, int width, int height) throws GLOutOfMemoryException { Matrix matrix = mTransformation.getMatrix(); matrix.getValues(mMatrixValues); if (isMatrixRotatedOrFlipped(mMatrixValues)) { throw new IllegalArgumentException("cannot support rotated matrix"); } float points[] = mapPoints(matrix, x, y + height, x + width, y); x = (int) points[0]; y = (int) points[1]; width = (int) points[2] - x; height = (int) points[3] - y; GL11 gl = mGL; int newWidth = Util.nextPowerOf2(width); int newHeight = Util.nextPowerOf2(height); int glError = GL11.GL_NO_ERROR; gl.glBindTexture(GL11.GL_TEXTURE_2D, texture.getId()); int[] cropRect = {0, 0, width, height}; gl.glTexParameteriv(GL11.GL_TEXTURE_2D, GL11Ext.GL_TEXTURE_CROP_RECT_OES, cropRect, 0); gl.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_S, GL11.GL_CLAMP_TO_EDGE); gl.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_T, GL11.GL_CLAMP_TO_EDGE); gl.glTexParameterf(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MIN_FILTER, GL11.GL_LINEAR); gl.glTexParameterf(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MAG_FILTER, GL11.GL_LINEAR); gl.glCopyTexImage2D(GL11.GL_TEXTURE_2D, 0, GL11.GL_RGBA, x, y, newWidth, newHeight, 0); glError = gl.glGetError(); if (glError == GL11.GL_OUT_OF_MEMORY) { throw new GLOutOfMemoryException(); } if (glError != GL11.GL_NO_ERROR) { throw new RuntimeException("Texture copy fail, glError " + glError); } texture.setSize(width, height); texture.setTextureSize(newWidth, newHeight); }
/** * Stretches the texture according to the nine-patch rules. It will linearly distribute the * strechy parts defined in the nine-patch chunk to the target area. * * <pre> * source * /--------------^---------------\ * u0 u1 u2 u3 u4 u5 * div ---> |fffff|ssssssss|fff|ssssss|ffff| ---> u * | div0 div1 div2 div3 | * | | / / / / * | | / / / / * | | / / / / * |fffff|ssss|fff|sss|ffff| ---> x * x0 x1 x2 x3 x4 x5 * \----------v------------/ * target * * f: fixed segment * s: stretchy segment * </pre> * * @param div the stretch parts defined in nine-patch chunk * @param source the length of the texture * @param target the length on the drawing plan * @param u output, the positions of these dividers in the texture coordinate * @param x output, the corresponding position of these dividers on the drawing plan * @return the number of these dividers. */ private int stretch(int x[], float u[], int div[], int source, int target) { int textureSize = Util.nextPowerOf2(source); float textureBound = (source - 0.5f) / textureSize; int stretch = 0; for (int i = 0, n = div.length; i < n; i += 2) { stretch += div[i + 1] - div[i]; } float remaining = target - source + stretch; int lastX = 0; int lastU = 0; x[0] = 0; u[0] = 0; for (int i = 0, n = div.length; i < n; i += 2) { // fixed segment x[i + 1] = lastX + (div[i] - lastU); u[i + 1] = Math.min((float) div[i] / textureSize, textureBound); // stretchy segment float partU = div[i + 1] - div[i]; int partX = (int) (remaining * partU / stretch + 0.5f); remaining -= partX; stretch -= partU; lastX = x[i + 1] + partX; lastU = div[i + 1]; x[i + 2] = lastX; u[i + 2] = Math.min((float) lastU / textureSize, textureBound); } // the last fixed segment x[div.length + 1] = target; u[div.length + 1] = textureBound; // remove segments with length 0. int last = 0; for (int i = 1, n = div.length + 2; i < n; ++i) { if (x[last] == x[i]) continue; x[++last] = x[i]; u[last] = u[i]; } return last + 1; }