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