• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "TextureDraw.h"
16 
17 #include "DispatchTables.h"
18 
19 #include "host-common/crash_reporter.h"
20 
21 #include <algorithm>
22 #include <string>
23 #include <assert.h>
24 #include <string.h>
25 #include <stdio.h>
26 #define ERR(...)  fprintf(stderr, __VA_ARGS__)
27 
28 namespace {
29 
30 // Helper function to create a new shader.
31 // |shaderType| is the shader type (e.g. GL_VERTEX_SHADER).
32 // |shaderText| is a 0-terminated C string for the shader source to use.
33 // On success, return the handle of the new compiled shader, or 0 on failure.
createShader(GLint shaderType,const char * shaderText)34 GLuint createShader(GLint shaderType, const char* shaderText) {
35     // Create new shader handle and attach source.
36     GLuint shader = s_gles2.glCreateShader(shaderType);
37     if (!shader) {
38         return 0;
39     }
40     const GLchar* text = static_cast<const GLchar*>(shaderText);
41     const GLint textLen = ::strlen(shaderText);
42     s_gles2.glShaderSource(shader, 1, &text, &textLen);
43 
44     // Compiler the shader.
45     GLint success;
46     s_gles2.glCompileShader(shader);
47     s_gles2.glGetShaderiv(shader, GL_COMPILE_STATUS, &success);
48     if (success == GL_FALSE) {
49         GLint infoLogLength;
50         s_gles2.glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infoLogLength);
51         std::string infoLog(infoLogLength + 1, '\0');
52         fprintf(stderr, "%s: TextureDraw shader compile failed.\n", __func__);
53         s_gles2.glGetShaderInfoLog(shader, infoLogLength, 0, &infoLog[0]);
54         fprintf(stderr, "%s: Info log:\n%s\n", __func__,
55                 infoLog.c_str());
56         fprintf(stderr, "%s: Source:\n%s\n", __func__,
57                 shaderText);
58         s_gles2.glDeleteShader(shader);
59 
60         // No point in continuing as it's going to be a black screen.
61         // Send a crash report.
62         // emugl::emugl_crash_reporter(
63         //     "FATAL: Could not compile shader for guest framebuffer blit. "
64         //     "There may be an issue with the GPU drivers on your machine. "
65         //     "Try using software rendering; launch the emulator "
66         //     "from the command line with -gpu swiftshader_indirect. ");
67     }
68 
69     return shader;
70 }
71 
72 // No scaling / projection since we want to fill the whole viewport with
73 // the texture, hence a trivial vertex shader that only supports translation.
74 // Note: we used to have a proper free-angle rotation support in this shader,
75 //  but looks like SwiftShader doesn't support either complicated calculations
76 //  for gl_Position/varyings or just doesn't like trigonometric functions in
77 //  shader; anyway the new code has hardcoded texture coordinate mapping for
78 //  different rotation angles and works in both native OpenGL and SwiftShader.
79 const char kVertexShaderSource[] =
80     "attribute vec4 position;\n"
81     "attribute vec2 inCoord;\n"
82     "varying vec2 outCoord;\n"
83     "uniform vec2 translation;\n"
84     "uniform vec2 scale;\n"
85     "uniform vec2 coordTranslation;\n"
86     "uniform vec2 coordScale;\n"
87 
88     "void main(void) {\n"
89     "  gl_Position.xy = position.xy * scale.xy - translation.xy;\n"
90     "  gl_Position.zw = position.zw;\n"
91     "  outCoord = inCoord * coordScale + coordTranslation;\n"
92     "}\n";
93 
94 // Similarly, just interpolate texture coordinates.
95 const char kFragmentShaderSource[] =
96     "#define kComposeModeDevice 2\n"
97     "precision mediump float;\n"
98     "varying lowp vec2 outCoord;\n"
99     "uniform sampler2D tex;\n"
100     "uniform float alpha;\n"
101     "uniform int composeMode;\n"
102     "uniform vec4 color ;\n"
103 
104     "void main(void) {\n"
105     "  if (composeMode == kComposeModeDevice) {\n"
106     "    gl_FragColor = alpha * texture2D(tex, outCoord);\n"
107     "  } else {\n"
108     "    gl_FragColor = alpha * color;\n"
109     "  }\n"
110     "}\n";
111 
112 // Hard-coded arrays of vertex information.
113 struct Vertex {
114     float pos[3];
115     float coord[2];
116 };
117 
118 const Vertex kVertices[] = {
119     // 0 degree
120     {{ +1, -1, +0 }, { +1, +0 }},
121     {{ +1, +1, +0 }, { +1, +1 }},
122     {{ -1, +1, +0 }, { +0, +1 }},
123     {{ -1, -1, +0 }, { +0, +0 }},
124     // 90 degree clock-wise
125     {{ +1, -1, +0 }, { +1, +1 }},
126     {{ +1, +1, +0 }, { +0, +1 }},
127     {{ -1, +1, +0 }, { +0, +0 }},
128     {{ -1, -1, +0 }, { +1, +0 }},
129     // 180 degree clock-wise
130     {{ +1, -1, +0 }, { +0, +1 }},
131     {{ +1, +1, +0 }, { +0, +0 }},
132     {{ -1, +1, +0 }, { +1, +0 }},
133     {{ -1, -1, +0 }, { +1, +1 }},
134     // 270 degree clock-wise
135     {{ +1, -1, +0 }, { +0, +0 }},
136     {{ +1, +1, +0 }, { +1, +0 }},
137     {{ -1, +1, +0 }, { +1, +1 }},
138     {{ -1, -1, +0 }, { +0, +1 }},
139     // flip horizontally
140     {{ +1, -1, +0 }, { +0, +0 }},
141     {{ +1, +1, +0 }, { +0, +1 }},
142     {{ -1, +1, +0 }, { +1, +1 }},
143     {{ -1, -1, +0 }, { +1, +0 }},
144     // flip vertically
145     {{ +1, -1, +0 }, { +1, +1 }},
146     {{ +1, +1, +0 }, { +1, +0 }},
147     {{ -1, +1, +0 }, { +0, +0 }},
148     {{ -1, -1, +0 }, { +0, +1 }},
149     // flip source image horizontally, the rotate 90 degrees clock-wise
150     {{ +1, -1, +0 }, { +0, +1 }},
151     {{ +1, +1, +0 }, { +1, +1 }},
152     {{ -1, +1, +0 }, { +1, +0 }},
153     {{ -1, -1, +0 }, { +0, +0 }},
154     // flip source image vertically, the rotate 90 degrees clock-wise
155     {{ +1, -1, +0 }, { +1, +0 }},
156     {{ +1, +1, +0 }, { +0, +0 }},
157     {{ -1, +1, +0 }, { +0, +1 }},
158     {{ -1, -1, +0 }, { +1, +1 }},
159 };
160 
161 // Vertex indices for predefined rotation angles.
162 const GLubyte kIndices[] = {
163     0, 1, 2, 2, 3, 0,      // 0
164     4, 5, 6, 6, 7, 4,      // 90
165     8, 9, 10, 10, 11, 8,   // 180
166     12, 13, 14, 14, 15, 12, // 270
167     16, 17, 18 ,18, 19, 16, // flip h
168     20, 21, 22, 22, 23, 20, // flip v
169     24, 25, 26, 26, 27, 24, // flip h, 90
170     28, 29, 30, 30, 31, 28  // flip v, 90
171 };
172 
173 const GLint kIndicesPerDraw = 6;
174 
175 }  // namespace
176 
TextureDraw()177 TextureDraw::TextureDraw()
178     : mVertexShader(0),
179       mFragmentShader(0),
180       mProgram(0),
181       mCoordTranslation(-1),
182       mCoordScale(-1),
183       mPositionSlot(-1),
184       mInCoordSlot(-1),
185       mScaleSlot(-1),
186       mTextureSlot(-1),
187       mTranslationSlot(-1),
188       mMaskTexture(0),
189       mMaskTextureWidth(0),
190       mMaskTextureHeight(0),
191       mHaveNewMask(false),
192       mMaskIsValid(false),
193       mShouldReallocateTexture(true) {
194     // Create shaders and program.
195     mVertexShader = createShader(GL_VERTEX_SHADER, kVertexShaderSource);
196     mFragmentShader = createShader(GL_FRAGMENT_SHADER, kFragmentShaderSource);
197 
198     mProgram = s_gles2.glCreateProgram();
199     s_gles2.glAttachShader(mProgram, mVertexShader);
200     s_gles2.glAttachShader(mProgram, mFragmentShader);
201 
202     GLint success;
203     s_gles2.glLinkProgram(mProgram);
204     s_gles2.glGetProgramiv(mProgram, GL_LINK_STATUS, &success);
205     if (success == GL_FALSE) {
206         GLchar messages[256];
207         s_gles2.glGetProgramInfoLog(
208                 mProgram, sizeof(messages), 0, &messages[0]);
209         ERR("%s: Could not create/link program: %s\n", __FUNCTION__, messages);
210         s_gles2.glDeleteProgram(mProgram);
211         mProgram = 0;
212         return;
213     }
214 
215     s_gles2.glUseProgram(mProgram);
216 
217     // Retrieve attribute/uniform locations.
218     mPositionSlot = s_gles2.glGetAttribLocation(mProgram, "position");
219     s_gles2.glEnableVertexAttribArray(mPositionSlot);
220 
221     mInCoordSlot = s_gles2.glGetAttribLocation(mProgram, "inCoord");
222     s_gles2.glEnableVertexAttribArray(mInCoordSlot);
223 
224     mAlpha = s_gles2.glGetUniformLocation(mProgram, "alpha");
225     mComposeMode = s_gles2.glGetUniformLocation(mProgram, "composeMode");
226     mColor = s_gles2.glGetUniformLocation(mProgram, "color");
227     mCoordTranslation = s_gles2.glGetUniformLocation(mProgram, "coordTranslation");
228     mCoordScale = s_gles2.glGetUniformLocation(mProgram, "coordScale");
229     mScaleSlot = s_gles2.glGetUniformLocation(mProgram, "scale");
230     mTranslationSlot = s_gles2.glGetUniformLocation(mProgram, "translation");
231     mTextureSlot = s_gles2.glGetUniformLocation(mProgram, "tex");
232 
233     // set default uniform values
234     s_gles2.glUniform1f(mAlpha, 1.0);
235     s_gles2.glUniform1i(mComposeMode, 2);
236     s_gles2.glUniform2f(mTranslationSlot, 0.0, 0.0);
237     s_gles2.glUniform2f(mScaleSlot, 1.0, 1.0);
238     s_gles2.glUniform2f(mCoordTranslation, 0.0, 0.0);
239     s_gles2.glUniform2f(mCoordScale, 1.0, 1.0);
240 
241 #if 0
242     printf("SLOTS position=%d inCoord=%d texture=%d translation=%d\n",
243           mPositionSlot, mInCoordSlot, mTextureSlot, mTranslationSlot);
244 #endif
245 
246     // Create vertex and index buffers.
247     s_gles2.glGenBuffers(1, &mVertexBuffer);
248     s_gles2.glBindBuffer(GL_ARRAY_BUFFER, mVertexBuffer);
249     s_gles2.glBufferData(
250             GL_ARRAY_BUFFER, sizeof(kVertices), kVertices, GL_STATIC_DRAW);
251 
252     s_gles2.glGenBuffers(1, &mIndexBuffer);
253     s_gles2.glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mIndexBuffer);
254     s_gles2.glBufferData(GL_ELEMENT_ARRAY_BUFFER,
255                          sizeof(kIndices),
256                          kIndices,
257                          GL_STATIC_DRAW);
258 
259     // Reset state.
260     s_gles2.glUseProgram(0);
261     s_gles2.glDisableVertexAttribArray(mPositionSlot);
262     s_gles2.glDisableVertexAttribArray(mInCoordSlot);
263     s_gles2.glBindBuffer(GL_ARRAY_BUFFER, 0);
264     s_gles2.glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
265 
266     // Create a texture handle for use with an overlay mask
267     s_gles2.glGenTextures(1, &mMaskTexture);
268 }
269 
drawImpl(GLuint texture,float rotation,float dx,float dy,bool wantOverlay)270 bool TextureDraw::drawImpl(GLuint texture, float rotation,
271                            float dx, float dy, bool wantOverlay) {
272     if (!mProgram) {
273         ERR("%s: no program\n", __FUNCTION__);
274         return false;
275     }
276 
277     // TODO(digit): Save previous program state.
278 
279     s_gles2.glUseProgram(mProgram);
280 
281 #ifndef NDEBUG
282     GLenum err = s_gles2.glGetError();
283     if (err != GL_NO_ERROR) {
284         ERR("%s: Could not use program error=0x%x\n",
285             __FUNCTION__, err);
286     }
287 #endif
288 
289     // Setup the |position| attribute values.
290     s_gles2.glBindBuffer(GL_ARRAY_BUFFER, mVertexBuffer);
291 
292 #ifndef NDEBUG
293     err = s_gles2.glGetError();
294     if (err != GL_NO_ERROR) {
295         ERR("%s: Could not bind GL_ARRAY_BUFFER error=0x%x\n",
296             __FUNCTION__, err);
297     }
298 #endif
299 
300     s_gles2.glEnableVertexAttribArray(mPositionSlot);
301     s_gles2.glVertexAttribPointer(mPositionSlot,
302                                   3,
303                                   GL_FLOAT,
304                                   GL_FALSE,
305                                   sizeof(Vertex),
306                                   0);
307 
308 #ifndef NDEBUG
309     err = s_gles2.glGetError();
310     if (err != GL_NO_ERROR) {
311         ERR("%s: Could glVertexAttribPointer with mPositionSlot error=0x%x\n",
312             __FUNCTION__, err);
313     }
314 #endif
315 
316     // Setup the |inCoord| attribute values.
317     s_gles2.glEnableVertexAttribArray(mInCoordSlot);
318     s_gles2.glVertexAttribPointer(mInCoordSlot,
319                                   2,
320                                   GL_FLOAT,
321                                   GL_FALSE,
322                                   sizeof(Vertex),
323                                   reinterpret_cast<GLvoid*>(
324                                         static_cast<uintptr_t>(
325                                                 sizeof(float) * 3)));
326 
327     // setup the |texture| uniform value.
328     s_gles2.glActiveTexture(GL_TEXTURE0);
329     s_gles2.glBindTexture(GL_TEXTURE_2D, texture);
330     s_gles2.glUniform1i(mTextureSlot, 0);
331 
332     // setup the |translation| uniform value.
333     s_gles2.glUniform2f(mTranslationSlot, dx, dy);
334 
335 #ifndef NDEBUG
336     // Validate program, just to be sure.
337     s_gles2.glValidateProgram(mProgram);
338     GLint validState = 0;
339     s_gles2.glGetProgramiv(mProgram, GL_VALIDATE_STATUS, &validState);
340     if (validState == GL_FALSE) {
341         GLchar messages[256] = {};
342         s_gles2.glGetProgramInfoLog(
343                 mProgram, sizeof(messages), 0, &messages[0]);
344         ERR("%s: Could not run program: '%s'\n", __FUNCTION__, messages);
345         return false;
346     }
347 #endif
348 
349     // Do the rendering.
350     s_gles2.glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mIndexBuffer);
351 #ifndef NDEBUG
352     err = s_gles2.glGetError();
353     if (err != GL_NO_ERROR) {
354         ERR("%s: Could not glBindBuffer(GL_ELEMENT_ARRAY_BUFFER) error=0x%x\n",
355             __FUNCTION__, err);
356     }
357 #endif
358 
359     // We may only get 0, 90, 180, 270 in |rotation| so far.
360     const int intRotation = ((int)rotation)/90;
361     assert(intRotation >= 0 && intRotation <= 3);
362     intptr_t indexShift = 0;
363     switch (intRotation) {
364     case 0:
365         indexShift = 5 * kIndicesPerDraw;
366         break;
367     case 1:
368         indexShift = 7 * kIndicesPerDraw;
369         break;
370     case 2:
371         indexShift = 4 * kIndicesPerDraw;
372         break;
373     case 3:
374         indexShift = 6 * kIndicesPerDraw;
375         break;
376     }
377 
378     s_gles2.glClear(GL_COLOR_BUFFER_BIT);
379     s_gles2.glDrawElements(GL_TRIANGLES, kIndicesPerDraw, GL_UNSIGNED_BYTE,
380                            (const GLvoid*)indexShift);
381 
382     bool shouldDrawMask = false;
383     GLfloat scale[2];
384     s_gles2.glGetUniformfv(mProgram, mScaleSlot, scale);
385     GLfloat overlayScale[2];
386     {
387         android::base::AutoLock lock(mMaskLock);
388         if (wantOverlay && mHaveNewMask) {
389             // Create a texture from the mask image and make it
390             // available to be blended
391             GLint prevUnpackAlignment;
392             s_gles2.glGetIntegerv(GL_UNPACK_ALIGNMENT, &prevUnpackAlignment);
393             s_gles2.glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
394 
395             s_gles2.glBindTexture(GL_TEXTURE_2D, mMaskTexture);
396 
397             s_gles2.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
398             s_gles2.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
399 
400             if (mShouldReallocateTexture) {
401                 mMaskTextureWidth = std::max(mMaskTextureWidth, mMaskWidth);
402                 mMaskTextureHeight = std::max(mMaskTextureHeight, mMaskHeight);
403                 // mMaskPixels is actually not used here, we only use
404                 // glTexImage2D here to resize the texture
405                 s_gles2.glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8,
406                                      mMaskTextureWidth, mMaskTextureHeight, 0,
407                                      GL_RGBA, GL_UNSIGNED_BYTE,
408                                      mMaskPixels.data());
409                 mShouldReallocateTexture = false;
410             }
411 
412             // Put the new texture in the center.
413             s_gles2.glTexSubImage2D(
414                     GL_TEXTURE_2D, 0, (mMaskTextureWidth - mMaskWidth) / 2,
415                     (mMaskTextureHeight - mMaskHeight) / 2, mMaskWidth,
416                     mMaskHeight, GL_RGBA, GL_UNSIGNED_BYTE, mMaskPixels.data());
417 
418             s_gles2.glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
419             s_gles2.glEnable(GL_BLEND);
420 
421             s_gles2.glPixelStorei(GL_UNPACK_ALIGNMENT, prevUnpackAlignment);
422 
423             mHaveNewMask = false;
424             mMaskIsValid = true;
425         }
426         shouldDrawMask = mMaskIsValid && wantOverlay;
427         // Scale the texture to only show that actual mask.
428         overlayScale[0] = static_cast<float>(mMaskTextureWidth) /
429                           static_cast<float>(mMaskWidth) * scale[0];
430         overlayScale[1] = static_cast<float>(mMaskTextureHeight) /
431                           static_cast<float>(mMaskHeight) * scale[1];
432     }
433 
434     if (shouldDrawMask) {
435         if (mBlendResetNeeded) {
436             s_gles2.glEnable(GL_BLEND);
437             mBlendResetNeeded = false;
438         }
439         s_gles2.glUniform2f(mScaleSlot, overlayScale[0], overlayScale[1]);
440         // mMaskTexture should only be accessed on the thread where drawImpl is
441         // called, hence no need for lock.
442         s_gles2.glBindTexture(GL_TEXTURE_2D, mMaskTexture);
443         s_gles2.glDrawElements(GL_TRIANGLES, kIndicesPerDraw, GL_UNSIGNED_BYTE,
444                                (const GLvoid*)indexShift);
445         // Reset to the "normal" texture
446         s_gles2.glBindTexture(GL_TEXTURE_2D, texture);
447         s_gles2.glUniform2f(mScaleSlot, scale[0], scale[1]);
448     }
449 
450 #ifndef NDEBUG
451     err = s_gles2.glGetError();
452     if (err != GL_NO_ERROR) {
453         ERR("%s: Could not glDrawElements() error=0x%x\n",
454             __FUNCTION__, err);
455     }
456 #endif
457 
458     // TODO(digit): Restore previous program state.
459     // For now, reset back to zero and assume other users will
460     // follow the same protocol.
461     s_gles2.glUseProgram(0);
462     s_gles2.glDisableVertexAttribArray(mPositionSlot);
463     s_gles2.glDisableVertexAttribArray(mInCoordSlot);
464     s_gles2.glBindBuffer(GL_ARRAY_BUFFER, 0);
465     s_gles2.glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
466 
467     return true;
468 }
469 
~TextureDraw()470 TextureDraw::~TextureDraw() {
471     s_gles2.glDeleteBuffers(1, &mIndexBuffer);
472     s_gles2.glDeleteBuffers(1, &mVertexBuffer);
473 
474     if (mFragmentShader) {
475         s_gles2.glDeleteShader(mFragmentShader);
476     }
477     if (mVertexShader) {
478         s_gles2.glDeleteShader(mVertexShader);
479     }
480     if (mMaskTexture) {
481         s_gles2.glDeleteTextures(1, &mMaskTexture);
482     }
483 }
484 
setScreenMask(int width,int height,const unsigned char * rgbaData)485 void TextureDraw::setScreenMask(int width, int height, const unsigned char* rgbaData) {
486     android::base::AutoLock lock(mMaskLock);
487     if (width <= 0 || height <= 0 || rgbaData == nullptr) {
488         mMaskIsValid = false;
489         return;
490     }
491 
492     mShouldReallocateTexture =
493             (width > mMaskTextureWidth) || (height > mMaskTextureHeight);
494     auto nextMaskTextureWidth = std::max(width, mMaskTextureWidth);
495     auto nextMaskTextureHeight = std::max(height, mMaskTextureHeight);
496     mMaskPixels.resize(nextMaskTextureWidth * nextMaskTextureHeight * 4);
497     // Save the data for use in the right context
498     std::copy(rgbaData, rgbaData + width * height * 4, mMaskPixels.begin());
499 
500     mHaveNewMask = true;
501     mMaskWidth = width;
502     mMaskHeight = height;
503 }
504 
prepareForDrawLayer()505 void TextureDraw::prepareForDrawLayer() {
506     if (!mProgram) {
507         ERR("%s: no program\n", __FUNCTION__);
508         return;
509     }
510     s_gles2.glUseProgram(mProgram);
511 #ifndef NDEBUG
512     GLenum err = s_gles2.glGetError();
513     if (err != GL_NO_ERROR) {
514         ERR("%s: Could not use program error=0x%x\n",
515             __FUNCTION__, err);
516     }
517 #endif
518 
519     s_gles2.glBindBuffer(GL_ARRAY_BUFFER, mVertexBuffer);
520 #ifndef NDEBUG
521     err = s_gles2.glGetError();
522     if (err != GL_NO_ERROR) {
523         ERR("%s: Could not bind GL_ARRAY_BUFFER error=0x%x\n",
524             __FUNCTION__, err);
525     }
526 #endif
527     s_gles2.glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mIndexBuffer);
528 #ifndef NDEBUG
529     err = s_gles2.glGetError();
530     if (err != GL_NO_ERROR) {
531         ERR("%s: Could not glBindBuffer(GL_ELEMENT_ARRAY_BUFFER) error=0x%x\n",
532             __FUNCTION__, err);
533     }
534 #endif
535 
536     s_gles2.glEnableVertexAttribArray(mPositionSlot);
537     s_gles2.glVertexAttribPointer(mPositionSlot,
538                                   3,
539                                   GL_FLOAT,
540                                   GL_FALSE,
541                                   sizeof(Vertex),
542                                   0);
543 
544     s_gles2.glEnableVertexAttribArray(mInCoordSlot);
545     s_gles2.glVertexAttribPointer(mInCoordSlot,
546                                   2,
547                                   GL_FLOAT,
548                                   GL_FALSE,
549                                   sizeof(Vertex),
550                                   reinterpret_cast<GLvoid*>(
551                                         static_cast<uintptr_t>(
552                                                 sizeof(float) * 3)));
553 #ifndef NDEBUG
554     err = s_gles2.glGetError();
555     if (err != GL_NO_ERROR) {
556         ERR("%s: Could glVertexAttribPointer with mPositionSlot error=0x%x\n",
557             __FUNCTION__, err);
558     }
559 #endif
560 
561    // set composition default
562     s_gles2.glUniform1i(mComposeMode, 2);
563     s_gles2.glActiveTexture(GL_TEXTURE0);
564     s_gles2.glUniform1i(mTextureSlot, 0);
565     s_gles2.glEnable(GL_BLEND);
566     s_gles2.glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
567 
568     // clear color
569     s_gles2.glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
570 }
571 
drawLayer(ComposeLayer * l,int frameWidth,int frameHeight,int cbWidth,int cbHeight,GLuint texture)572 void TextureDraw::drawLayer(ComposeLayer* l, int frameWidth, int frameHeight,
573                             int cbWidth, int cbHeight, GLuint texture) {
574     switch(l->composeMode) {
575         case HWC2_COMPOSITION_DEVICE:
576             s_gles2.glBindTexture(GL_TEXTURE_2D, texture);
577             break;
578         case HWC2_COMPOSITION_SOLID_COLOR: {
579             s_gles2.glUniform1i(mComposeMode, l->composeMode);
580             s_gles2.glUniform4f(mColor,
581                                 l->color.r/255.0, l->color.g/255.0,
582                                 l->color.b/255.0, l->color.a/255.0);
583             break;
584         }
585         case HWC2_COMPOSITION_CLIENT:
586         case HWC2_COMPOSITION_CURSOR:
587         case HWC2_COMPOSITION_SIDEBAND:
588         case HWC2_COMPOSITION_INVALID:
589         default:
590             ERR("%s: invalid composition mode %d", __FUNCTION__, l->composeMode);
591             return;
592     }
593 
594     switch(l->blendMode) {
595         case HWC2_BLEND_MODE_NONE:
596             s_gles2.glDisable(GL_BLEND);
597             mBlendResetNeeded = true;
598             break;
599         case HWC2_BLEND_MODE_PREMULTIPLIED:
600             break;
601         case HWC2_BLEND_MODE_INVALID:
602         case HWC2_BLEND_MODE_COVERAGE:
603         default:
604             ERR("%s: invalid blendMode %d", __FUNCTION__, l->blendMode);
605             return;
606     }
607 
608     s_gles2.glUniform1f(mAlpha, l->alpha);
609 
610     float edges[4];
611     edges[0] = 1 - 2.0 * (frameWidth - l->displayFrame.left)/frameWidth;
612     edges[1] = 1 - 2.0 * (frameHeight - l->displayFrame.top)/frameHeight;
613     edges[2] = 1 - 2.0 * (frameWidth - l->displayFrame.right)/frameWidth;
614     edges[3] = 1- 2.0 * (frameHeight - l->displayFrame.bottom)/frameHeight;
615 
616     float crop[4];
617     crop[0] = l->crop.left/cbWidth;
618     crop[1] = l->crop.top/cbHeight;
619     crop[2] = l->crop.right/cbWidth;
620     crop[3] = l->crop.bottom/cbHeight;
621 
622     // setup the |translation| uniform value.
623     s_gles2.glUniform2f(mTranslationSlot, (-edges[2] - edges[0])/2,
624                         (-edges[3] - edges[1])/2);
625     s_gles2.glUniform2f(mScaleSlot, (edges[2] - edges[0])/2,
626                         (edges[1] - edges[3])/2);
627     s_gles2.glUniform2f(mCoordTranslation, crop[0], crop[3]);
628     s_gles2.glUniform2f(mCoordScale, crop[2] - crop[0], crop[1] - crop[3]);
629 
630     intptr_t indexShift;
631     switch(l->transform) {
632     case HWC_TRANSFORM_ROT_90:
633         indexShift = 1 * kIndicesPerDraw;
634         break;
635     case HWC_TRANSFORM_ROT_180:
636         indexShift = 2 * kIndicesPerDraw;
637         break;
638     case HWC_TRANSFORM_ROT_270:
639         indexShift = 3 * kIndicesPerDraw;
640         break;
641     case HWC_TRANSFORM_FLIP_H:
642         indexShift = 4 * kIndicesPerDraw;
643         break;
644     case HWC_TRANSFORM_FLIP_V:
645         indexShift = 5 * kIndicesPerDraw;
646         break;
647     case HWC_TRANSFORM_FLIP_H_ROT_90:
648         indexShift = 6 * kIndicesPerDraw;
649         break;
650     case HWC_TRANSFORM_FLIP_V_ROT_90:
651         indexShift = 7 * kIndicesPerDraw;
652         break;
653     default:
654         indexShift = 0;
655     }
656     s_gles2.glDrawElements(GL_TRIANGLES, kIndicesPerDraw, GL_UNSIGNED_BYTE,
657                            (const GLvoid*)indexShift);
658 #ifndef NDEBUG
659     GLenum err = s_gles2.glGetError();
660     if (err != GL_NO_ERROR) {
661         ERR("%s: Could not glDrawElements() error=0x%x\n",
662             __FUNCTION__, err);
663     }
664 #endif
665 
666     // restore the default value for the next draw layer
667     if (l->composeMode != HWC2_COMPOSITION_DEVICE) {
668         s_gles2.glUniform1i(mComposeMode, HWC2_COMPOSITION_DEVICE);
669     }
670     if (l->blendMode != HWC2_BLEND_MODE_PREMULTIPLIED) {
671         s_gles2.glEnable(GL_BLEND);
672         mBlendResetNeeded = false;
673         s_gles2.glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
674     }
675 }
676 
677 // Do Post right after drawing each layer, so keep using this program
cleanupForDrawLayer()678 void TextureDraw::cleanupForDrawLayer() {
679     s_gles2.glUniform1f(mAlpha, 1.0);
680     s_gles2.glUniform1i(mComposeMode, HWC2_COMPOSITION_DEVICE);
681     s_gles2.glUniform2f(mTranslationSlot, 0.0, 0.0);
682     s_gles2.glUniform2f(mScaleSlot, 1.0, 1.0);
683     s_gles2.glUniform2f(mCoordTranslation, 0.0, 0.0);
684     s_gles2.glUniform2f(mCoordScale, 1.0, 1.0);
685 }
686