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