-
-
Save denisdemaisbr/74307c13c8ebd0c21ffa5487ad77d49d to your computer and use it in GitHub Desktop.
Render to screen using FrameBuffer using OpenGL ES 2.0
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
LOCAL_PATH := $(call my-dir) | |
include $(CLEAR_VARS) | |
LOCAL_MODULE := FriengerScreenRecord | |
LOCAL_SRC_FILES := Log.cpp CustomFrameBuffer.cpp CustomFrameTexture.cpp FriengerScreenRecord.cpp | |
LOCAL_CFLAGS := -Werror -std=gnu++11 | |
LOCAL_LDLIBS := -llog -lGLESv2 | |
include $(BUILD_SHARED_LIBRARY) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <CustomFrameBuffer.h> | |
void CustomFrameBuffer::setResolution(int width, int height) { | |
printLog(DEBUG, "set resolution to FrameBuffer: width=%d, height=%d", width, height); | |
if (this->framebuffer != -1) { | |
release(); | |
} | |
GLuint *glValues; | |
glValues = (GLuint *) malloc(sizeof(GLuint)); | |
glGenTextures(1, glValues); | |
checkGlError("glGenTextures"); | |
this->offScreenTexture = *glValues; | |
free(glValues); | |
glBindTexture(GL_TEXTURE_2D, this->offScreenTexture); | |
checkGlError("glBindTexture"); | |
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); | |
checkGlError("glTexImage2D"); | |
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); | |
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); | |
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); | |
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); | |
// get previous gl state | |
GLint *glState; | |
glState = (GLint *) malloc(sizeof(GLint)); | |
glGetIntegerv(GL_FRAMEBUFFER_BINDING, glState); | |
checkGlError("get current FrameBuffer binding %d", glState); | |
this->defaultFBO = *glState; | |
free(glState); | |
glValues = (GLuint *) malloc(sizeof(GLuint)); | |
glGetIntegerv(GL_RENDERBUFFER_BINDING, glState); | |
checkGlError("get current RenderBuffer binding %d", glState); | |
this->defaultRenderBuffer = *glState; | |
free(glState); | |
glValues = (GLuint *) malloc(sizeof(GLuint)); | |
glGenFramebuffers(1, glValues); | |
checkGlError("glGenFramebuffers"); | |
this->framebuffer = *glValues; | |
free(glValues); | |
glBindFramebuffer(GL_FRAMEBUFFER, this->framebuffer); | |
checkGlError("glBindFramebuffer"); | |
glValues = (GLuint *) malloc(sizeof(GLuint)); | |
glGenRenderbuffers(1, glValues); | |
checkGlError("glGenRenderbuffers"); | |
this->depthBuffer = *glValues; | |
free(glValues); | |
glBindRenderbuffer(GL_RENDERBUFFER, this->depthBuffer); | |
checkGlError("glBindRenderbuffer"); | |
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, width, height); | |
checkGlError("glRenderbufferStorage"); | |
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, | |
GL_RENDERBUFFER, this->depthBuffer); | |
checkGlError("glFramebufferRenderbuffer"); | |
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, | |
this->offScreenTexture, 0); | |
checkGlError("glFramebufferTexture2D"); | |
int status = glCheckFramebufferStatus(GL_FRAMEBUFFER); | |
checkGlError("glCheckFramebufferStatus"); | |
if (status != GL_FRAMEBUFFER_COMPLETE) { | |
printLog(ERROR, "failed when create frame buffer"); | |
} | |
// restore 2 current Unity FBO, renderbuffer | |
glBindFramebuffer(GL_FRAMEBUFFER, this->defaultFBO); | |
checkGlError("glBindFramebuffer to default value:%d", this->defaultFBO); | |
glBindRenderbuffer(GL_RENDERBUFFER, this->defaultRenderBuffer); | |
checkGlError("glBindRenderbuffer to default value:%d", this->defaultRenderBuffer); | |
} | |
int CustomFrameBuffer::getOffScreenTexture() { | |
return this->offScreenTexture; | |
} | |
void CustomFrameBuffer::bind() { | |
glViewport(0, 0, this->width, this->height); | |
// get default Unity FBO | |
GLint *temp; | |
temp =(GLint *)malloc(sizeof(GLint)); | |
glGetIntegerv(GL_FRAMEBUFFER_BINDING, temp); | |
checkGlError("get default Unity FBO"); | |
this->defaultFBO = *temp; | |
free(temp); | |
temp =(GLint *)malloc(sizeof(GLint)); | |
glGetIntegerv(GL_RENDERBUFFER_BINDING, temp); | |
checkGlError("get default render buffer"); | |
this->defaultRenderBuffer = *temp; | |
free(temp); | |
glBindFramebuffer(GL_FRAMEBUFFER, this->framebuffer); | |
checkGlError("bind custom FBO:%d", this->framebuffer); | |
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); | |
checkGlError("clear buffer"); | |
} | |
void CustomFrameBuffer::unbind() { | |
// restore 2 current Unity FBO, renderbuffer | |
glBindFramebuffer(GL_FRAMEBUFFER, defaultFBO); | |
checkGlError("glBindFramebuffer(default:%d)", defaultFBO); | |
glBindRenderbuffer(GL_RENDERBUFFER, defaultRenderBuffer); | |
checkGlError("glBindRenderbuffer (default:%d)", defaultRenderBuffer); | |
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); | |
checkGlError("clear buffer"); | |
} | |
void CustomFrameBuffer::release() { | |
GLuint *glValues ; | |
if (this->offScreenTexture > 0) { | |
glValues = (GLuint *) malloc(sizeof(GLuint)); | |
*glValues = this->offScreenTexture; | |
glDeleteBuffers(1, glValues); | |
this->offScreenTexture = -1; | |
free(glValues); | |
} | |
if (this->framebuffer > 0) { | |
glValues = (GLuint *) malloc(sizeof(GLuint)); | |
*glValues = this->framebuffer; | |
glDeleteFramebuffers(1, glValues); | |
this->framebuffer = -1; | |
free(glValues); | |
} | |
if (this->depthBuffer > 0) { | |
glValues = (GLuint *) malloc(sizeof(GLuint)); | |
*glValues = this->depthBuffer; | |
glDeleteRenderbuffers(1, glValues); | |
this->depthBuffer = -1; | |
free(glValues); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#ifndef CUSTOMFRAMEBUFFER_H_ | |
#define CUSTOMFRAMEBUFFER_H_ | |
#include <Log.h> | |
class CustomFrameBuffer { | |
// attribute | |
private: | |
int width; | |
int height; | |
int framebuffer; | |
int offScreenTexture; | |
int depthBuffer; | |
int defaultFBO; | |
int defaultRenderBuffer; | |
// method | |
public: | |
static CustomFrameBuffer& getInstance() { | |
static CustomFrameBuffer instance; | |
return instance; | |
} | |
void setResolution(int width, int height); | |
int getOffScreenTexture(); | |
void release(); | |
void bind(); | |
void unbind(); | |
private: | |
CustomFrameBuffer() { | |
this->defaultFBO = -1; | |
this->defaultRenderBuffer = -1; | |
this->depthBuffer = -1; | |
this->width = width; | |
this->height = height; | |
this->framebuffer = -1; | |
this->offScreenTexture = -1; | |
}; | |
CustomFrameBuffer(CustomFrameBuffer const &); | |
void operator=(CustomFrameBuffer const&); | |
}; | |
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <CustomFrameTexture.h> | |
const char CustomFrameTexture::VERTEXT_SHADER_EXT[] = "\n" | |
"attribute vec4 a_position;\n" | |
"uniform mat4 u_matrix;\n" | |
"\n\n" | |
"#ifdef GL_ES\nvarying mediump vec2 v_texCoord;\n" | |
"#else\nvarying vec2 v_texCoord;\n" | |
"#endif\n\n" | |
"void main()\n{\n" | |
" gl_Position = u_matrix * a_position;\n " | |
"v_texCoord =\n" | |
" 0.5*(a_position.xy + vec2(1.0, 1.0));\n}\n"; | |
const char CustomFrameTexture::FRAGMENT_SHADER_EXT[] = "\n" | |
"#ifdef GL_ES\nprecision lowp float;\n" | |
"#endif\n\n" | |
"varying vec2 v_texCoord;\n" | |
"uniform sampler2D u_texture;\n" | |
"\nvoid main()\n" | |
"{\n gl_FragColor = vec4( texture2D(u_texture,\n" | |
" v_texCoord).xyz, 1.0 );\n}\n"; | |
const float CustomFrameTexture::FLOAT_QUAD_COORDINATES[8] = { -1.0F, -1.0F, 1.0F, -1.0F, -1.0F, 1.0F, 1.0F, 1.0F }; | |
const int CustomFrameTexture::LOCAL_BYTE[4] = { 0, 1, 2, 3 }; | |
const float CustomFrameTexture::UNIFORM_DATA[16] = { 1.0F, 0.0F, 0.0F, 0.0F, 0.0F, 1.0F, 0.0F, 0.0F, 0.0F, 0.0F, 1.0F, 0.0F, 0.0F, 0.0F, 0.0F, 1.0F }; | |
void CustomFrameTexture::initCustomFrameTexture() { | |
printLog(DEBUG, "Initialize custom frame texture !"); | |
this->currProgram = glCreateProgram(); | |
checkGlError("create program %d", this->currProgram); | |
this->vertexShader = initShader(GL_VERTEX_SHADER, CustomFrameTexture::VERTEXT_SHADER_EXT); | |
if (this->vertexShader == 0) { | |
printLog(ERROR, "error when create vertex shader with source %s!!!", CustomFrameTexture::VERTEXT_SHADER_EXT); | |
return; | |
} | |
this->fragmentShader = initShader(GL_FRAGMENT_SHADER, CustomFrameTexture::FRAGMENT_SHADER_EXT); | |
if (this->fragmentShader == 0) { | |
printLog(ERROR, "error when create fragment shader witg source %s !!!", CustomFrameTexture::FRAGMENT_SHADER_EXT); | |
return; | |
} | |
// attach shader | |
glAttachShader(this->currProgram, this->vertexShader); | |
checkGlError("attach vertex shader"); | |
glAttachShader(this->currProgram, this->fragmentShader); | |
checkGlError("attach fragment shader"); | |
// create temporary array to use 4 save return value | |
GLint *tempArr; | |
tempArr = (GLint *) malloc(sizeof(GLint)); | |
// get max attributes of vertex | |
glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, tempArr); | |
this->maxVertexAttribs = *tempArr - 1; | |
// bind attributes location to last index of vertex attribute array | |
glBindAttribLocation(this->currProgram, this->maxVertexAttribs, "a_position"); | |
checkGlError("bind attribute location"); | |
// link program | |
glLinkProgram(this->currProgram); | |
checkGlError("link program " + currProgram); | |
// check shader link status of current program | |
getGlInfo(GL_LINK_STATUS); | |
// check validate status of current program | |
getGlInfo(GL_VALIDATE_STATUS); | |
// delete shader to reduce usage of memory | |
if (this->vertexShader != 0) { | |
glDeleteShader(this->vertexShader); | |
this->vertexShader = 0; | |
} | |
if (this->fragmentShader != 0) { | |
glDeleteShader(this->fragmentShader); | |
this->fragmentShader = 0; | |
} | |
// get previous state : openGL program, current binding array buffer, current binding element array buffer | |
free(tempArr); | |
tempArr = (GLint *) malloc(sizeof(GLint)); | |
glGetIntegerv(GL_CURRENT_PROGRAM, tempArr); | |
int previousProgram = *tempArr; | |
free(tempArr); | |
tempArr = (GLint *) malloc(sizeof(GLint)); | |
glGetIntegerv(GL_ARRAY_BUFFER_BINDING, tempArr); | |
int previousArrBuffBinding = *tempArr; | |
free(tempArr); | |
tempArr = (GLint *) malloc(sizeof(GLint)); | |
glGetIntegerv(GL_ELEMENT_ARRAY_BUFFER_BINDING, tempArr); | |
int previousElementArrBuffBinding = *tempArr; | |
free(tempArr); | |
// use our created program | |
glUseProgram(this->currProgram); | |
checkGlError("use current program %d", this->currProgram); | |
// get uniform location | |
this->textureLocation = glGetUniformLocation(this->currProgram, "u_texture"); | |
checkGlError("get texture location %d", this->textureLocation); | |
this->matrixLocation = glGetUniformLocation(this->currProgram, "u_matrix"); | |
checkGlError("get matrix location %d", this->matrixLocation); | |
// generate new array buffer, element array buffer then bind | |
GLuint *temp; | |
temp = (GLuint *) malloc(sizeof(GLuint)); | |
glGenBuffers(1, temp); | |
this->arrBuff = *temp; | |
free(temp); | |
temp = (GLuint *) malloc(sizeof(GLuint)); | |
glGenBuffers(1, temp); | |
this->elementArrBuff = *temp; | |
free(temp); | |
glBindBuffer(GL_ARRAY_BUFFER, this->arrBuff); | |
glBufferData(GL_ARRAY_BUFFER, sizeof(float) * 8, FLOAT_QUAD_COORDINATES, GL_STATIC_DRAW); | |
checkGlError("bind buffer data to array buffer %d", this->arrBuff); | |
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, this->elementArrBuff); | |
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(int) * 4, LOCAL_BYTE, GL_STATIC_DRAW); | |
checkGlError("bind buffer data to element array buffer %d", this->elementArrBuff); | |
// restore previous state | |
glBindBuffer(GL_ARRAY_BUFFER, previousArrBuffBinding); | |
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, previousElementArrBuffBinding); | |
glUseProgram(previousProgram); | |
} | |
GLuint CustomFrameTexture::initShader(GLenum type, const char* shaderTxt) { | |
GLint compiled; | |
if (shaderTxt == NULL){ | |
printLog(ERROR,"null shader"); | |
return 0; | |
} | |
int shader = glCreateShader(type); | |
checkGlError("create shader %d", shader); | |
// create shader then compile | |
glShaderSource(shader, 1, &shaderTxt, NULL); | |
checkGlError("attach shader source %s to shader %d", shaderTxt, shader); | |
glCompileShader(shader); | |
checkGlError("compile shader %d", shader); | |
// check compile status | |
glGetShaderiv(shader, GL_COMPILE_STATUS, &compiled); | |
if (!compiled) { | |
GLint infoLen = 0; | |
glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infoLen); | |
if (infoLen > 1) { | |
char* infoLog = (char *) malloc(sizeof(char) * infoLen); | |
glGetShaderInfoLog(shader, infoLen, NULL, infoLog); | |
printLog(ERROR, "Error compiling shader:\n%s\n", infoLog); | |
free(infoLog); | |
} | |
glDeleteShader(shader); | |
return 0; | |
} | |
return shader; | |
} | |
void CustomFrameTexture::draw2Screen(int textureId, int width, int height) { | |
/* get previous state : vertex attribute array enabled , current binding vertex attribute array, active texture, | |
* current 2d binding texture, current program, current binding element array buffer, current binding array buffer | |
*/ | |
// temp array that used to save return value | |
GLint *tempArr ; | |
tempArr = (GLint *) malloc(sizeof(GLint)); | |
glGetVertexAttribiv(this->maxVertexAttribs, GL_VERTEX_ATTRIB_ARRAY_ENABLED, tempArr); | |
int enableVertexAttribArray = *tempArr; | |
checkGlError("check vertex_attrib_enable: %d", enableVertexAttribArray); | |
free(tempArr); | |
tempArr = (GLint *) malloc(sizeof(GLint)); | |
glGetVertexAttribiv(this->maxVertexAttribs, GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING, tempArr); | |
int bindingVertexAtrribArray = *tempArr; | |
checkGlError("get vertex attributes array buffer binding %d", bindingVertexAtrribArray); | |
free(tempArr); | |
tempArr = (GLint *) malloc(sizeof(GLint)); | |
glGetIntegerv(GL_ACTIVE_TEXTURE, tempArr); | |
int activeTexture = *tempArr; | |
checkGlError("get active texture %d", activeTexture); | |
free(tempArr); | |
tempArr = (GLint *) malloc(sizeof(GLint)); | |
glGetIntegerv(GL_TEXTURE_BINDING_2D, tempArr); | |
int binding2DTexture = *tempArr; | |
checkGlError("get texture binding 2D %d", binding2DTexture); | |
free(tempArr); | |
tempArr = (GLint *) malloc(sizeof(GLint)); | |
glGetIntegerv(GL_CURRENT_PROGRAM, tempArr); | |
int previousProgram = *tempArr; | |
checkGlError("get current program %d", previousProgram); | |
free(tempArr); | |
tempArr = (GLint *) malloc(sizeof(GLint)); | |
glGetIntegerv(GL_ARRAY_BUFFER_BINDING, tempArr); | |
int arrayBufferBinding = *tempArr; | |
checkGlError("get array buffer binding %d", arrayBufferBinding); | |
free(tempArr); | |
tempArr = (GLint *) malloc(sizeof(GLint)); | |
glGetIntegerv(GL_ELEMENT_ARRAY_BUFFER_BINDING, tempArr); | |
int elementArrayBufferBinding = *tempArr; | |
checkGlError("get element array binding %d", elementArrayBufferBinding); | |
free(tempArr); | |
// disable Blend, cull face, depth test if enabled | |
int enableBlend = glIsEnabled(GL_BLEND); | |
if (enableBlend) | |
glDisable(GL_BLEND); | |
int enableCullFace = glIsEnabled(GL_CULL_FACE); | |
if (enableCullFace) | |
glDisable(GL_CULL_FACE); | |
int depthTest = glIsEnabled(GL_DEPTH_TEST); | |
if (depthTest) | |
glDisable(GL_DEPTH_TEST); | |
// get depth func, change value to GL_LESS | |
tempArr = (GLint *) malloc(sizeof(GLint)); | |
glGetIntegerv(GL_DEPTH_FUNC, tempArr); | |
int depthFunc = *tempArr; | |
if (depthFunc != GL_LESS) | |
glDepthFunc(GL_LESS); | |
free(tempArr); | |
// set viewport | |
glViewport(0, 0, width, height); | |
// bind texture using textureId | |
glActiveTexture(GL_TEXTURE0); | |
glBindTexture(GL_TEXTURE_2D, textureId); | |
// save previous texture state : min filter, mag filter, wrapS, wrapT | |
tempArr = (GLint *) malloc(sizeof(GLint)); | |
glGetTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, tempArr); | |
int textureMinFilter = *tempArr; | |
free(tempArr); | |
// set texture min filter to nearest | |
if (textureMinFilter != GL_NEAREST){ | |
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); | |
checkGlError("set texture parameter GL_TEXTURE_MIN_FILTER to GL_NEAREST"); | |
} | |
tempArr = (GLint *) malloc(sizeof(GLint)); | |
glGetTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, tempArr); | |
int textureMagFilter = *tempArr; | |
free(tempArr); | |
// set texture mag filter to nearest | |
if (textureMagFilter != GL_NEAREST){ | |
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); | |
checkGlError("set texture parameter GL_TEXTURE_MAG_FILTER to GL_NEAREST"); | |
} | |
tempArr = (GLint *) malloc(sizeof(GLint)); | |
glGetTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, tempArr); | |
int textureWrapS = *tempArr; | |
free(tempArr); | |
// set texture wrap S to clamp to edge | |
if (textureWrapS != GL_CLAMP_TO_EDGE){ | |
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); | |
checkGlError("set texture parameter GL_TEXTURE_WRAP_S to GL_CLAMP_TO_EDGE"); | |
} | |
tempArr = (GLint *) malloc(sizeof(GLint)); | |
glGetTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, tempArr); | |
int textureWrapT = *tempArr; | |
free(tempArr); | |
// set texture wrap T to clamp to edge | |
if (textureWrapT != GL_CLAMP_TO_EDGE){ | |
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); | |
checkGlError("set texture parameter GL_TEXTURE_WRAP_T to GL_CLAMP_TO_EDGE"); | |
} | |
// use our created program | |
if(glIsProgram(this->currProgram) != GL_TRUE){ | |
printLog(ERROR,"error using GL program: %d", this->currProgram); | |
} | |
glUseProgram(this->currProgram); | |
checkGlError("use program %d", this->currProgram); | |
// bind our created array buffer, element array buffer | |
glBindBuffer(GL_ARRAY_BUFFER, this->arrBuff); | |
checkGlError("bind array buffer "); | |
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, this->elementArrBuff); | |
checkGlError("bind element array buffer "); | |
// enable vertex attribute array with our created index | |
glEnableVertexAttribArray(this->maxVertexAttribs); | |
checkGlError("enable vertex attribute %d", this->maxVertexAttribs); | |
glVertexAttribPointer(this->maxVertexAttribs, 2, GL_FLOAT, false, 0, 0); | |
checkGlError("create a pointer 2 vertex attributes %d", this->maxVertexAttribs); | |
// modify uniform location matrix | |
glUniformMatrix4fv(this->matrixLocation, 0, false, this->UNIFORM_DATA); | |
checkGlError("uniform matrix "); | |
glUniform1i(this->textureLocation, 0); | |
checkGlError("uniform texture"); | |
// draw quad | |
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); | |
checkGlError("draw array with matrix location: %d " | |
"& texture location: %d & maxVertexAttribs: %d", this->matrixLocation, this->textureLocation, this->maxVertexAttribs); | |
// restore state | |
if (enableVertexAttribArray) | |
glEnableVertexAttribArray(this->maxVertexAttribs); | |
else | |
glDisableVertexAttribArray(this->maxVertexAttribs); | |
glBindBuffer(GL_ARRAY_BUFFER, bindingVertexAtrribArray); | |
glUseProgram(previousProgram); | |
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, elementArrayBufferBinding); | |
glBindBuffer(GL_ARRAY_BUFFER, arrayBufferBinding); | |
if (activeTexture != GL_TEXTURE0) | |
glActiveTexture(activeTexture); | |
glBindTexture(GL_TEXTURE_2D, binding2DTexture); | |
if (enableBlend) | |
glEnable(GL_BLEND); | |
if (enableCullFace) | |
glEnable(GL_CULL_FACE); | |
if (depthTest) | |
glEnable(GL_DEPTH_TEST); | |
if (depthFunc != GL_LESS) | |
glDepthFunc(depthFunc); | |
} | |
void CustomFrameTexture::getGlInfo(GLenum type){ | |
// check shader link status of current program | |
GLint status; | |
glGetProgramiv(this->currProgram, type, &status); | |
if (!status) { | |
GLint maxLength; | |
glGetProgramiv(this->currProgram, GL_INFO_LOG_LENGTH, &maxLength); | |
char* infoLog = (char *) malloc(sizeof(char) * maxLength); | |
glGetProgramInfoLog(this->currProgram, maxLength, NULL, infoLog); | |
printLog(ERROR, infoLog); | |
free(infoLog); | |
} | |
} | |
void CustomFrameTexture::release() { | |
if (this->currProgram > 0) { | |
glDeleteProgram(this->currProgram); | |
this->currProgram = 0; | |
} | |
GLuint *temp; | |
if (this->arrBuff != 0) { | |
temp = (GLuint*) malloc(sizeof(GLuint)); | |
*temp = this->arrBuff; | |
glDeleteBuffers(1, temp); | |
free(temp); | |
} | |
if (this->elementArrBuff != 0) { | |
temp = (GLuint*) malloc(sizeof(GLuint)); | |
*temp = this->elementArrBuff; | |
glDeleteBuffers(1, temp); | |
free(temp); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#ifndef CUSTOMFRAMETEXTURE_H | |
#define CUSTOMFRAMETEXTURE_H | |
#include <Log.h> | |
class CustomFrameTexture { | |
// attribute | |
private: | |
// vertext shader | |
static const char VERTEXT_SHADER_EXT[]; | |
// fragment shader | |
static const char FRAGMENT_SHADER_EXT[]; | |
// coordinates | |
static const float FLOAT_QUAD_COORDINATES[8]; | |
// buffer data | |
static const int LOCAL_BYTE[4]; | |
// uniform data | |
static const float UNIFORM_DATA[16]; | |
int arrBuff; | |
int elementArrBuff; | |
int currProgram; | |
GLuint vertexShader; | |
GLuint fragmentShader; | |
int maxVertexAttribs; | |
int textureLocation; | |
int matrixLocation; | |
// method | |
public: | |
static CustomFrameTexture& getInstance(){ | |
static CustomFrameTexture instance; | |
return instance; | |
} | |
void initCustomFrameTexture(); | |
void draw2Screen(int textureId,int width, int height); | |
void release(); | |
private: | |
CustomFrameTexture(){ | |
this->arrBuff = -1; | |
this->elementArrBuff = -1; | |
this->currProgram = -1; | |
this->vertexShader = -1; | |
this->fragmentShader = -1; | |
this->maxVertexAttribs = -1; | |
this->textureLocation = -1; | |
this->matrixLocation = -1; | |
}; | |
CustomFrameTexture(CustomFrameTexture const&); | |
void operator=(CustomFrameTexture const&); | |
GLuint initShader(GLenum type,const char* shaderTxt); | |
void getGlInfo(GLenum type); | |
}; | |
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <FriengerScreenRecord.h> | |
/* | |
* Class: jp_oot_screenrecorder_ScreenRecordNative | |
* Method: initGLContext | |
* Signature: (II)V | |
*/JNIEXPORT void JNICALL Java_jp_oot_screenrecorder_ScreenRecordNative_initGLContext( | |
JNIEnv * jEnv, jclass jClass, jint width, jint height) { | |
printLog(DEBUG, "Initialize GLContext with width=%d, height=%d", width, height); | |
CustomFrameBuffer::getInstance().setResolution(width, height); | |
CustomFrameTexture::getInstance().initCustomFrameTexture(); | |
} | |
/* | |
* Class: jp_oot_screenrecorder_ScreenRecordNative | |
* Method: bindFrameBuffer | |
* Signature: ()V | |
*/JNIEXPORT void JNICALL Java_jp_oot_screenrecorder_ScreenRecordNative_bindFrameBuffer( | |
JNIEnv * jEnv, jclass jClass) { | |
printLog(DEBUG, "bind custom FrameBuffer"); | |
CustomFrameBuffer::getInstance().bind(); | |
} | |
/* | |
* Class: jp_oot_screenrecorder_ScreenRecordNative | |
* Method: unbindFrameBuffer | |
* Signature: ()V | |
*/JNIEXPORT void JNICALL Java_jp_oot_screenrecorder_ScreenRecordNative_unbindFrameBuffer( | |
JNIEnv * jEnv, jclass jClass) { | |
printLog(DEBUG, "unbind custom FrameBuffer"); | |
CustomFrameBuffer::getInstance().unbind(); | |
} | |
/* | |
* Class: jp_oot_screenrecorder_ScreenRecordNative | |
* Method: draw2Screen | |
* Signature: (III)V | |
*/JNIEXPORT void JNICALL Java_jp_oot_screenrecorder_ScreenRecordNative_draw2Screen( | |
JNIEnv * jEnv, jclass jClass, jint width, jint height) { | |
GLint textureId = CustomFrameBuffer::getInstance().getOffScreenTexture(); | |
printLog(DEBUG, "draw texture %d to screen(width = %d , height = %d)", textureId, width, height); | |
CustomFrameTexture::getInstance().draw2Screen(textureId, width, height); | |
} | |
JNIEXPORT void JNICALL Java_jp_oot_screenrecorder_ScreenRecordNative_releaseGLContext( | |
JNIEnv * jEnv, jclass jClass) { | |
printLog(DEBUG, "release GL context"); | |
CustomFrameBuffer::getInstance().release(); | |
CustomFrameTexture::getInstance().release(); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* DO NOT EDIT THIS FILE - it is machine generated */ | |
#include <jni.h> | |
/* Header for class jp_oot_screenrecorder_ScreenRecordNative */ | |
#include <Log.h> | |
#include <CustomFrameBuffer.h> | |
#include <CustomFrameTexture.h> | |
#ifndef _Included_jp_oot_screenrecorder_ScreenRecordNative | |
#define _Included_jp_oot_screenrecorder_ScreenRecordNative | |
#ifdef __cplusplus | |
extern "C" { | |
#endif | |
/* | |
* Class: jp_oot_screenrecorder_ScreenRecordNative | |
* Method: initGLContext | |
* Signature: (II)V | |
*/ | |
JNIEXPORT void JNICALL Java_jp_oot_screenrecorder_ScreenRecordNative_initGLContext | |
(JNIEnv *, jclass, jint, jint); | |
/* | |
* Class: jp_oot_screenrecorder_ScreenRecordNative | |
* Method: bindFrameBuffer | |
* Signature: ()V | |
*/ | |
JNIEXPORT void JNICALL Java_jp_oot_screenrecorder_ScreenRecordNative_bindFrameBuffer | |
(JNIEnv *, jclass); | |
/* | |
* Class: jp_oot_screenrecorder_ScreenRecordNative | |
* Method: unbindFrameBuffer | |
* Signature: ()V | |
*/ | |
JNIEXPORT void JNICALL Java_jp_oot_screenrecorder_ScreenRecordNative_unbindFrameBuffer | |
(JNIEnv *, jclass); | |
/* | |
* Class: jp_oot_screenrecorder_ScreenRecordNative | |
* Method: draw2Screen | |
* Signature: (II)V | |
*/ | |
JNIEXPORT void JNICALL Java_jp_oot_screenrecorder_ScreenRecordNative_draw2Screen | |
(JNIEnv *, jclass, jint, jint); | |
/* | |
* Class: jp_oot_screenrecorder_ScreenRecordNative | |
* Method: releaseGLContext | |
* Signature: ()V | |
*/ | |
JNIEXPORT void JNICALL Java_jp_oot_screenrecorder_ScreenRecordNative_releaseGLContext | |
(JNIEnv *, jclass); | |
#ifdef __cplusplus | |
} | |
#endif | |
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <Log.h> | |
int IS_DEBUG_MODE = TRUE; | |
void printGLString(const char *name, GLenum s) { | |
if (IS_DEBUG_MODE) { | |
const char *v = (const char *) glGetString(s); | |
LOGI("GL %s = %s\n", name, v); | |
} | |
} | |
void printLog(LOG_TYPE type,const char *name, ...){ | |
if(IS_DEBUG_MODE){ | |
va_list params; | |
char buf[BUFSIZ]; | |
va_start(params, name); | |
vsprintf(buf, name, params); | |
if (type == DEBUG) | |
LOGD("%s", buf); | |
else if (type == ERROR) | |
LOGE("%s", buf); | |
va_end(params); | |
} | |
} | |
void checkGlError(const char* op, ...) { | |
if (IS_DEBUG_MODE) { | |
va_list params; | |
char buf[BUFSIZ]; | |
va_start(params, op); | |
vsprintf(buf, op, params); | |
for (GLint error = glGetError(); error; error = glGetError()) { | |
switch (error) { | |
case GL_INVALID_ENUM: | |
LOGE("after %s() glError: GL_INVALID_ENUM \n", buf); | |
break; | |
case GL_INVALID_VALUE: | |
LOGE("after %s() glError: GL_INVALID_VALUE \n", buf); | |
break; | |
case GL_INVALID_OPERATION: | |
LOGE("after %s() glError: GL_INVALID_OPERATION \n", buf); | |
break; | |
case GL_INVALID_FRAMEBUFFER_OPERATION: | |
LOGE("after %s() glError: GL_INVALID_FRAMEBUFFER_OPERATION \n", buf); | |
break; | |
case GL_OUT_OF_MEMORY: | |
LOGE("after %s() glError: GL_OUT_OF_MEMORY \n", buf); | |
break; | |
default: | |
break; | |
} | |
} | |
va_end(params); | |
} | |
} | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#ifndef LOG_H | |
#define LOG_H | |
#include <jni.h> | |
#include <android/log.h> | |
#include <GLES2/gl2.h> | |
#include <GLES2/gl2ext.h> | |
#include <GLES/glext.h> | |
#include <stdio.h> | |
#include <stdlib.h> | |
#include <math.h> | |
#define LOG_TAG "NativeScreenRecord" | |
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG,LOG_TAG,__VA_ARGS__) | |
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO,LOG_TAG,__VA_ARGS__) | |
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR,LOG_TAG,__VA_ARGS__) | |
#define TRUE 1 | |
#define FALSE 0 | |
enum LOG_TYPE {DEBUG, ERROR} ; | |
void printGLString(const char *name, GLenum s); | |
void printLog(LOG_TYPE type,const char *name, ...); | |
void checkGlError(const char* op, ...); | |
#endif |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment