• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2 * Copyright (C) 2016 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16 
17 #pragma once
18 
19 #include <GLES2/gl2.h>
20 #include <GLES2/gl2ext.h>
21 
22 #include "FrameworkFormats.h"
23 
24 #include <stdint.h>
25 #include <cstring>
26 #include <vector>
27 
28 namespace gfxstream {
29 namespace gl {
30 
31 enum class YUVPlane : int {
32     Y = 0,
33     U = 1,
34     V = 2,
35     UV = 3,
36 };
37 
38 // The purpose of YUVConverter is to use
39 // OpenGL shaders to convert YUV images to RGB
40 // images that can be displayed on screen.
41 // Doing this on the GPU can be much faster than
42 // on the CPU.
43 
44 // Usage:
45 // 0. Have a current OpenGL context working.
46 // 1. Constructing the YUVConverter object will allocate
47 //    OpenGL resources needed to convert, given the desired
48 //    |width| and |height| of the buffer.
49 // 2. To convert a given YUV buffer of |pixels|, call
50 //    the drawConvert method (with x, y, width, and height
51 //    arguments depicting the region to convert).
52 //    The RGB version of the YUV buffer will be drawn
53 //    to the current framebuffer. To retrieve
54 //    the result, if the user of the result is an OpenGL texture,
55 //    it suffices to have that texture be the color attachment
56 //    of the framebuffer object. Or, if you want the results
57 //    on the CPU, call glReadPixels() after the call to drawConvert().
58 class YUVConverter {
59 public:
60     // call ctor when creating a gralloc buffer
61     // with YUV format
62     YUVConverter(int width, int height, FrameworkFormat format,
63                  bool yuv420888ToNv21);
64     // destroy when ColorBuffer is destroyed
65     ~YUVConverter();
66     // call when gralloc_unlock updates
67     // the host color buffer
68     // (rcUpdateColorBuffer)
69     void drawConvert(int x, int y, int width, int height, const char* pixels);
70     void drawConvertFromFormat(FrameworkFormat format, int x, int y, int width, int height,
71                                const char* pixels, void* metadata = nullptr);
72 
73     uint32_t getDataSize();
74     // read YUV data into pixels, exactly pixels_size bytes;
75     // if size mismatches, will read nothing.
76     void readPixels(uint8_t* pixels, uint32_t pixels_size);
77 
78     void swapTextures(FrameworkFormat type, GLuint* textures, void* metadata = nullptr);
79 
80     // public so other classes can call
81     static void createYUVGLTex(GLenum textureUnit,
82                                GLsizei width,
83                                GLsizei height,
84                                FrameworkFormat format,
85                                bool yuv420888ToNv21,
86                                YUVPlane plane,
87                                GLuint* outTextureName);
88 private:
89     void init(int w, int h, FrameworkFormat format);
90     void reset();
91 
92     void createYUVGLShader();
93     void createYUVGLFullscreenQuad();
94 
95     // For dealing with n-pixel-aligned buffers
96     void updateCutoffs(float yWidth, float yStridePixels,
97                        float uvWidth, float uvStridePixels);
98 
99     int mWidth = 0;
100     int mHeight = 0;
101     FrameworkFormat mFormat;
102     // colorbuffer w/h/format, could be different
103     FrameworkFormat mColorBufferFormat;
104     // We need the following GL objects:
105     GLuint mProgram = 0;
106     GLuint mQuadVertexBuffer = 0;
107     GLuint mQuadIndexBuffer = 0;
108     GLuint mTextureY = 0;
109     GLuint mTextureU = 0;
110     GLuint mTextureV = 0;
111     bool mTexturesSwapped = false;
112     GLint mUniformLocYWidthCutoff = -1;
113     GLint mUniformLocUVWidthCutoff = -1;
114     GLint mUniformLocSamplerY = -1;
115     GLint mUniformLocSamplerU = -1;
116     GLint mUniformLocSamplerV = -1;
117     GLint mAttributeLocPos = -1;
118     GLint mAttributeLocTexCoord = -1;
119 
120     float mYWidthCutoff = 1.0;
121     float mUVWidthCutoff = 1.0;
122     bool mHasGlsl3Support = false;
123     bool mYuv420888ToNv21 = false;
124 
125     // YUVConverter can end up being used
126     // in a TextureDraw / subwindow context, and subsequently
127     // overwrite the previous state.
128     // This section is so YUVConverter can be used in the middle
129     // of any GL context without impacting what's
130     // already going on there, by saving/restoring the state
131     // that it is impacting.
132     void saveGLState();
133     void restoreGLState();
134     // Impacted state
135     GLfloat mCurrViewport[4] = {};
136     GLint mCurrTexUnit = 0;
137     GLint mCurrProgram = 0;
138     GLint mCurrTexBind = 0;
139     GLint mCurrVbo = 0;
140     GLint mCurrIbo = 0;
141 
142     // color aspects related information
143     uint64_t mColorPrimaries = 4;  // this is 601, the default
144     uint64_t mColorRange = 2;      // this is limited range, the default
145     uint64_t mColorTransfer = 3;   // this is the default
146 
147     bool checkAndUpdateColorAspectsChanged(void* metadata);
148 };
149 
150 }  // namespace gl
151 }  // namespace gfxstream
152