1 //
2 // Copyright (c) 2002-2014 The ANGLE Project Authors. All rights reserved.
3 // Use of this source code is governed by a BSD-style license that can be
4 // found in the LICENSE file.
5 //
6 
7 // Surface.cpp: Implements the egl::Surface class, representing a drawing surface
8 // such as the client area of a window, including any back buffers.
9 // Implements EGLSurface and related functionality. [EGL 1.4] section 2.2 page 3.
10 
11 #include "libANGLE/Surface.h"
12 
13 #include <EGL/eglext.h>
14 
15 #include <iostream>
16 
17 #include "libANGLE/Config.h"
18 #include "libANGLE/Context.h"
19 #include "libANGLE/Display.h"
20 #include "libANGLE/Framebuffer.h"
21 #include "libANGLE/Texture.h"
22 #include "libANGLE/Thread.h"
23 #include "libANGLE/formatutils.h"
24 #include "libANGLE/renderer/EGLImplFactory.h"
25 
26 namespace egl
27 {
28 
SurfaceState(const egl::Config * configIn,const AttributeMap & attributesIn)29 SurfaceState::SurfaceState(const egl::Config *configIn, const AttributeMap &attributesIn)
30     : defaultFramebuffer(nullptr), config(configIn), attributes(attributesIn)
31 {
32 }
33 
Surface(EGLint surfaceType,const egl::Config * config,const AttributeMap & attributes)34 Surface::Surface(EGLint surfaceType, const egl::Config *config, const AttributeMap &attributes)
35     : FramebufferAttachmentObject(),
36       mState(config, attributes),
37       mImplementation(nullptr),
38       mCurrentCount(0),
39       mDestroyed(false),
40       mType(surfaceType),
41       mPostSubBufferRequested(false),
42       mLargestPbuffer(false),
43       mGLColorspace(EGL_GL_COLORSPACE_LINEAR),
44       mVGAlphaFormat(EGL_VG_ALPHA_FORMAT_NONPRE),
45       mVGColorspace(EGL_VG_COLORSPACE_sRGB),
46       mMipmapTexture(false),
47       mMipmapLevel(0),
48       mHorizontalResolution(EGL_UNKNOWN),
49       mVerticalResolution(EGL_UNKNOWN),
50       mMultisampleResolve(EGL_MULTISAMPLE_RESOLVE_DEFAULT),
51       mFixedSize(false),
52       mFixedWidth(0),
53       mFixedHeight(0),
54       mTextureFormat(EGL_NO_TEXTURE),
55       mTextureTarget(EGL_NO_TEXTURE),
56       // FIXME: Determine actual pixel aspect ratio
57       mPixelAspectRatio(static_cast<EGLint>(1.0 * EGL_DISPLAY_SCALING)),
58       mRenderBuffer(EGL_BACK_BUFFER),
59       mSwapBehavior(EGL_NONE),
60       mOrientation(0),
61       mTexture(),
62       mBackFormat(config->renderTargetFormat),
63       mDSFormat(config->depthStencilFormat)
64 {
65     mPostSubBufferRequested = (attributes.get(EGL_POST_SUB_BUFFER_SUPPORTED_NV, EGL_FALSE) == EGL_TRUE);
66     mFlexibleSurfaceCompatibilityRequested =
67         (attributes.get(EGL_FLEXIBLE_SURFACE_COMPATIBILITY_SUPPORTED_ANGLE, EGL_FALSE) == EGL_TRUE);
68 
69     if (mType == EGL_PBUFFER_BIT)
70     {
71         mLargestPbuffer = (attributes.get(EGL_LARGEST_PBUFFER, EGL_FALSE) == EGL_TRUE);
72     }
73 
74     mGLColorspace =
75         static_cast<EGLenum>(attributes.get(EGL_GL_COLORSPACE, EGL_GL_COLORSPACE_LINEAR));
76     mVGAlphaFormat =
77         static_cast<EGLenum>(attributes.get(EGL_VG_ALPHA_FORMAT, EGL_VG_ALPHA_FORMAT_NONPRE));
78     mVGColorspace = static_cast<EGLenum>(attributes.get(EGL_VG_COLORSPACE, EGL_VG_COLORSPACE_sRGB));
79     mMipmapTexture = (attributes.get(EGL_MIPMAP_TEXTURE, EGL_FALSE) == EGL_TRUE);
80 
81     mDirectComposition = (attributes.get(EGL_DIRECT_COMPOSITION_ANGLE, EGL_FALSE) == EGL_TRUE);
82 
83     mRobustResourceInitialization =
84         (attributes.get(EGL_ROBUST_RESOURCE_INITIALIZATION_ANGLE, EGL_FALSE) == EGL_TRUE);
85 
86     mFixedSize = (attributes.get(EGL_FIXED_SIZE_ANGLE, EGL_FALSE) == EGL_TRUE);
87     if (mFixedSize)
88     {
89         mFixedWidth  = static_cast<size_t>(attributes.get(EGL_WIDTH, 0));
90         mFixedHeight = static_cast<size_t>(attributes.get(EGL_HEIGHT, 0));
91     }
92 
93     if (mType != EGL_WINDOW_BIT)
94     {
95         mTextureFormat = static_cast<EGLenum>(attributes.get(EGL_TEXTURE_FORMAT, EGL_NO_TEXTURE));
96         mTextureTarget = static_cast<EGLenum>(attributes.get(EGL_TEXTURE_TARGET, EGL_NO_TEXTURE));
97     }
98 
99     mOrientation = static_cast<EGLint>(attributes.get(EGL_SURFACE_ORIENTATION_ANGLE, 0));
100 }
101 
~Surface()102 Surface::~Surface()
103 {
104 }
105 
getAttachmentImpl() const106 rx::FramebufferAttachmentObjectImpl *Surface::getAttachmentImpl() const
107 {
108     return mImplementation;
109 }
110 
destroyImpl(const Display * display)111 Error Surface::destroyImpl(const Display *display)
112 {
113     if (mState.defaultFramebuffer)
114     {
115         mState.defaultFramebuffer->destroyDefault(display);
116     }
117     if (mImplementation)
118     {
119         mImplementation->destroy(display);
120     }
121 
122     if (mTexture.get())
123     {
124         if (mImplementation)
125         {
126             ANGLE_TRY(mImplementation->releaseTexImage(EGL_BACK_BUFFER));
127         }
128         auto glErr = mTexture->releaseTexImageFromSurface(display->getProxyContext());
129         if (glErr.isError())
130         {
131             return Error(EGL_BAD_SURFACE);
132         }
133         mTexture.set(nullptr, nullptr);
134     }
135 
136     if (mState.defaultFramebuffer)
137     {
138         mState.defaultFramebuffer->onDestroy(display->getProxyContext());
139     }
140     SafeDelete(mState.defaultFramebuffer);
141     SafeDelete(mImplementation);
142 
143     delete this;
144     return NoError();
145 }
146 
initialize(const Display * display)147 Error Surface::initialize(const Display *display)
148 {
149     ANGLE_TRY(mImplementation->initialize(display));
150 
151     // Initialized here since impl is nullptr in the constructor.
152     // Must happen after implementation initialize for Android.
153     mSwapBehavior = mImplementation->getSwapBehavior();
154 
155     // Must happen after implementation initialize for OSX.
156     mState.defaultFramebuffer = createDefaultFramebuffer(display);
157     ASSERT(mState.defaultFramebuffer != nullptr);
158 
159     return NoError();
160 }
161 
setIsCurrent(const gl::Context * context,bool isCurrent)162 Error Surface::setIsCurrent(const gl::Context *context, bool isCurrent)
163 {
164     if (isCurrent)
165     {
166         mCurrentCount++;
167         return NoError();
168     }
169 
170     ASSERT(mCurrentCount > 0);
171     mCurrentCount--;
172     if (mCurrentCount == 0 && mDestroyed)
173     {
174         ASSERT(context);
175         return destroyImpl(context->getCurrentDisplay());
176     }
177     return NoError();
178 }
179 
onDestroy(const Display * display)180 Error Surface::onDestroy(const Display *display)
181 {
182     mDestroyed = true;
183     if (mCurrentCount == 0)
184     {
185         return destroyImpl(display);
186     }
187     return NoError();
188 }
189 
getType() const190 EGLint Surface::getType() const
191 {
192     return mType;
193 }
194 
swap(const gl::Context * context)195 Error Surface::swap(const gl::Context *context)
196 {
197     return mImplementation->swap(context);
198 }
199 
swapWithDamage(const gl::Context * context,EGLint * rects,EGLint n_rects)200 Error Surface::swapWithDamage(const gl::Context *context, EGLint *rects, EGLint n_rects)
201 {
202     return mImplementation->swapWithDamage(context, rects, n_rects);
203 }
204 
postSubBuffer(const gl::Context * context,EGLint x,EGLint y,EGLint width,EGLint height)205 Error Surface::postSubBuffer(const gl::Context *context,
206                              EGLint x,
207                              EGLint y,
208                              EGLint width,
209                              EGLint height)
210 {
211     return mImplementation->postSubBuffer(context, x, y, width, height);
212 }
213 
querySurfacePointerANGLE(EGLint attribute,void ** value)214 Error Surface::querySurfacePointerANGLE(EGLint attribute, void **value)
215 {
216     return mImplementation->querySurfacePointerANGLE(attribute, value);
217 }
218 
isPostSubBufferSupported() const219 EGLint Surface::isPostSubBufferSupported() const
220 {
221     return mPostSubBufferRequested && mImplementation->isPostSubBufferSupported();
222 }
223 
setSwapInterval(EGLint interval)224 void Surface::setSwapInterval(EGLint interval)
225 {
226     mImplementation->setSwapInterval(interval);
227 }
228 
setMipmapLevel(EGLint level)229 void Surface::setMipmapLevel(EGLint level)
230 {
231     // Level is set but ignored
232     UNIMPLEMENTED();
233     mMipmapLevel = level;
234 }
235 
setMultisampleResolve(EGLenum resolve)236 void Surface::setMultisampleResolve(EGLenum resolve)
237 {
238     // Behaviour is set but ignored
239     UNIMPLEMENTED();
240     mMultisampleResolve = resolve;
241 }
242 
setSwapBehavior(EGLenum behavior)243 void Surface::setSwapBehavior(EGLenum behavior)
244 {
245     // Behaviour is set but ignored
246     UNIMPLEMENTED();
247     mSwapBehavior = behavior;
248 }
249 
getConfig() const250 const Config *Surface::getConfig() const
251 {
252     return mState.config;
253 }
254 
getPixelAspectRatio() const255 EGLint Surface::getPixelAspectRatio() const
256 {
257     return mPixelAspectRatio;
258 }
259 
getRenderBuffer() const260 EGLenum Surface::getRenderBuffer() const
261 {
262     return mRenderBuffer;
263 }
264 
getSwapBehavior() const265 EGLenum Surface::getSwapBehavior() const
266 {
267     return mSwapBehavior;
268 }
269 
getTextureFormat() const270 EGLenum Surface::getTextureFormat() const
271 {
272     return mTextureFormat;
273 }
274 
getTextureTarget() const275 EGLenum Surface::getTextureTarget() const
276 {
277     return mTextureTarget;
278 }
279 
getLargestPbuffer() const280 bool Surface::getLargestPbuffer() const
281 {
282     return mLargestPbuffer;
283 }
284 
getGLColorspace() const285 EGLenum Surface::getGLColorspace() const
286 {
287     return mGLColorspace;
288 }
289 
getVGAlphaFormat() const290 EGLenum Surface::getVGAlphaFormat() const
291 {
292     return mVGAlphaFormat;
293 }
294 
getVGColorspace() const295 EGLenum Surface::getVGColorspace() const
296 {
297     return mVGColorspace;
298 }
299 
getMipmapTexture() const300 bool Surface::getMipmapTexture() const
301 {
302     return mMipmapTexture;
303 }
304 
getMipmapLevel() const305 EGLint Surface::getMipmapLevel() const
306 {
307     return mMipmapLevel;
308 }
309 
getHorizontalResolution() const310 EGLint Surface::getHorizontalResolution() const
311 {
312     return mHorizontalResolution;
313 }
314 
getVerticalResolution() const315 EGLint Surface::getVerticalResolution() const
316 {
317     return mVerticalResolution;
318 }
319 
getMultisampleResolve() const320 EGLenum Surface::getMultisampleResolve() const
321 {
322     return mMultisampleResolve;
323 }
324 
isFixedSize() const325 EGLint Surface::isFixedSize() const
326 {
327     return mFixedSize;
328 }
329 
getWidth() const330 EGLint Surface::getWidth() const
331 {
332     return mFixedSize ? static_cast<EGLint>(mFixedWidth) : mImplementation->getWidth();
333 }
334 
getHeight() const335 EGLint Surface::getHeight() const
336 {
337     return mFixedSize ? static_cast<EGLint>(mFixedHeight) : mImplementation->getHeight();
338 }
339 
bindTexImage(const gl::Context * context,gl::Texture * texture,EGLint buffer)340 Error Surface::bindTexImage(const gl::Context *context, gl::Texture *texture, EGLint buffer)
341 {
342     ASSERT(!mTexture.get());
343     ANGLE_TRY(mImplementation->bindTexImage(texture, buffer));
344 
345     auto glErr = texture->bindTexImageFromSurface(context, this);
346     if (glErr.isError())
347     {
348         return Error(EGL_BAD_SURFACE);
349     }
350     mTexture.set(context, texture);
351 
352     return NoError();
353 }
354 
releaseTexImage(const gl::Context * context,EGLint buffer)355 Error Surface::releaseTexImage(const gl::Context *context, EGLint buffer)
356 {
357     ASSERT(context);
358 
359     ANGLE_TRY(mImplementation->releaseTexImage(buffer));
360 
361     ASSERT(mTexture.get());
362     auto glErr = mTexture->releaseTexImageFromSurface(context);
363     if (glErr.isError())
364     {
365         return Error(EGL_BAD_SURFACE);
366     }
367     mTexture.set(context, nullptr);
368 
369     return NoError();
370 }
371 
getSyncValues(EGLuint64KHR * ust,EGLuint64KHR * msc,EGLuint64KHR * sbc)372 Error Surface::getSyncValues(EGLuint64KHR *ust, EGLuint64KHR *msc, EGLuint64KHR *sbc)
373 {
374     return mImplementation->getSyncValues(ust, msc, sbc);
375 }
376 
releaseTexImageFromTexture(const gl::Context * context)377 void Surface::releaseTexImageFromTexture(const gl::Context *context)
378 {
379     ASSERT(mTexture.get());
380     mTexture.set(context, nullptr);
381 }
382 
getAttachmentSize(const gl::ImageIndex &) const383 gl::Extents Surface::getAttachmentSize(const gl::ImageIndex & /*target*/) const
384 {
385     return gl::Extents(getWidth(), getHeight(), 1);
386 }
387 
getAttachmentFormat(GLenum binding,const gl::ImageIndex & target) const388 const gl::Format &Surface::getAttachmentFormat(GLenum binding, const gl::ImageIndex &target) const
389 {
390     return (binding == GL_BACK ? mBackFormat : mDSFormat);
391 }
392 
getAttachmentSamples(const gl::ImageIndex & target) const393 GLsizei Surface::getAttachmentSamples(const gl::ImageIndex &target) const
394 {
395     return getConfig()->samples;
396 }
397 
getId() const398 GLuint Surface::getId() const
399 {
400     UNREACHABLE();
401     return 0;
402 }
403 
createDefaultFramebuffer(const Display * display)404 gl::Framebuffer *Surface::createDefaultFramebuffer(const Display *display)
405 {
406     return new gl::Framebuffer(display, this);
407 }
408 
initState(const gl::ImageIndex &) const409 gl::InitState Surface::initState(const gl::ImageIndex & /*imageIndex*/) const
410 {
411     // TODO(jmadill): Lazy surface init.
412     return gl::InitState::Initialized;
413 }
414 
setInitState(const gl::ImageIndex &,gl::InitState)415 void Surface::setInitState(const gl::ImageIndex & /*imageIndex*/, gl::InitState /*initState*/)
416 {
417     // No-op.
418 }
419 
WindowSurface(rx::EGLImplFactory * implFactory,const egl::Config * config,EGLNativeWindowType window,const AttributeMap & attribs)420 WindowSurface::WindowSurface(rx::EGLImplFactory *implFactory,
421                              const egl::Config *config,
422                              EGLNativeWindowType window,
423                              const AttributeMap &attribs)
424     : Surface(EGL_WINDOW_BIT, config, attribs)
425 {
426     mImplementation = implFactory->createWindowSurface(mState, window, attribs);
427 }
428 
~WindowSurface()429 WindowSurface::~WindowSurface()
430 {
431 }
432 
PbufferSurface(rx::EGLImplFactory * implFactory,const Config * config,const AttributeMap & attribs)433 PbufferSurface::PbufferSurface(rx::EGLImplFactory *implFactory,
434                                const Config *config,
435                                const AttributeMap &attribs)
436     : Surface(EGL_PBUFFER_BIT, config, attribs)
437 {
438     mImplementation = implFactory->createPbufferSurface(mState, attribs);
439 }
440 
PbufferSurface(rx::EGLImplFactory * implFactory,const Config * config,EGLenum buftype,EGLClientBuffer clientBuffer,const AttributeMap & attribs)441 PbufferSurface::PbufferSurface(rx::EGLImplFactory *implFactory,
442                                const Config *config,
443                                EGLenum buftype,
444                                EGLClientBuffer clientBuffer,
445                                const AttributeMap &attribs)
446     : Surface(EGL_PBUFFER_BIT, config, attribs)
447 {
448     mImplementation =
449         implFactory->createPbufferFromClientBuffer(mState, buftype, clientBuffer, attribs);
450 }
451 
~PbufferSurface()452 PbufferSurface::~PbufferSurface()
453 {
454 }
455 
PixmapSurface(rx::EGLImplFactory * implFactory,const Config * config,NativePixmapType nativePixmap,const AttributeMap & attribs)456 PixmapSurface::PixmapSurface(rx::EGLImplFactory *implFactory,
457                              const Config *config,
458                              NativePixmapType nativePixmap,
459                              const AttributeMap &attribs)
460     : Surface(EGL_PIXMAP_BIT, config, attribs)
461 {
462     mImplementation = implFactory->createPixmapSurface(mState, nativePixmap, attribs);
463 }
464 
~PixmapSurface()465 PixmapSurface::~PixmapSurface()
466 {
467 }
468 
469 // SurfaceDeleter implementation.
470 
SurfaceDeleter(const Display * display)471 SurfaceDeleter::SurfaceDeleter(const Display *display) : mDisplay(display)
472 {
473 }
474 
~SurfaceDeleter()475 SurfaceDeleter::~SurfaceDeleter()
476 {
477 }
478 
operator ()(Surface * surface)479 void SurfaceDeleter::operator()(Surface *surface)
480 {
481     ANGLE_SWALLOW_ERR(surface->onDestroy(mDisplay));
482 }
483 
484 }  // namespace egl
485