/* * Copyright 2018 Google Inc. All rights reserved. * * 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 androidx.heifwriter; import android.graphics.Rect; import java.nio.ByteBuffer; import java.nio.ByteOrder; import java.nio.FloatBuffer; /** * This class represents a viewport-sized sprite that will be rendered with * a subrect from a texture. * * @hide */ public class EglRectBlt { private static final int SIZEOF_FLOAT = 4; /** * A "full" square, extending from -1 to +1 in both dimensions. When the * model/view/projection matrix is identity, this will exactly cover the viewport. */ private static final float FULL_RECTANGLE_COORDS[] = { -1.0f, -1.0f, // 0 bottom left 1.0f, -1.0f, // 1 bottom right -1.0f, 1.0f, // 2 top left 1.0f, 1.0f, // 3 top right }; private static final FloatBuffer FULL_RECTANGLE_BUF = createFloatBuffer(FULL_RECTANGLE_COORDS); private final float mTexCoords[] = new float[8]; private final FloatBuffer mTexCoordArray = createFloatBuffer(mTexCoords); private final int mTexWidth; private final int mTexHeight; private Texture2dProgram mProgram; /** * Allocates a direct float buffer, and populates it with the float array data. */ public static FloatBuffer createFloatBuffer(float[] coords) { // Allocate a direct ByteBuffer, using 4 bytes per float, and copy coords into it. ByteBuffer bb = ByteBuffer.allocateDirect(coords.length * SIZEOF_FLOAT); bb.order(ByteOrder.nativeOrder()); FloatBuffer fb = bb.asFloatBuffer(); fb.put(coords); fb.position(0); return fb; } /** * Prepares the object. * * @param program The program to use. EglRectBlitter takes ownership, and will release * the program when no longer needed. */ public EglRectBlt(Texture2dProgram program, int texWidth, int texHeight) { mProgram = program; mTexWidth = texWidth; mTexHeight = texHeight; } /** * Releases resources. *

* This must be called with the appropriate EGL context current (i.e. the one that was * current when the constructor was called). If we're about to destroy the EGL context, * there's no value in having the caller make it current just to do this cleanup, so you * can pass a flag that will tell this function to skip any EGL-context-specific cleanup. */ public void release(boolean doEglCleanup) { if (mProgram != null) { if (doEglCleanup) { mProgram.release(); } mProgram = null; } } /** * Creates a texture object suitable for use with drawFrame(). */ public int createTextureObject() { return mProgram.createTextureObject(); } /** * Draws a viewport-filling rect, texturing it with the specified texture object and rect. */ public void copyRect(int textureId, float[] texMatrix, Rect texRect) { setTexRect(texRect); // Use the identity matrix for MVP so our 2x2 FULL_RECTANGLE covers the viewport. mProgram.draw(Texture2dProgram.IDENTITY_MATRIX, FULL_RECTANGLE_BUF, 0, 4, 2, 2 * SIZEOF_FLOAT, texMatrix, mTexCoordArray, textureId, 2 * SIZEOF_FLOAT); } void setTexRect(Rect rect) { mTexCoords[0] = rect.left / (float)mTexWidth; mTexCoords[1] = 1.0f - rect.bottom / (float)mTexHeight; mTexCoords[2] = rect.right / (float)mTexWidth; mTexCoords[3] = 1.0f - rect.bottom / (float)mTexHeight; mTexCoords[4] = rect.left / (float)mTexWidth; mTexCoords[5] = 1.0f - rect.top / (float)mTexHeight; mTexCoords[6] = rect.right / (float)mTexWidth; mTexCoords[7] = 1.0f - rect.top / (float)mTexHeight; mTexCoordArray.put(mTexCoords); mTexCoordArray.position(0); } }