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