1 // Copyright (C) 2015 The Android Open Source Project
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
7 // http://www.apache.org/licenses/LICENSE-2.0
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
15 #include "anbox/graphics/emugl/TextureDraw.h"
16 #include "anbox/graphics/emugl/DispatchTables.h"
17 #include "anbox/logger.h"
25 // M_PI isn't defined in C++ (when strict ISO compliance is enabled)
27 #define M_PI 3.14159265358979323846264338327
32 // Helper function to create a new shader.
33 // |shaderType| is the shader type (e.g. GL_VERTEX_SHADER).
34 // |shaderText| is a 0-terminated C string for the shader source to use.
35 // On success, return the handle of the new compiled shader, or 0 on failure.
36 GLuint createShader(GLint shaderType, const char* shaderText) {
37 // Create new shader handle and attach source.
38 GLuint shader = s_gles2.glCreateShader(shaderType);
42 const GLchar* text = static_cast<const GLchar*>(shaderText);
43 const GLint textLen = ::strlen(shaderText);
44 s_gles2.glShaderSource(shader, 1, &text, &textLen);
46 // Compiler the shader.
48 s_gles2.glCompileShader(shader);
49 s_gles2.glGetShaderiv(shader, GL_COMPILE_STATUS, &success);
50 if (success == GL_FALSE) {
51 s_gles2.glDeleteShader(shader);
58 // No scaling / projection since we want to fill the whole viewport with
59 // the texture, hence a trivial vertex shader.
60 const char kVertexShaderSource[] =
61 "attribute vec4 position;\n"
62 "attribute vec2 inCoord;\n"
63 "varying lowp vec2 outCoord;\n"
65 " gl_Position.x = position.x;\n"
66 " gl_Position.y = position.y;\n"
67 " gl_Position.zw = position.zw;\n"
68 " outCoord = inCoord;\n"
71 // Similarly, just interpolate texture coordinates.
72 const char kFragmentShaderSource[] =
73 "varying lowp vec2 outCoord;\n"
74 "uniform sampler2D texture;\n"
77 " gl_FragColor = texture2D(texture, outCoord);\n"
80 // Hard-coded arrays of vertex information.
86 const Vertex kVertices[] = {
87 {{+1, -1, +0}, {+1, +1}},
88 {{+1, +1, +0}, {+1, +0}},
89 {{-1, +1, +0}, {+0, +0}},
90 {{-1, -1, +0}, {+0, +1}},
93 const GLubyte kIndices[] = {0, 1, 2, 2, 3, 0};
94 const GLint kIndicesLen = sizeof(kIndices) / sizeof(kIndices[0]);
98 TextureDraw::TextureDraw(EGLDisplay)
105 // Create shaders and program.
106 mVertexShader = createShader(GL_VERTEX_SHADER, kVertexShaderSource);
107 mFragmentShader = createShader(GL_FRAGMENT_SHADER, kFragmentShaderSource);
109 mProgram = s_gles2.glCreateProgram();
110 s_gles2.glAttachShader(mProgram, mVertexShader);
111 s_gles2.glAttachShader(mProgram, mFragmentShader);
114 s_gles2.glLinkProgram(mProgram);
115 s_gles2.glGetProgramiv(mProgram, GL_LINK_STATUS, &success);
116 if (success == GL_FALSE) {
117 GLchar messages[256];
118 s_gles2.glGetProgramInfoLog(mProgram, sizeof(messages), 0, &messages[0]);
119 ERROR("Could not create/link program: %s", messages);
120 s_gles2.glDeleteProgram(mProgram);
125 s_gles2.glUseProgram(mProgram);
127 // Retrieve attribute/uniform locations.
128 mPositionSlot = s_gles2.glGetAttribLocation(mProgram, "position");
129 s_gles2.glEnableVertexAttribArray(mPositionSlot);
131 mInCoordSlot = s_gles2.glGetAttribLocation(mProgram, "inCoord");
132 s_gles2.glEnableVertexAttribArray(mInCoordSlot);
134 mTextureSlot = s_gles2.glGetUniformLocation(mProgram, "texture");
136 // Create vertex and index buffers.
137 s_gles2.glGenBuffers(1, &mVertexBuffer);
138 s_gles2.glBindBuffer(GL_ARRAY_BUFFER, mVertexBuffer);
139 s_gles2.glBufferData(GL_ARRAY_BUFFER, sizeof(kVertices), kVertices,
142 s_gles2.glGenBuffers(1, &mIndexBuffer);
143 s_gles2.glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mIndexBuffer);
144 s_gles2.glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(kIndices), kIndices,
148 bool TextureDraw::draw(GLuint texture) {
150 ERROR(" No program");
154 // TODO(digit): Save previous program state.
158 s_gles2.glUseProgram(mProgram);
159 err = s_gles2.glGetError();
160 if (err != GL_NO_ERROR) {
161 ERROR("Could not use program error 0x%x", err);
164 // Setup the |position| attribute values.
165 s_gles2.glBindBuffer(GL_ARRAY_BUFFER, mVertexBuffer);
166 err = s_gles2.glGetError();
167 if (err != GL_NO_ERROR) {
168 ERROR("Could not bind GL_ARRAY_BUFFER error=0x%x", err);
171 s_gles2.glEnableVertexAttribArray(mPositionSlot);
172 s_gles2.glVertexAttribPointer(mPositionSlot, 3, GL_FLOAT, GL_FALSE,
174 err = s_gles2.glGetError();
175 if (err != GL_NO_ERROR) {
176 ERROR("Could glVertexAttribPointer with mPositionSlot error 0x%x", err);
179 // Setup the |inCoord| attribute values.
180 s_gles2.glEnableVertexAttribArray(mInCoordSlot);
181 s_gles2.glVertexAttribPointer(
182 mInCoordSlot, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex),
183 reinterpret_cast<GLvoid*>(static_cast<uintptr_t>(sizeof(float) * 3)));
185 // setup the |texture| uniform value.
186 s_gles2.glActiveTexture(GL_TEXTURE0);
187 s_gles2.glBindTexture(GL_TEXTURE_2D, texture);
188 s_gles2.glUniform1i(mTextureSlot, 0);
190 // Validate program, just to be sure.
191 s_gles2.glValidateProgram(mProgram);
192 GLint validState = 0;
193 s_gles2.glGetProgramiv(mProgram, GL_VALIDATE_STATUS, &validState);
194 if (validState == GL_FALSE) {
195 GLchar messages[256];
196 s_gles2.glGetProgramInfoLog(mProgram, sizeof(messages), 0, &messages[0]);
197 ERROR("Could not run program: %s", messages);
202 s_gles2.glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mIndexBuffer);
203 err = s_gles2.glGetError();
204 if (err != GL_NO_ERROR) {
205 ERROR("Could not glBindBuffer(GL_ELEMENT_ARRAY_BUFFER) error 0x%x", err);
208 s_gles2.glDrawElements(GL_TRIANGLES, kIndicesLen, GL_UNSIGNED_BYTE, 0);
209 err = s_gles2.glGetError();
210 if (err != GL_NO_ERROR) {
211 ERROR("Could not glDrawElements() error 0x%x", err);
214 // TODO(digit): Restore previous program state.
219 TextureDraw::~TextureDraw() {
220 s_gles2.glDeleteBuffers(1, &mIndexBuffer);
221 s_gles2.glDeleteBuffers(1, &mVertexBuffer);
223 if (mFragmentShader) {
224 s_gles2.glDeleteShader(mFragmentShader);
227 s_gles2.glDeleteShader(mVertexShader);