• 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 // The purpose of YUVConverter is to use
28 // OpenGL shaders to convert YUV images to RGB
29 // images that can be displayed on screen.
30 // Doing this on the GPU can be much faster than
31 // on the CPU.
32 
33 // Usage:
34 // 0. Have a current OpenGL context working.
35 // 1. Constructing the YUVConverter object will allocate
36 //    OpenGL resources needed to convert, given the desired
37 //    |width| and |height| of the buffer.
38 // 2. To convert a given YUV buffer of |pixels|, call
39 //    the drawConvert method (with x, y, width, and height
40 //    arguments depicting the region to convert).
41 //    The RGB version of the YUV buffer will be drawn
42 //    to the current framebuffer. To retrieve
43 //    the result, if the user of the result is an OpenGL texture,
44 //    it suffices to have that texture be the color attachment
45 //    of the framebuffer object. Or, if you want the results
46 //    on the CPU, call glReadPixels() after the call to drawConvert().
47 class YUVConverter {
48 public:
49     // call ctor when creating a gralloc buffer
50     // with YUV format
51     YUVConverter(int width, int height, FrameworkFormat format);
52     // destroy when ColorBuffer is destroyed
53     ~YUVConverter();
54     // call when gralloc_unlock updates
55     // the host color buffer
56     // (rcUpdateColorBuffer)
57     void drawConvert(int x, int y, int width, int height, char* pixels);
58 
59     uint32_t getDataSize();
60     // read YUV data into pixels, exactly pixels_size bytes;
61     // if size mismatches, will read nothing.
62     void readPixels(uint8_t* pixels, uint32_t pixels_size);
63 
64     void swapTextures(uint32_t type, uint32_t* textures);
65 
66     // NV12 and YUV420 are all packed
NV12ToYUV420PlanarInPlaceConvert(int nWidth,int nHeight,uint8_t * pFrame,uint8_t * pQuad)67     static void NV12ToYUV420PlanarInPlaceConvert(int nWidth,
68                                                  int nHeight,
69                                                  uint8_t* pFrame,
70                                                  uint8_t* pQuad) {
71         std::vector<uint8_t> tmp;
72         if (pQuad == nullptr) {
73             tmp.resize(nWidth * nHeight / 4);
74             pQuad = tmp.data();
75         }
76         int nPitch = nWidth;
77         uint8_t *puv = pFrame + nPitch * nHeight, *pu = puv,
78                 *pv = puv + nPitch * nHeight / 4;
79         for (int y = 0; y < nHeight / 2; y++) {
80             for (int x = 0; x < nWidth / 2; x++) {
81                 pu[y * nPitch / 2 + x] = puv[y * nPitch + x * 2];
82                 pQuad[y * nWidth / 2 + x] = puv[y * nPitch + x * 2 + 1];
83             }
84         }
85         memcpy(pv, pQuad, nWidth * nHeight / 4);
86     }
87 
88     // public so other classes can call
89     static void createYUVGLTex(GLenum texture_unit,
90                                GLsizei width,
91                                GLsizei height,
92                                GLuint* texName_out,
93                                bool uvInterleaved);
94 private:
95     void init(int w, int h, FrameworkFormat format);
96     void reset();
97 
98     // For dealing with n-pixel-aligned buffers
99     void updateCutoffs(float width, float ywidth, float halfwidth, float cwidth);
100     int mWidth = 0;
101     int mHeight = 0;
102     FrameworkFormat mFormat;
103     // colorbuffer w/h/format, could be different
104     FrameworkFormat mCbFormat;
105     // We need the following GL objects:
106     GLuint mProgram = 0;
107     GLuint mVbuf = 0;
108     GLuint mIbuf = 0;
109     GLuint mYtex = 0;
110     GLuint mUtex = 0;
111     GLuint mVtex = 0;
112     GLuint mVUtex = 0;
113     GLuint mUVtex = 0;
114     // shader uniform locations
115     GLint mYWidthCutoffLoc = -1;
116     GLint mCWidthCutoffLoc = -1;
117     GLint mYSamplerLoc = -1;
118     GLint mUSamplerLoc = -1;
119     GLint mVSamplerLoc = -1;
120     GLint mVUSamplerLoc = -1;
121     GLint mInCoordLoc = -1;
122     GLint mPosLoc = -1;
123     float mYWidthCutoff = 1.0;
124     float mCWidthCutoff = 1.0;
125 
126     // YUVConverter can end up being used
127     // in a TextureDraw / subwindow context, and subsequently
128     // overwrite the previous state.
129     // This section is so YUVConverter can be used in the middle
130     // of any GL context without impacting what's
131     // already going on there, by saving/restoring the state
132     // that it is impacting.
133     void saveGLState();
134     void restoreGLState();
135     // Impacted state
136     GLfloat mCurrViewport[4] = {};
137     GLint mCurrTexUnit = 0;
138     GLint mCurrProgram = 0;
139     GLint mCurrTexBind = 0;
140     GLint mCurrVbo = 0;
141     GLint mCurrIbo = 0;
142 };
143