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