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 #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