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/window.h>
26 #include "../../Common/GrallocAndroid.hpp"
27 #endif
28 
29 #if defined(__ANDROID__) && !defined(ANDROID_HOST_BUILD) && !defined(ANDROID_NDK_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 GLsizei ComputePixelSize(GLenum format, GLenum type);
62 size_t ComputePackingOffset(GLenum format, GLenum type, GLsizei width, GLsizei height, const PixelStorageModes &storageModes);
63 
64 }
65 
66 namespace egl
67 {
68 
69 class ClientBuffer
70 {
71 public:
ClientBuffer(int width,int height,sw::Format format,void * buffer,size_t plane)72 	ClientBuffer(int width, int height, sw::Format format, void* buffer, size_t plane)
73 		: width(width), height(height), format(format), buffer(buffer), plane(plane)
74 	{}
75 
76 	int getWidth() const;
77 	int getHeight() const;
78 	sw::Format getFormat() const;
79 	size_t getPlane() const;
80 	int pitchP() const;
81 	void retain();
82 	void release();
83 	void* lock(int x, int y, int z);
84 	void unlock();
85 	bool requiresSync() const;
86 
87 private:
88 	int width;
89 	int height;
90 	sw::Format format;
91 	void* buffer;
92 	size_t plane;
93 };
94 
95 class [[clang::lto_visibility_public]] Image : public sw::Surface, public gl::Object
96 {
97 protected:
98 	// 2D texture image
Image(Texture * parentTexture,GLsizei width,GLsizei height,GLint internalformat)99 	Image(Texture *parentTexture, GLsizei width, GLsizei height, GLint internalformat)
100 		: sw::Surface(parentTexture->getResource(), width, height, 1, 0, 1, gl::SelectInternalFormat(internalformat), true, true),
101 		  width(width), height(height), depth(1), internalformat(internalformat), parentTexture(parentTexture)
102 	{
103 		shared = false;
104 		Object::addRef();
105 		parentTexture->addRef();
106 	}
107 
108 	// 3D/Cube texture image
Image(Texture * parentTexture,GLsizei width,GLsizei height,GLsizei depth,int border,GLint internalformat)109 	Image(Texture *parentTexture, GLsizei width, GLsizei height, GLsizei depth, int border, GLint internalformat)
110 		: sw::Surface(parentTexture->getResource(), width, height, depth, border, 1, gl::SelectInternalFormat(internalformat), true, true),
111 		  width(width), height(height), depth(depth), internalformat(internalformat), parentTexture(parentTexture)
112 	{
113 		shared = false;
114 		Object::addRef();
115 		parentTexture->addRef();
116 	}
117 
118 	// Native EGL image
Image(GLsizei width,GLsizei height,GLint internalformat,int pitchP)119 	Image(GLsizei width, GLsizei height, GLint internalformat, int pitchP)
120 		: sw::Surface(nullptr, width, height, 1, 0, 1, gl::SelectInternalFormat(internalformat), true, true, pitchP),
121 		  width(width), height(height), depth(1), internalformat(internalformat), parentTexture(nullptr)
122 	{
123 		shared = true;
124 		Object::addRef();
125 	}
126 
127 	// Render target
Image(GLsizei width,GLsizei height,GLint internalformat,int multiSampleDepth,bool lockable)128 	Image(GLsizei width, GLsizei height, GLint internalformat, int multiSampleDepth, bool lockable)
129 		: sw::Surface(nullptr, width, height, 1, 0, multiSampleDepth, gl::SelectInternalFormat(internalformat), lockable, true),
130 		  width(width), height(height), depth(1), internalformat(internalformat), parentTexture(nullptr)
131 	{
132 		shared = false;
133 		Object::addRef();
134 	}
135 
136 public:
137 	// 2D texture image
138 	static Image *create(Texture *parentTexture, GLsizei width, GLsizei height, GLint internalformat);
139 
140 	// 3D/Cube texture image
141 	static Image *create(Texture *parentTexture, GLsizei width, GLsizei height, GLsizei depth, int border, GLint internalformat);
142 
143 	// Native EGL image
144 	static Image *create(GLsizei width, GLsizei height, GLint internalformat, int pitchP);
145 
146 	// Render target
147 	static Image *create(GLsizei width, GLsizei height, GLint internalformat, int multiSampleDepth, bool lockable);
148 
149 	// Back buffer from client buffer
150 	static Image *create(const egl::ClientBuffer& clientBuffer);
151 
152 	static size_t size(int width, int height, int depth, int border, int samples, GLint internalformat);
153 
getWidth() const154 	GLsizei getWidth() const
155 	{
156 		return width;
157 	}
158 
getHeight() const159 	GLsizei getHeight() const
160 	{
161 		return height;
162 	}
163 
getDepth() const164 	int getDepth() const
165 	{
166 		// FIXME: add member if the depth dimension (for 3D textures or 2D testure arrays)
167 		// and multi sample depth are ever simultaneously required.
168 		return depth;
169 	}
170 
getFormat() const171 	GLint getFormat() const
172 	{
173 		return internalformat;
174 	}
175 
isShared() const176 	bool isShared() const
177 	{
178 		return shared;
179 	}
180 
markShared()181 	void markShared()
182 	{
183 		shared = true;
184 	}
185 
lock(int x,int y,int z,sw::Lock lock)186 	virtual void *lock(int x, int y, int z, sw::Lock lock)
187 	{
188 		return lockExternal(x, y, z, lock, sw::PUBLIC);
189 	}
190 
getPitch() const191 	unsigned int getPitch() const
192 	{
193 		return getExternalPitchB();
194 	}
195 
getSlice() const196 	unsigned int getSlice() const
197 	{
198 		return getExternalSliceB();
199 	}
200 
unlock()201 	virtual void unlock()
202 	{
203 		unlockExternal();
204 	}
205 
206 	void *lockInternal(int x, int y, int z, sw::Lock lock, sw::Accessor client) override = 0;
207 	void unlockInternal() override = 0;
208 
209 	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);
210 	void loadCompressedData(GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLsizei imageSize, const void *pixels);
211 
212 	void release() override = 0;
213 	void unbind(const Texture *parent);   // Break parent ownership and release
214 	bool isChildOf(const Texture *parent) const;
215 
destroyShared()216 	virtual void destroyShared()   // Release a shared image
217 	{
218 		assert(shared);
219 		shared = false;
220 		release();
221 	}
222 
223 protected:
224 	const GLsizei width;
225 	const GLsizei height;
226 	const int depth;
227 	const GLint internalformat;
228 
229 	bool shared;   // Used as an EGLImage
230 
231 	egl::Texture *parentTexture;
232 
233 	~Image() override = 0;
234 
235 	void loadImageData(GLsizei width, GLsizei height, GLsizei depth, int inputPitch, int inputHeight, GLenum format, GLenum type, const void *input, void *buffer);
236 	void loadStencilData(GLsizei width, GLsizei height, GLsizei depth, int inputPitch, int inputHeight, GLenum format, GLenum type, const void *input, void *buffer);
237 };
238 
239 #if defined(__ANDROID__) && !defined(ANDROID_NDK_BUILD)
240 
GLPixelFormatFromAndroid(int halFormat)241 inline GLenum GLPixelFormatFromAndroid(int halFormat)
242 {
243 	switch(halFormat)
244 	{
245 	case HAL_PIXEL_FORMAT_RGBA_8888: return GL_RGBA8;
246 #if ANDROID_PLATFORM_SDK_VERSION > 16
247 	case HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED: return GL_RGB8;
248 #endif
249 	case HAL_PIXEL_FORMAT_RGBX_8888: return GL_RGB8;
250 	case HAL_PIXEL_FORMAT_BGRA_8888: return GL_BGRA8_EXT;
251 	case HAL_PIXEL_FORMAT_RGB_565:   return GL_RGB565;
252 	case HAL_PIXEL_FORMAT_YV12:      return SW_YV12_BT601;
253 #ifdef GRALLOC_MODULE_API_VERSION_0_2
254 	case HAL_PIXEL_FORMAT_YCbCr_420_888: return SW_YV12_BT601;
255 #endif
256 #if ANDROID_PLATFORM_SDK_VERSION >= 26
257 	case HAL_PIXEL_FORMAT_RGBA_FP16: return GL_RGBA16F;
258 #endif
259 	case HAL_PIXEL_FORMAT_RGB_888:   // Unsupported.
260 	default:
261 		ERR("Unsupported EGL image format %d", halFormat); ASSERT(false);
262 		return GL_NONE;
263 	}
264 }
265 
266 class AndroidNativeImage : public egl::Image
267 {
268 public:
AndroidNativeImage(ANativeWindowBuffer * nativeBuffer)269 	explicit AndroidNativeImage(ANativeWindowBuffer *nativeBuffer)
270 		: egl::Image(nativeBuffer->width, nativeBuffer->height,
271 		             GLPixelFormatFromAndroid(nativeBuffer->format),
272 		             nativeBuffer->stride),
273 		  nativeBuffer(nativeBuffer)
274 	{
275 		nativeBuffer->common.incRef(&nativeBuffer->common);
276 	}
277 
278 private:
279 	ANativeWindowBuffer *nativeBuffer;
280 
~AndroidNativeImage()281 	~AndroidNativeImage() override
282 	{
283 		sync();   // Wait for any threads that use this image to finish.
284 
285 		nativeBuffer->common.decRef(&nativeBuffer->common);
286 	}
287 
lockInternal(int x,int y,int z,sw::Lock lock,sw::Accessor client)288 	void *lockInternal(int x, int y, int z, sw::Lock lock, sw::Accessor client) override
289 	{
290 		LOGLOCK("image=%p op=%s.swsurface lock=%d", this, __FUNCTION__, lock);
291 
292 		// Always do this for reference counting.
293 		void *data = sw::Surface::lockInternal(x, y, z, lock, client);
294 
295 		if(nativeBuffer)
296 		{
297 			if(x != 0 || y != 0 || z != 0)
298 			{
299 				TRACE("badness: %s called with unsupported parms: image=%p x=%d y=%d z=%d", __FUNCTION__, this, x, y, z);
300 			}
301 
302 			LOGLOCK("image=%p op=%s.ani lock=%d", this, __FUNCTION__, lock);
303 
304 			// Lock the ANativeWindowBuffer and use its address.
305 			data = lockNativeBuffer(GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN);
306 
307 			if(lock == sw::LOCK_UNLOCKED)
308 			{
309 				// We're never going to get a corresponding unlock, so unlock
310 				// immediately. This keeps the gralloc reference counts sane.
311 				unlockNativeBuffer();
312 			}
313 		}
314 
315 		return data;
316 	}
317 
unlockInternal()318 	void unlockInternal() override
319 	{
320 		if(nativeBuffer)   // Unlock the buffer from ANativeWindowBuffer
321 		{
322 			LOGLOCK("image=%p op=%s.ani", this, __FUNCTION__);
323 			unlockNativeBuffer();
324 		}
325 
326 		LOGLOCK("image=%p op=%s.swsurface", this, __FUNCTION__);
327 		sw::Surface::unlockInternal();
328 	}
329 
lock(int x,int y,int z,sw::Lock lock)330 	void *lock(int x, int y, int z, sw::Lock lock) override
331 	{
332 		LOGLOCK("image=%p op=%s lock=%d", this, __FUNCTION__, lock);
333 		(void)sw::Surface::lockExternal(x, y, z, lock, sw::PUBLIC);
334 
335 		return lockNativeBuffer(GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN);
336 	}
337 
unlock()338 	void unlock() override
339 	{
340 		LOGLOCK("image=%p op=%s.ani", this, __FUNCTION__);
341 		unlockNativeBuffer();
342 
343 		LOGLOCK("image=%p op=%s.swsurface", this, __FUNCTION__);
344 		sw::Surface::unlockExternal();
345 	}
346 
lockNativeBuffer(int usage)347 	void *lockNativeBuffer(int usage)
348 	{
349 		void *buffer = nullptr;
350 		GrallocModule::getInstance()->lock(nativeBuffer->handle, usage, 0, 0, nativeBuffer->width, nativeBuffer->height, &buffer);
351 
352 		return buffer;
353 	}
354 
unlockNativeBuffer()355 	void unlockNativeBuffer()
356 	{
357 		GrallocModule::getInstance()->unlock(nativeBuffer->handle);
358 	}
359 
release()360 	void release() override
361 	{
362 		Image::release();
363 	}
364 };
365 
366 #endif  // __ANDROID__ && !defined(ANDROID_NDK_BUILD)
367 
368 }
369 
370 #endif   // egl_Image_hpp
371