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