1 // Copyright 2016 The SwiftShader Authors. All Rights Reserved. 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 #ifndef egl_Image_hpp 16 #define egl_Image_hpp 17 18 #include "libEGL/Texture.hpp" 19 #include "Renderer/Surface.hpp" 20 21 #include <GLES3/gl3.h> 22 #include <GLES2/gl2ext.h> 23 24 #if defined(__ANDROID__) 25 #include <hardware/gralloc.h> 26 #include <system/window.h> 27 #include "../../Common/GrallocAndroid.hpp" 28 #include "../../Common/DebugAndroid.hpp" 29 #define LOGLOCK(fmt, ...) // ALOGI(fmt " tid=%d", ##__VA_ARGS__, gettid()) 30 #else 31 #include <assert.h> 32 #define LOGLOCK(...) 33 #endif 34 35 // Implementation-defined formats 36 #define SW_YV12_BT601 0x32315659 // YCrCb 4:2:0 Planar, 16-byte aligned, BT.601 color space, studio swing 37 #define SW_YV12_BT709 0x48315659 // YCrCb 4:2:0 Planar, 16-byte aligned, BT.709 color space, studio swing 38 #define SW_YV12_JFIF 0x4A315659 // YCrCb 4:2:0 Planar, 16-byte aligned, BT.601 color space, full swing 39 40 namespace egl 41 { 42 43 sw::Format ConvertFormatType(GLenum format, GLenum type); 44 sw::Format SelectInternalFormat(GLenum format, GLenum type); 45 GLsizei ComputePitch(GLsizei width, GLenum format, GLenum type, GLint alignment); 46 GLsizei ComputeCompressedSize(GLsizei width, GLsizei height, GLenum format); 47 size_t ComputePackingOffset(GLenum format, GLenum type, GLsizei width, GLsizei height, GLint alignment, GLint skipImages, GLint skipRows, GLint skipPixels); 48 49 class Image : public sw::Surface, public gl::Object 50 { 51 public: 52 // 2D texture image 53 Image(Texture *parentTexture, GLsizei width, GLsizei height, GLenum format, GLenum type) 54 : sw::Surface(parentTexture->getResource(), width, height, 1, SelectInternalFormat(format, type), true, true), 55 width(width), height(height), format(format), type(type), internalFormat(SelectInternalFormat(format, type)), depth(1), 56 parentTexture(parentTexture) 57 { 58 shared = false; 59 Object::addRef(); 60 parentTexture->addRef(); 61 } 62 63 // 3D texture image 64 Image(Texture *parentTexture, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type) 65 : sw::Surface(parentTexture->getResource(), width, height, depth, SelectInternalFormat(format, type), true, true), 66 width(width), height(height), format(format), type(type), internalFormat(SelectInternalFormat(format, type)), depth(depth), 67 parentTexture(parentTexture) 68 { 69 shared = false; 70 Object::addRef(); 71 parentTexture->addRef(); 72 } 73 74 // Native EGL image 75 Image(GLsizei width, GLsizei height, GLenum format, GLenum type, int pitchP) 76 : sw::Surface(nullptr, width, height, 1, SelectInternalFormat(format, type), true, true, pitchP), 77 width(width), height(height), format(format), type(type), internalFormat(SelectInternalFormat(format, type)), depth(1), 78 parentTexture(nullptr) 79 { 80 shared = true; 81 Object::addRef(); 82 } 83 84 // Render target 85 Image(GLsizei width, GLsizei height, sw::Format internalFormat, int multiSampleDepth, bool lockable) 86 : sw::Surface(nullptr, width, height, multiSampleDepth, internalFormat, lockable, true), 87 width(width), height(height), format(0 /*GL_NONE*/), type(0 /*GL_NONE*/), internalFormat(internalFormat), depth(multiSampleDepth), 88 parentTexture(nullptr) 89 { 90 shared = false; 91 Object::addRef(); 92 } 93 94 GLsizei getWidth() const 95 { 96 return width; 97 } 98 99 GLsizei getHeight() const 100 { 101 return height; 102 } 103 104 int getDepth() const 105 { 106 // FIXME: add member if the depth dimension (for 3D textures or 2D testure arrays) 107 // and multi sample depth are ever simultaneously required. 108 return depth; 109 } 110 111 GLenum getFormat() const 112 { 113 return format; 114 } 115 116 GLenum getType() const 117 { 118 return type; 119 } 120 121 sw::Format getInternalFormat() const 122 { 123 return internalFormat; 124 } 125 126 bool isShared() const 127 { 128 return shared; 129 } 130 131 void markShared() 132 { 133 shared = true; 134 } 135 136 virtual void *lock(unsigned int left, unsigned int top, sw::Lock lock) 137 { 138 return lockExternal(left, top, 0, lock, sw::PUBLIC); 139 } 140 141 unsigned int getPitch() const 142 { 143 return getExternalPitchB(); 144 } 145 146 virtual void unlock() 147 { 148 unlockExternal(); 149 } 150 151 struct UnpackInfo 152 { 153 UnpackInfo() : alignment(4), rowLength(0), imageHeight(0), skipPixels(0), skipRows(0), skipImages(0) {} 154 155 GLint alignment; 156 GLint rowLength; 157 GLint imageHeight; 158 GLint skipPixels; 159 GLint skipRows; 160 GLint skipImages; 161 }; 162 163 void loadImageData(GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const UnpackInfo& unpackInfo, const void *input); 164 void loadCompressedData(GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLsizei imageSize, const void *pixels); 165 166 void release() override; 167 void unbind(const Texture *parent); // Break parent ownership and release 168 bool isChildOf(const Texture *parent) const; 169 170 virtual void destroyShared() // Release a shared image 171 { 172 assert(shared); 173 shared = false; 174 release(); 175 } 176 177 protected: 178 const GLsizei width; 179 const GLsizei height; 180 const GLenum format; 181 const GLenum type; 182 const sw::Format internalFormat; 183 const int depth; 184 185 bool shared; // Used as an EGLImage 186 187 egl::Texture *parentTexture; 188 189 virtual ~Image(); 190 191 void loadD24S8ImageData(GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, int inputPitch, int inputHeight, const void *input, void *buffer); 192 void loadD32FS8ImageData(GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, int inputPitch, int inputHeight, const void *input, void *buffer); 193 }; 194 195 #ifdef __ANDROID__ 196 197 inline GLenum GLPixelFormatFromAndroid(int halFormat) 198 { 199 switch(halFormat) 200 { 201 case HAL_PIXEL_FORMAT_RGBA_8888: return GL_RGBA8; 202 #if ANDROID_PLATFORM_SDK_VERSION > 16 203 case HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED: return GL_RGB8; 204 #endif 205 case HAL_PIXEL_FORMAT_RGBX_8888: return GL_RGB8; 206 case HAL_PIXEL_FORMAT_RGB_888: return GL_NONE; // Unsupported 207 case HAL_PIXEL_FORMAT_BGRA_8888: return GL_BGRA8_EXT; 208 case HAL_PIXEL_FORMAT_RGB_565: return GL_RGB565; 209 case HAL_PIXEL_FORMAT_YV12: return SW_YV12_BT601; 210 #ifdef GRALLOC_MODULE_API_VERSION_0_2 211 case HAL_PIXEL_FORMAT_YCbCr_420_888: return SW_YV12_BT601; 212 #endif 213 default: return GL_NONE; 214 } 215 } 216 217 inline GLenum GLPixelTypeFromAndroid(int halFormat) 218 { 219 switch(halFormat) 220 { 221 case HAL_PIXEL_FORMAT_RGBA_8888: return GL_UNSIGNED_BYTE; 222 #if ANDROID_PLATFORM_SDK_VERSION > 16 223 case HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED: return GL_UNSIGNED_BYTE; 224 #endif 225 case HAL_PIXEL_FORMAT_RGBX_8888: return GL_UNSIGNED_BYTE; 226 case HAL_PIXEL_FORMAT_RGB_888: return GL_NONE; // Unsupported 227 case HAL_PIXEL_FORMAT_BGRA_8888: return GL_UNSIGNED_BYTE; 228 case HAL_PIXEL_FORMAT_RGB_565: return GL_UNSIGNED_SHORT_5_6_5; 229 case HAL_PIXEL_FORMAT_YV12: return GL_UNSIGNED_BYTE; 230 #ifdef GRALLOC_MODULE_API_VERSION_0_2 231 case HAL_PIXEL_FORMAT_YCbCr_420_888: return GL_UNSIGNED_BYTE; 232 #endif 233 default: return GL_NONE; 234 } 235 } 236 237 class AndroidNativeImage : public egl::Image 238 { 239 public: 240 explicit AndroidNativeImage(ANativeWindowBuffer *nativeBuffer) 241 : egl::Image(nativeBuffer->width, nativeBuffer->height, 242 GLPixelFormatFromAndroid(nativeBuffer->format), 243 GLPixelTypeFromAndroid(nativeBuffer->format), 244 nativeBuffer->stride), 245 nativeBuffer(nativeBuffer) 246 { 247 nativeBuffer->common.incRef(&nativeBuffer->common); 248 } 249 250 private: 251 ANativeWindowBuffer *nativeBuffer; 252 253 virtual ~AndroidNativeImage() 254 { 255 // Wait for any draw calls that use this image to finish 256 resource->lock(sw::DESTRUCT); 257 resource->unlock(); 258 259 nativeBuffer->common.decRef(&nativeBuffer->common); 260 } 261 262 virtual void *lockInternal(int x, int y, int z, sw::Lock lock, sw::Accessor client) 263 { 264 LOGLOCK("image=%p op=%s.swsurface lock=%d", this, __FUNCTION__, lock); 265 266 // Always do this for reference counting. 267 void *data = sw::Surface::lockInternal(x, y, z, lock, client); 268 269 if(nativeBuffer) 270 { 271 if(x != 0 || y != 0 || z != 0) 272 { 273 ALOGI("badness: %s called with unsupported parms: image=%p x=%d y=%d z=%d", __FUNCTION__, this, x, y, z); 274 } 275 276 LOGLOCK("image=%p op=%s.ani lock=%d", this, __FUNCTION__, lock); 277 278 // Lock the ANativeWindowBuffer and use its address. 279 data = lockNativeBuffer(GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN); 280 281 if(lock == sw::LOCK_UNLOCKED) 282 { 283 // We're never going to get a corresponding unlock, so unlock 284 // immediately. This keeps the gralloc reference counts sane. 285 unlockNativeBuffer(); 286 } 287 } 288 289 return data; 290 } 291 292 virtual void unlockInternal() 293 { 294 if(nativeBuffer) // Unlock the buffer from ANativeWindowBuffer 295 { 296 LOGLOCK("image=%p op=%s.ani", this, __FUNCTION__); 297 unlockNativeBuffer(); 298 } 299 300 LOGLOCK("image=%p op=%s.swsurface", this, __FUNCTION__); 301 sw::Surface::unlockInternal(); 302 } 303 304 virtual void *lock(unsigned int left, unsigned int top, sw::Lock lock) 305 { 306 LOGLOCK("image=%p op=%s lock=%d", this, __FUNCTION__, lock); 307 (void)sw::Surface::lockExternal(left, top, 0, lock, sw::PUBLIC); 308 309 return lockNativeBuffer(GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN); 310 } 311 312 virtual void unlock() 313 { 314 LOGLOCK("image=%p op=%s.ani", this, __FUNCTION__); 315 unlockNativeBuffer(); 316 317 LOGLOCK("image=%p op=%s.swsurface", this, __FUNCTION__); 318 sw::Surface::unlockExternal(); 319 } 320 321 void* lockNativeBuffer(int usage) 322 { 323 void *buffer = nullptr; 324 GrallocModule::getInstance()->lock(nativeBuffer->handle, usage, 0, 0, nativeBuffer->width, nativeBuffer->height, &buffer); 325 326 return buffer; 327 } 328 329 void unlockNativeBuffer() 330 { 331 GrallocModule::getInstance()->unlock(nativeBuffer->handle); 332 } 333 }; 334 335 #endif // __ANDROID__ 336 337 } 338 339 #endif // egl_Image_hpp 340