YUV格式纹理贴图的例子
(2018-03-27 23:02:38)分类: GPU |
非最新
frameworks/native/opengl/tests/gl2_yuvtex/gl2_yuvtex.cpp
是Android提供的yuv格式纹理贴图的例子。
前面先申请存放纹理数据的buffer
yuvTexBuffer = new
GraphicBuffer(yuvTexWidth, yuvTexHeight, yuvTexFormat,
yuvTexUsage);
其中 yuvTexFormat =
HAL_PIXEL_FORMAT_YV12
class GraphicBuffer在
frameworks/native/include/ui/GraphicBuffer.h
中定义,其初始化函数通过initSize调用allocator.alloc申请空间。allocator是GraphicBufferAllocator的引用,这个class包含了alloc_device_t变量,是grallocHAL模块中alloc设备使用的结构体,完成对图形缓冲区的管理,实现从硬件内存到应用地址的映射。
后续会通过vendor
driver提供的eglCreateImageKHR调用dpy->winsys->get_native_buffer,到winsysp_native_buffer_validate,get_buffer_egl_format,再到hal_format_to_egl_format,完成从HAL
format到egl format的映射,例如 HAL_PIXEL_FORMAT_YV12 <->
EGL_COLOR_BUFFER_FORMAT_YV12_BT601_NARROW
配置在
arm/xxx/android/config/mali_config_interface_reference.cpp
在eglCreateImageKHR通过get_native_buffer到egl_color_buffer_wrap_external_planar生成EGLImageKHR后,调用glEGLImageTargetTexture2DOES(GL_TEXTURE_EXTERNAL_OES,
image),从EGLImageKHR产生纹理。
这个过程利用了OpenGL的extension
- GL_OES_EGL_image_external
这个extension定义了一个新的texture target -
TEXTURE_EXTERNAL_OES;相应地在shader中增加了一个新的sampler类型 -
samplerExternalOES,是a handle for accessing an external
texture。
注意:这个extension已经过时,应该使用GL_OES_EGL_image_external_essl3
Vulkan则用VkSamplerYcbcrModelConversion定义了从source color
model到shader color model的转换。
typedef enum VkSamplerYcbcrModelConversion
{
}
VkSamplerYcbcrModelConversion;
原程序的YUV值共有2^3=8种组合,所以输出色块共有8种颜色。为了调试方便可以改动赋值以输出纯色,以红色(255,
0, 0)为例,
Y = 0.257 * R + 0.504 * G + 0.098 * B + 16
= 0.257 * 255 + 16
= 81
U = -0.148 * R - 0.291 * G + 0.439 * B + 128
= -0.148
* 255 + 128 = 90
V = 0.439 * R - 0.368 * G - 0.071 * B +
128 = 0.439
* 255 + 128 = 240
在修改yuvTexWidth
= yuvTexHeight = 128的情况下,
yuvTexStrideY =
128
yuvTexOffsetV =
16384 yuvTexStrideV = 64
yuvTexOffsetU =
20480 yuvTexStrideU = 64
为了检查输出,可以在renderFrame和eglSwapBuffers之间插入glReadPixels如下:
GLubyte *pixels = (GLubyte *) calloc(4,
sizeof(GLubyte));
glReadPixels(w/2, h/2, 1, 1, GL_RGBA,
GL_UNSIGNED_BYTE, pixels);
printf("RGBA values: %d %d %d %d\n",
pixels[0], pixels[1], pixels[2], pixels[3]);
free(pixels);
另外ISP信号通常使用YUV420SP也就是NV21格式。
HAL_PIXEL_FORMAT_YCrCb_420_SP
<-> EGL_COLOR_BUFFER_FORMAT_NV21_BT601_NARROW