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