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