• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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:
ClientBuffer(int width,int height,sw::Format format,void * buffer,size_t plane)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
Image(Texture * parentTexture,GLsizei width,GLsizei height,GLint internalformat)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
Image(Texture * parentTexture,GLsizei width,GLsizei height,GLsizei depth,int border,GLint internalformat)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
Image(GLsizei width,GLsizei height,GLint internalformat,int pitchP)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
Image(GLsizei width,GLsizei height,GLint internalformat,int multiSampleDepth,bool lockable)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 
getWidth() const148 	GLsizei getWidth() const
149 	{
150 		return width;
151 	}
152 
getHeight() const153 	GLsizei getHeight() const
154 	{
155 		return height;
156 	}
157 
getDepth() const158 	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 
getFormat() const165 	GLint getFormat() const
166 	{
167 		return internalformat;
168 	}
169 
isShared() const170 	bool isShared() const
171 	{
172 		return shared;
173 	}
174 
markShared()175 	void markShared()
176 	{
177 		shared = true;
178 	}
179 
lock(int x,int y,int z,sw::Lock lock)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 
getPitch() const185 	unsigned int getPitch() const
186 	{
187 		return getExternalPitchB();
188 	}
189 
getSlice() const190 	unsigned int getSlice() const
191 	{
192 		return getExternalSliceB();
193 	}
194 
unlock()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 
destroyShared()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 
GLPixelFormatFromAndroid(int halFormat)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:
AndroidNativeImage(ANativeWindowBuffer * nativeBuffer)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 
~AndroidNativeImage()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 
lockInternal(int x,int y,int z,sw::Lock lock,sw::Accessor client)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 
unlockInternal()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 
lock(int x,int y,int z,sw::Lock lock)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 
unlock()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 
lockNativeBuffer(int usage)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 
unlockNativeBuffer()349 	void unlockNativeBuffer()
350 	{
351 		GrallocModule::getInstance()->unlock(nativeBuffer->handle);
352 	}
353 
release()354 	void release() override
355 	{
356 		Image::release();
357 	}
358 };
359 
360 #endif  // __ANDROID__
361 
362 }
363 
364 #endif   // egl_Image_hpp
365