要使用Direct Texture,需要有一份android系统的源码
部分C++代码如下:
#include <stdio.h>
#include <stdlib.h>
#include <GLES2/gl2.h>
#include <GLES2/gl2ext.h>
#include <EGL/egl.h>
#include <EGL/eglext.h>
#include <android/native_window.h>
#include <ui/GraphicBuffer.h>
#include <dlfcn.h>
#include <jni.h>
#include "render_native.h"
int
Graphics::initGL(){
const
char
*
const
driver_absolute_path =
"/system/lib/egl/libEGL_mali.so"
;
// On Gingerbread you have to load symbols manually from Mali driver because
// Android EGL library has a bug.
// From ICE CREAM SANDWICH you can freely use the eglGetProcAddress function.
// You might be able to get away with just eglGetProcAddress (no dlopen). Tr y it, else revert to the following code
void
* dso = dlopen(driver_absolute_path, RTLD_LAZY);
if
(dso != 0)
{
LOGI(
"dlopen: SUCCEEDED"
);
_eglCreateImageKHR = (PFNEGLCREATEIMAGEKHRPROC)dlsym(dso,
"eglCreateImageKHR"
);
_eglDestroyImageKHR = (PFNEGLDESTROYIMAGEKHRPROC) dlsym(dso,
"eglDestroyImageKHR"
);
}
else
{
LOGI(
"dlopen: FAILED! Loading functions in common way!"
);
_eglCreateImageKHR = (PFNEGLCREATEIMAGEKHRPROC) eglGetProcAddress(
"eglCreateImageKHR"
);
_eglDestroyImageKHR = (PFNEGLDESTROYIMAGEKHRPROC) eglGetProcAddress(
"eglDestroyImageKHR"
);
}
if
(_eglCreateImageKHR == NULL)
{
LOGE(
"Error: Failed to find eglCreateImageKHR at %s:%in"
, __FILE__, __LINE__);
exit
(1);
}
if
(_eglDestroyImageKHR == NULL)
{
LOGE(
"Error: Failed to find eglDestroyImageKHR at %s:%in"
, __FILE__, __LINE__);
exit
(1);
}
_glEGLImageTargetTexture2DOES = (PFNGLEGLIMAGETARGETTEXTURE2DOESPROC) eglGetProcAddress(
"glEGLImageTargetTexture2DOES"
);
if
(_glEGLImageTargetTexture2DOES == NULL)
{
LOGI(
"Error: Failed to find glEGLImageTargetTexture2DOES at %s:%in"
, __FILE__, __LINE__);
return
0;
}
graphicBuffer =
new
GraphicBuffer( emu_width,emu_height,
HAL_PIXEL_FORMAT_RGBA_8888,
GraphicBuffer::USAGE_HW_TEXTURE |
GraphicBuffer::USAGE_HW_2D |
GRALLOC_USAGE_SW_READ_OFTEN |
GRALLOC_USAGE_SW_WRITE_OFTEN);
status_t err = graphicBuffer->initCheck();
if
(err != NO_ERROR)
{
LOGI(
"Error: %sn"
,
strerror
(-err));
return
0;
}
GGLSurface t;
// graphicBuffer->lock(GraphicBuffer::USAGE_SW_WRITE_OFTEN, &addr);
graphicBuffer->lock(&t, GRALLOC_USAGE_SW_WRITE_OFTEN);
memset
(t.data,128,t.stride*t.height);
graphicBuffer->unlock();
// Retrieve andorid native buffer
android_native_buffer_t* anb =graphicBuffer->getNativeBuffer();
// create the new EGLImageKHR
const
EGLint attrs[] =
{
EGL_IMAGE_PRESERVED_KHR, EGL_TRUE,
EGL_NONE, EGL_NONE
};
mEngine.mTexture.pEGLImage = _eglCreateImageKHR(eglGetCurrentDisplay(),
mEngine.nContext, EGL_NATIVE_BUFFER_ANDROID, (EGLClientBuffer)anb, attrs);
if
(mEngine.mTexture.pEGLImage == EGL_NO_IMAGE_KHR)
{
LOGI(
"Error: eglCreateImage() failed at %s:%in"
, __FILE__, __LINE__);
return
0;
}
checkGlError(
"eglCreateImageKHR"
);
LOGI(
"create Program......."
);
GLuint gProgram = createProgram(vertex_source, fragment_source);
checkGlError(
"createProgram"
);
if
(!gProgram) {
LOGE(
"Could not create program."
);
return
false
;
}
glUseProgram(gProgram);
vPosition = glGetAttribLocation(gProgram,
"glVertex"
);
checkGlError(
"glGetAttribLocation glVertex"
);
glEnableVertexAttribArray(vPosition);
a_texCoord0 = glGetAttribLocation(gProgram,
"a_texCoord0"
);
checkGlError(
"glGetAttribLocation texCoord0"
);
glEnableVertexAttribArray(a_texCoord0);
s_tex0 = glGetUniformLocation(gProgram,
"s_texture0"
);
checkGlError(
"glGetAttribLocation texture"
);
LOGI(
"glGen Textures......."
);
glGenTextures(1, &texID);
glDisable(GL_BLEND);
glDisable(GL_DEPTH_TEST);
glDisable(GL_STENCIL_TEST);
glDisable(GL_DITHER);
checkGlError(
"glDisable"
);
// glEnable(GL_TEXTURE_2D);
// checkGlError("glEnable(GL_TEXTURE_2D)");
glGenTextures(1,&texID);
checkGlError(
"glGenTextures"
);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, texID);
// glPixelStorei(GL_PACK_ALIGNMENT, 1);
// glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST );
// glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, mEngine.mTexture.nTextureWidth, mEngine.mTexture.nTextureHeight, 0,GL_RGBA, GL_UNSIGNED_BYTE, NULL);
// glFinish();
_glEGLImageTargetTexture2DOES(GL_TEXTURE_2D,mEngine.mTexture.pEGLImage);
float
w =
float
(emu_width) /
float
(mEngine.mTexture.nTextureWidth);
float
h =
float
(emu_height) /
float
(mEngine.mTexture.nTextureHeight);
g_pos=initFloatBuffer(vertices,12);
g_texvbo=initFloatBuffer(texCoords,8);
glViewport(0, 0, mEngine.nScreen_Width, mEngine.nScreen_Height);
return
1;
}
void
Graphics::renderFrame() {
// texture=(unsigned char*)ture;
glClearColor(0.5f, 0.5f, 0.5f, 1);
glClear( GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
glUniform1i(s_tex0, 0);
glBindBuffer(GL_ARRAY_BUFFER, g_pos);
glVertexAttribPointer(vPosition, 3, GL_FLOAT, GL_FALSE, 0, 0);
glBindBuffer(GL_ARRAY_BUFFER, g_texvbo);
glVertexAttribPointer(a_texCoord0, 2, GL_FLOAT, GL_FALSE, 0, 0);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
eglSwapBuffers(mEngine.nDisplay, mEngine.nSurface);
}
void
* Graphics::begin(){
GGLSurface t;
graphicBuffer->lock(&t,GRALLOC_USAGE_SW_WRITE_OFTEN);
return
t.data;
}
void
Graphics::end(){
graphicBuffer->unlock();
renderFrame();
}
使用时如下:
Graphics render;
void
*buffer=render.begin();
把数据填充到buffer里
render.end();
编译时包含头文件
LOCAL_C_INCLUDES +=
$(ANDROID_SRC_HOME)/frameworks/base/core/jni/android/graphics
$(ANDROID_SRC_HOME)/frameworks/base/include/
$(ANDROID_SRC_HOME)/hardware/libhardware/include
$(ANDROID_SRC_HOME)/
system
/core/include
$(ANDROID_SRC_HOME)/frameworks/base/native/include/
$(ANDROID_SRC_HOME)/frameworks/base/opengl/include/
链接选项:
LOCAL_LDLIBS := -llog -lGLESv2 -lEGL -landroid -lui -landroid_runtime -ljnigraphics
android Opengles 里虽然没有PBO, 但是用Direct Texture能实现类似的功能。
direct textures 的使用介绍
http:
//snorp.net/2011/12/16/android-direct-texture.html
eglCreateImageKHR扩展的介绍
http:
//www.khronos.org/registry/egl/extensions/KHR/EGL_KHR_image_base.txt
描述:在opengles 编程时如果用glTexImage2D /glTexSubImage2D API的话,当渲染的图片很大时,速度会变得很慢的,因为运行时会发生数据拷贝的过程,而使用opengles 的扩展glEGLImageTargetTexture2DOES可以解决这个问题,用这个扩展要用到另一个扩展 eglCreateImageKHR 。