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