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
Image(Texture * parentTexture,GLsizei width,GLsizei height,GLenum format,GLenum type)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
Image(Texture * parentTexture,GLsizei width,GLsizei height,GLsizei depth,GLenum format,GLenum type)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
Image(GLsizei width,GLsizei height,GLenum format,GLenum type,int pitchP)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
Image(GLsizei width,GLsizei height,sw::Format internalFormat,int multiSampleDepth,bool lockable)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 
getWidth() const94 	GLsizei getWidth() const
95 	{
96 		return width;
97 	}
98 
getHeight() const99 	GLsizei getHeight() const
100 	{
101 		return height;
102 	}
103 
getDepth() const104 	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 
getFormat() const111 	GLenum getFormat() const
112 	{
113 		return format;
114 	}
115 
getType() const116 	GLenum getType() const
117 	{
118 		return type;
119 	}
120 
getInternalFormat() const121 	sw::Format getInternalFormat() const
122 	{
123 		return internalFormat;
124 	}
125 
isShared() const126 	bool isShared() const
127 	{
128 		return shared;
129 	}
130 
markShared()131 	void markShared()
132 	{
133 		shared = true;
134 	}
135 
lock(unsigned int left,unsigned int top,sw::Lock lock)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 
getPitch() const141 	unsigned int getPitch() const
142 	{
143 		return getExternalPitchB();
144 	}
145 
unlock()146 	virtual void unlock()
147 	{
148 		unlockExternal();
149 	}
150 
151 	struct UnpackInfo
152 	{
UnpackInfoegl::Image::UnpackInfo153 		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 
destroyShared()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 
GLPixelFormatFromAndroid(int halFormat)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 
GLPixelTypeFromAndroid(int halFormat)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:
AndroidNativeImage(ANativeWindowBuffer * nativeBuffer)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 
~AndroidNativeImage()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 
lockInternal(int x,int y,int z,sw::Lock lock,sw::Accessor client)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 
unlockInternal()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 
lock(unsigned int left,unsigned int top,sw::Lock lock)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 
unlock()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 
lockNativeBuffer(int usage)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 
unlockNativeBuffer()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