Android VideoPlayer 调用的OpenGL ES

2019-11-25  本文已影响0人  小老鼠oo

这次主要是为了看我们的OGLES driver里为什么会malloc的比mali多,dumpheap发现排名靠前的都是与texture有关的,我记得是glTexImage2D和glTexSubImage。里面是为了Mipmap临时malloc了system memory,但是谁知道后面会不会再用?不敢轻易free。OGL ES API我也不熟,怎么也得系统的看看。

书籍参考OpenGL ES 3.0 Programming Guide, www.java.1234.com可以下载,电子版,带目录。

这本书的中文版有点问题,他翻译的太多了,且不给英文原文,违和感很强。比如在书里看了统一变量,上下文,片段着色器,绘图表面的知识,再看代码,却很难在看到Uniform,context,fragment shader,surface时找到共鸣。

直接看英文书又太难,还是先看了中文熟悉基本的概念,再看英文,好看一点。


EGL API序列:

前面的API都是给状态,状态保存在glContext,只有Draw才会真正让GPU做事情,所有的draw API都会走到DrawPrimitive(),后面的Begin() => ValidateAttribute()可以看到所有的过程:

开始是EGL调用,EGL提供了下面的机制:

eglGetDisplay(EGL_DEFAULT_DISPLAY)=display_0;

eglInitialize(display_0, NULL, NULL);

DEFINE POINTER name=attrib_list_0, type=egl_attrib_list, count=0, data=imm{EGL_RENDERABLE_TYPE=EGL_OPENGL_ES2_BIT, EGL_RED_SIZE=8, EGL_GREEN_SIZE=8, EGL_BLUE_SIZE=8, EGL_ALPHA_SIZE=8, EGL_DEPTH_SIZE=0, EGL_CONFIG_CAVEAT=EGL_NONE, EGL_STENCIL_SIZE=8, EGL_SURFACE_TYPE=EGL_WINDOW_BIT, EGL_NONE};
eglChooseConfig(display_0, attrib_list_0, configs_0, 1, pointer_0);

eglCreateContext(display_0, configs_0[0], EGL_NO_CONTEXT, attrib_list_1)=context_0; //0x3

DEFINE POINTER name=attrib_list_2, type=egl_attrib_list, count=0, data=imm{EGL_WIDTH=1, EGL_HEIGHT=1, EGL_NONE};
eglCreatePbufferSurface(display_0, configs_0[0], attrib_list_2)=surface_0;

eglMakeCurrent(display_0, surface_0, surface_0, context_0);

这里的代码现在看也觉得很乱,后面再补充。至此,EGL调用做完了,本地环境有了,开始调用GL API.


GL ES API序列:

Vertex:

DEFINE POINTER name=buffer_0, type=uint, count=1, data=imm{null};
glGenBuffers(1, buffer_0);
API : its about Vertex Buffer Object
通过vertex arrays指定的vertex data保存在client memory,在调用glDrawArrays/DrawElements时必须保证这些data从client memory复制到了graphics memory。但是,不需要每次draw call都copy vertex data的,一直cache data in graphics memory更好。这就是vertex buffer objects的目的。
Vertex buffer objects 允许AP从graphics memory去allocate和cache vertex data,并从这个memory 去render,从而避免每次画primitive时都要resending data。
不只是vertex data, 描述primitive vertex indices的element indices,作为glDrawElements的arg,也可以cached在这个memory。
OGLES 3.0支持两种buffer object:

glBindBuffer(GL_ARRAY_BUFFER, buffer_0[0]);

DEFINE POINTER name=buffer_1, type=ubyte, count=64, file_offset=0, data=file{combine_0.bin};
glBufferData(GL_ARRAY_BUFFER, 64, buffer_1, GL_STATIC_DRAW);

glEnableVertexAttribArray(0x0);

//Example 6-3 Using Constant and Vertex Array Attributes
int Init ( ESContext *esContext )
{
    UserData *userData = (UserData*) esContext->userData;
    const char vShaderStr[] = 
        "#version 300 es \n"
        "layout(location = 0) in vec4 a_color; \n"
        "layout(location = 1) in vec4 a_position; \n"
        "out vec4 v_color; \n"
        "void main() \n"
        "{ v_color = a_color; \n"
        " gl_Position = a_position; }\n" ;

    const char fShaderStr[] = 
        "#version 300 es \n"
        "precision mediump float; \n"
        "in vec4 v_color; \n"
        "out vec4 o_fragColor; \n"
        "void main() \n"
        "{ o_fragColor = v_color; \n } " ;

        GLuint programObject;
        //Create program object;
        programObject = esLoadProgram(vShaderStr, fShaderStr);
        if(programObject == 0)  return GL_FALSE;
        //Store program object
        userData->programObject = programObject;
        glClearColor(0.0f, 0.0f, .0.0f, 0.0f );
        return GL_TRUE;
}

