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