Home | History | Annotate | Download | only in common
      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