1/* 2 * Copyright 2018 Google Inc. All rights reserved. 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 17package androidx.heifwriter; 18 19import android.graphics.Rect; 20 21import java.nio.ByteBuffer; 22import java.nio.ByteOrder; 23import java.nio.FloatBuffer; 24 25/** 26 * This class represents a viewport-sized sprite that will be rendered with 27 * a subrect from a texture. 28 * 29 * @hide 30 */ 31public class EglRectBlt { 32 private static final int SIZEOF_FLOAT = 4; 33 34 /** 35 * A "full" square, extending from -1 to +1 in both dimensions. When the 36 * model/view/projection matrix is identity, this will exactly cover the viewport. 37 */ 38 private static final float FULL_RECTANGLE_COORDS[] = { 39 -1.0f, -1.0f, // 0 bottom left 40 1.0f, -1.0f, // 1 bottom right 41 -1.0f, 1.0f, // 2 top left 42 1.0f, 1.0f, // 3 top right 43 }; 44 45 private static final FloatBuffer FULL_RECTANGLE_BUF = 46 createFloatBuffer(FULL_RECTANGLE_COORDS); 47 48 private final float mTexCoords[] = new float[8]; 49 private final FloatBuffer mTexCoordArray = createFloatBuffer(mTexCoords); 50 private final int mTexWidth; 51 private final int mTexHeight; 52 53 private Texture2dProgram mProgram; 54 55 /** 56 * Allocates a direct float buffer, and populates it with the float array data. 57 */ 58 public static FloatBuffer createFloatBuffer(float[] coords) { 59 // Allocate a direct ByteBuffer, using 4 bytes per float, and copy coords into it. 60 ByteBuffer bb = ByteBuffer.allocateDirect(coords.length * SIZEOF_FLOAT); 61 bb.order(ByteOrder.nativeOrder()); 62 FloatBuffer fb = bb.asFloatBuffer(); 63 fb.put(coords); 64 fb.position(0); 65 return fb; 66 } 67 68 /** 69 * Prepares the object. 70 * 71 * @param program The program to use. EglRectBlitter takes ownership, and will release 72 * the program when no longer needed. 73 */ 74 public EglRectBlt(Texture2dProgram program, int texWidth, int texHeight) { 75 mProgram = program; 76 77 mTexWidth = texWidth; 78 mTexHeight = texHeight; 79 } 80 81 /** 82 * Releases resources. 83 * <p> 84 * This must be called with the appropriate EGL context current (i.e. the one that was 85 * current when the constructor was called). If we're about to destroy the EGL context, 86 * there's no value in having the caller make it current just to do this cleanup, so you 87 * can pass a flag that will tell this function to skip any EGL-context-specific cleanup. 88 */ 89 public void release(boolean doEglCleanup) { 90 if (mProgram != null) { 91 if (doEglCleanup) { 92 mProgram.release(); 93 } 94 mProgram = null; 95 } 96 } 97 98 /** 99 * Creates a texture object suitable for use with drawFrame(). 100 */ 101 public int createTextureObject() { 102 return mProgram.createTextureObject(); 103 } 104 105 /** 106 * Draws a viewport-filling rect, texturing it with the specified texture object and rect. 107 */ 108 public void copyRect(int textureId, float[] texMatrix, Rect texRect) { 109 setTexRect(texRect); 110 111 // Use the identity matrix for MVP so our 2x2 FULL_RECTANGLE covers the viewport. 112 mProgram.draw(Texture2dProgram.IDENTITY_MATRIX, FULL_RECTANGLE_BUF, 0, 113 4, 2, 2 * SIZEOF_FLOAT, 114 texMatrix, mTexCoordArray, textureId, 2 * SIZEOF_FLOAT); 115 } 116 117 void setTexRect(Rect rect) { 118 mTexCoords[0] = rect.left / (float)mTexWidth; 119 mTexCoords[1] = 1.0f - rect.bottom / (float)mTexHeight; 120 mTexCoords[2] = rect.right / (float)mTexWidth; 121 mTexCoords[3] = 1.0f - rect.bottom / (float)mTexHeight; 122 mTexCoords[4] = rect.left / (float)mTexWidth; 123 mTexCoords[5] = 1.0f - rect.top / (float)mTexHeight; 124 mTexCoords[6] = rect.right / (float)mTexWidth; 125 mTexCoords[7] = 1.0f - rect.top / (float)mTexHeight; 126 127 mTexCoordArray.put(mTexCoords); 128 mTexCoordArray.position(0); 129 } 130} 131