Home | History | Annotate | Download | only in heifwriter
      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 
     17 package androidx.heifwriter;
     18 
     19 import android.graphics.Rect;
     20 
     21 import java.nio.ByteBuffer;
     22 import java.nio.ByteOrder;
     23 import 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  */
     31 public 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