void Draw(ESCOntext *esContext)
{
    UserData *userData = (UserData*)esContext->userData;
    GLfloat color[4] = {1.0f, 0.0f, 0.0f, 1.0f};
    //3 vertices, with(x,y,z)per-vertex
    GLfloat vertexPos[3*3] =
    { 0.0f,0.5f,0.0f, //v0
      -0.5f,-0.5f,0.0f, //v1
      0.5f,-0.5f,0.0f //v2
    };

    glViewport(0, 0, esContext->width, esContext->height);
    //
    glClear(GL_COLOR_BUFFER_BIT);
    glUseProgram(userData->programObject);
    glVertexAttrib4fb(0, color);
    glVettexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, vertexPos);
    glEnableVertexAttribArray(1);
    glDrawArrays(GL_TRANINGES, 0 ,3);
    glDisplayVertexAttribArray(1);
}

vertex attribute:color,用glVertexAttrib4fb指定一个常量,没有enable vertex attribute array 0。
vertexPos这个attribute,通过glVertexAttribPointer指定了使用vertex array,并enable array(by glEnableVertexAttribArray)
所以,color值对所有vertices of triangle都是一样的,但是每个vertices的vertexPos attribute是不同的。
上面的code用到了glVertexAttrib4fv(index, *values);用于指定Vertex Attribute Data,
Vertex attribute data,可以通过vertex array为每个vertex指定,也可以把一个constant value用于primitive的所有vertices。

void glVertexAttribPointer(index, size, type, normalized, stride, *ptr)
index : specifies generic vertex attibute index
size: 通过index引用的vertex attirbute的分量,1-4
stirde: as pitch(跨距) to get vertex data for next index.
ptr : 使用client-size vertex array时,指向持有vertex attibute data的buffer; 使用vertex buffer object时,表示offset in that buffer。

stirde: as pitch(跨距) to get vertex data for next index.
ptr : 使用client-size vertex array时,指向持有vertex attibute data的buffer; 使用vertex buffer object时,表示offset in that buffer。

先走着


texture:

glActiveTexture(GL_TEXTURE0);

//Vertex shader
#version 300 es
layout(location = 0) in vec4 a_position;
layout(location = 1) in vec2 a_texCoord;
out vec2 v_texCorrd;
void main()
{
    gl_Position = a_position;
     v_texCoord = a_texCoord;
}

//Fragment shader
#version 300 es
precision mediump float;
in vec2 v_texCoord;
layout(location = 0) out vec4 outColor;
uniform sampler2D s_texture;
void main()
{
    outColor = texture( s_texture, v_texCoord );
}

vertex shader以一个two-component texture coordinate作为vertex input, then passes it as output to framgnet shader.
fragment shader consumes the texture coordinate and used it for texture fetch(读取).
fragment shader声明了一个类型为sampler2D的uniform variable,called s_texture。

sampler是uniform变量的一个特殊类型,用来fetch from a texture map,读取纹理贴图。
sampler uniform will be loaded with a value specifying texture unit to which texture is bound;
比如,specifying a sampler with value of 0, says to fetch from unit GL_TEXTURE0,specifying a value of 1 says to fetch from GL_TEXTURE1, and so on.

Textures are bound to texture units by glActiveTexture(GLenum texture)
texture: texture unit to make active: GL_TEXTURE0/1/2/3/.../31/
glActiveTexture设置了current texture unit,以便后续的glBindTexutre()会Bind texture to currently active uint。
example show how sampler and texture are bound to texture unit:

//get the sampler locations
userData->samplerLoc = glGetUniformLocation(userData->programObject,"s_texture");

//bind texture
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, userData->textureId);

//set sampler texture unit to 0
glUniformli(userData->samplerLoc, 0);

到这里,我们已经load了texture, texturen bound to texture unit 0 , sampler set to use texture uint 0.
回到simple_texture2D sample,可以看到,shader code使用了内建函数texture,来fetch from texture map,

vec4 texture(sampler2D sampler, vec2 coord[,float bias])
sampler: sampler bound to a texture unit, 来指定要fetch的texture
coord: a 2D texture coordinate, 用来fetch from texture map
bias: 可选参数,提供texture fetch所用的mipmap bias(mip贴图 偏置),

texture()返回一个vec4,代表color fetched fromt texture map.
texture data mapped到color channels的方式,依赖于texture base format。
下表展示了texture format map到vec4 color的方式,texture swizzles决定了,每个分量的值,如何map到shader的分量

base format Texel Data 纹素
GL_RGB R G B 1.0
GL_RGBA R G B A
GL_LUMINANCE L L L 1.0
GL_LUMINANCE_ALPHA L L L A
GL_ALPHA 0.0 .0.0 0.0 A

这里有个texture swizzles,9.1.9纹理调配讲了:texture swizzles control how color components in input R,RG,RGB,RGBA texture map to components when fetched from in the shader.
感觉和allocation->flag.swizzled不一样,这个对应的是tiled,

上一篇下一篇

猜你喜欢

热点阅读