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