8bb1e592f11687181314b0f3ffc9a14123384844
[iec.git] / src / type3_AndroidCloud / anbox-master / src / anbox / graphics / emugl / TextureDraw.cpp
1 // Copyright (C) 2015 The Android Open Source Project
2 //
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
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
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.
14
15 #include "anbox/graphics/emugl/TextureDraw.h"
16 #include "anbox/graphics/emugl/DispatchTables.h"
17 #include "anbox/logger.h"
18
19 #include <math.h>
20 #include <string.h>
21 #include <vector>
22
23 #include <stdio.h>
24
25 // M_PI isn't defined in C++ (when strict ISO compliance is enabled)
26 #ifndef M_PI
27 #define M_PI 3.14159265358979323846264338327
28 #endif
29
30 namespace {
31
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);
39   if (!shader) {
40     return 0;
41   }
42   const GLchar* text = static_cast<const GLchar*>(shaderText);
43   const GLint textLen = ::strlen(shaderText);
44   s_gles2.glShaderSource(shader, 1, &text, &textLen);
45
46   // Compiler the shader.
47   GLint success;
48   s_gles2.glCompileShader(shader);
49   s_gles2.glGetShaderiv(shader, GL_COMPILE_STATUS, &success);
50   if (success == GL_FALSE) {
51     s_gles2.glDeleteShader(shader);
52     return 0;
53   }
54
55   return shader;
56 }
57
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"
64     "void main(void) {\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"
69     "}\n";
70
71 // Similarly, just interpolate texture coordinates.
72 const char kFragmentShaderSource[] =
73     "varying lowp vec2 outCoord;\n"
74     "uniform sampler2D texture;\n"
75
76     "void main(void) {\n"
77     "  gl_FragColor = texture2D(texture, outCoord);\n"
78     "}\n";
79
80 // Hard-coded arrays of vertex information.
81 struct Vertex {
82   float pos[3];
83   float coord[2];
84 };
85
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}},
91 };
92
93 const GLubyte kIndices[] = {0, 1, 2, 2, 3, 0};
94 const GLint kIndicesLen = sizeof(kIndices) / sizeof(kIndices[0]);
95
96 }  // namespace
97
98 TextureDraw::TextureDraw(EGLDisplay)
99     : mVertexShader(0),
100       mFragmentShader(0),
101       mProgram(0),
102       mPositionSlot(-1),
103       mInCoordSlot(-1),
104       mTextureSlot(-1) {
105   // Create shaders and program.
106   mVertexShader = createShader(GL_VERTEX_SHADER, kVertexShaderSource);
107   mFragmentShader = createShader(GL_FRAGMENT_SHADER, kFragmentShaderSource);
108
109   mProgram = s_gles2.glCreateProgram();
110   s_gles2.glAttachShader(mProgram, mVertexShader);
111   s_gles2.glAttachShader(mProgram, mFragmentShader);
112
113   GLint success;
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);
121     mProgram = 0;
122     return;
123   }
124
125   s_gles2.glUseProgram(mProgram);
126
127   // Retrieve attribute/uniform locations.
128   mPositionSlot = s_gles2.glGetAttribLocation(mProgram, "position");
129   s_gles2.glEnableVertexAttribArray(mPositionSlot);
130
131   mInCoordSlot = s_gles2.glGetAttribLocation(mProgram, "inCoord");
132   s_gles2.glEnableVertexAttribArray(mInCoordSlot);
133
134   mTextureSlot = s_gles2.glGetUniformLocation(mProgram, "texture");
135
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,
140                        GL_STATIC_DRAW);
141
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,
145                        GL_STATIC_DRAW);
146 }
147
148 bool TextureDraw::draw(GLuint texture) {
149   if (!mProgram) {
150     ERROR(" No program");
151     return false;
152   }
153
154   // TODO(digit): Save previous program state.
155
156   GLenum err;
157
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);
162   }
163
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);
169   }
170
171   s_gles2.glEnableVertexAttribArray(mPositionSlot);
172   s_gles2.glVertexAttribPointer(mPositionSlot, 3, GL_FLOAT, GL_FALSE,
173                                 sizeof(Vertex), 0);
174   err = s_gles2.glGetError();
175   if (err != GL_NO_ERROR) {
176     ERROR("Could glVertexAttribPointer with mPositionSlot error 0x%x", err);
177   }
178
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)));
184
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);
189
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);
198     return false;
199   }
200
201   // Do the rendering.
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);
206   }
207
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);
212   }
213
214   // TODO(digit): Restore previous program state.
215
216   return true;
217 }
218
219 TextureDraw::~TextureDraw() {
220   s_gles2.glDeleteBuffers(1, &mIndexBuffer);
221   s_gles2.glDeleteBuffers(1, &mVertexBuffer);
222
223   if (mFragmentShader) {
224     s_gles2.glDeleteShader(mFragmentShader);
225   }
226   if (mVertexShader) {
227     s_gles2.glDeleteShader(mVertexShader);
228   }
229 }