blob: 3759011f4aed20d5e7006b70c6b8021c6377050b [file] [log] [blame]
/*
* 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.
* <p>
* 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);
}
}