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