• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //
2 // Copyright 2002 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 "libANGLE/Config.h"
16 #include "libANGLE/Context.h"
17 #include "libANGLE/Display.h"
18 #include "libANGLE/Framebuffer.h"
19 #include "libANGLE/Texture.h"
20 #include "libANGLE/formatutils.h"
21 #include "libANGLE/renderer/EGLImplFactory.h"
22 #include "libANGLE/trace.h"
23 
24 namespace egl
25 {
26 namespace
27 {
28 angle::SubjectIndex kSurfaceImplSubjectIndex = 0;
29 }  // namespace
30 
SurfaceState(SurfaceID idIn,const egl::Config * configIn,const AttributeMap & attributesIn)31 SurfaceState::SurfaceState(SurfaceID idIn,
32                            const egl::Config *configIn,
33                            const AttributeMap &attributesIn)
34     : id(idIn),
35       label(nullptr),
36       config((configIn != nullptr) ? new egl::Config(*configIn) : nullptr),
37       attributes(attributesIn),
38       timestampsEnabled(false),
39       autoRefreshEnabled(false),
40       directComposition(false),
41       swapBehavior(EGL_NONE),
42       swapInterval(0)
43 {
44     directComposition = attributes.get(EGL_DIRECT_COMPOSITION_ANGLE, EGL_FALSE) == EGL_TRUE;
45     swapInterval      = attributes.getAsInt(EGL_SWAP_INTERVAL_ANGLE, 1);
46 }
47 
~SurfaceState()48 SurfaceState::~SurfaceState()
49 {
50     delete config;
51 }
52 
isRobustResourceInitEnabled() const53 bool SurfaceState::isRobustResourceInitEnabled() const
54 {
55     return attributes.get(EGL_ROBUST_RESOURCE_INITIALIZATION_ANGLE, EGL_FALSE) == EGL_TRUE;
56 }
57 
hasProtectedContent() const58 bool SurfaceState::hasProtectedContent() const
59 {
60     return attributes.get(EGL_PROTECTED_CONTENT_EXT, EGL_FALSE) == EGL_TRUE;
61 }
62 
Surface(EGLint surfaceType,SurfaceID id,const egl::Config * config,const AttributeMap & attributes,bool forceRobustResourceInit,EGLenum buftype)63 Surface::Surface(EGLint surfaceType,
64                  SurfaceID id,
65                  const egl::Config *config,
66                  const AttributeMap &attributes,
67                  bool forceRobustResourceInit,
68                  EGLenum buftype)
69     : FramebufferAttachmentObject(),
70       mState(id, config, attributes),
71       mImplementation(nullptr),
72       mRefCount(0),
73       mDestroyed(false),
74       mType(surfaceType),
75       mBuftype(buftype),
76       mPostSubBufferRequested(false),
77       mLargestPbuffer(false),
78       mGLColorspace(EGL_GL_COLORSPACE_LINEAR),
79       mVGAlphaFormat(EGL_VG_ALPHA_FORMAT_NONPRE),
80       mVGColorspace(EGL_VG_COLORSPACE_sRGB),
81       mMipmapTexture(false),
82       mMipmapLevel(0),
83       mHorizontalResolution(EGL_UNKNOWN),
84       mVerticalResolution(EGL_UNKNOWN),
85       mMultisampleResolve(EGL_MULTISAMPLE_RESOLVE_DEFAULT),
86       mFixedSize(false),
87       mFixedWidth(0),
88       mFixedHeight(0),
89       mTextureFormat(TextureFormat::NoTexture),
90       mTextureTarget(EGL_NO_TEXTURE),
91       // FIXME: Determine actual pixel aspect ratio
92       mPixelAspectRatio(static_cast<EGLint>(1.0 * EGL_DISPLAY_SCALING)),
93       mRenderBuffer(EGL_BACK_BUFFER),
94       mRequestedRenderBuffer(EGL_BACK_BUFFER),
95       mRequestedSwapInterval(mState.swapInterval),
96       mOrientation(0),
97       mTexture(nullptr),
98       mColorFormat(config->renderTargetFormat),
99       mDSFormat(config->depthStencilFormat),
100       mIsCurrentOnAnyContext(false),
101       mLockBufferPtr(nullptr),
102       mLockBufferPitch(0),
103       mBufferAgeQueriedSinceLastSwap(false),
104       mIsDamageRegionSet(false),
105       mColorInitState(gl::InitState::Initialized),
106       mDepthStencilInitState(gl::InitState::Initialized),
107       mImplObserverBinding(this, kSurfaceImplSubjectIndex)
108 {
109     mPostSubBufferRequested =
110         (attributes.get(EGL_POST_SUB_BUFFER_SUPPORTED_NV, EGL_FALSE) == EGL_TRUE);
111 
112     if (mType == EGL_PBUFFER_BIT)
113     {
114         mLargestPbuffer = (attributes.get(EGL_LARGEST_PBUFFER, EGL_FALSE) == EGL_TRUE);
115     }
116 
117     if (mType == EGL_PIXMAP_BIT)
118     {
119         mRenderBuffer          = EGL_SINGLE_BUFFER;
120         mRequestedRenderBuffer = EGL_SINGLE_BUFFER;
121     }
122 
123     if (mType == EGL_WINDOW_BIT)
124     {
125         mRenderBuffer          = mState.attributes.getAsInt(EGL_RENDER_BUFFER, EGL_BACK_BUFFER);
126         mRequestedRenderBuffer = mRenderBuffer;
127     }
128 
129     mGLColorspace =
130         static_cast<EGLenum>(attributes.get(EGL_GL_COLORSPACE, EGL_GL_COLORSPACE_LINEAR));
131     mVGAlphaFormat =
132         static_cast<EGLenum>(attributes.get(EGL_VG_ALPHA_FORMAT, EGL_VG_ALPHA_FORMAT_NONPRE));
133     mVGColorspace = static_cast<EGLenum>(attributes.get(EGL_VG_COLORSPACE, EGL_VG_COLORSPACE_sRGB));
134     mMipmapTexture = (attributes.get(EGL_MIPMAP_TEXTURE, EGL_FALSE) == EGL_TRUE);
135 
136     mRobustResourceInitialization =
137         forceRobustResourceInit ||
138         (attributes.get(EGL_ROBUST_RESOURCE_INITIALIZATION_ANGLE, EGL_FALSE) == EGL_TRUE);
139     if (mRobustResourceInitialization)
140     {
141         mColorInitState        = gl::InitState::MayNeedInit;
142         mDepthStencilInitState = gl::InitState::MayNeedInit;
143     }
144 
145     mFixedSize = (attributes.get(EGL_FIXED_SIZE_ANGLE, EGL_FALSE) == EGL_TRUE);
146     if (mFixedSize)
147     {
148         mFixedWidth  = static_cast<size_t>(attributes.get(EGL_WIDTH, 0));
149         mFixedHeight = static_cast<size_t>(attributes.get(EGL_HEIGHT, 0));
150     }
151 
152     if (mType != EGL_WINDOW_BIT)
153     {
154         mTextureFormat = attributes.getAsPackedEnum(EGL_TEXTURE_FORMAT, TextureFormat::NoTexture);
155         mTextureTarget = static_cast<EGLenum>(attributes.get(EGL_TEXTURE_TARGET, EGL_NO_TEXTURE));
156     }
157 
158     mOrientation = static_cast<EGLint>(attributes.get(EGL_SURFACE_ORIENTATION_ANGLE, 0));
159 
160     mTextureOffset.x = static_cast<int>(mState.attributes.get(EGL_TEXTURE_OFFSET_X_ANGLE, 0));
161     mTextureOffset.y = static_cast<int>(mState.attributes.get(EGL_TEXTURE_OFFSET_Y_ANGLE, 0));
162 }
163 
~Surface()164 Surface::~Surface() {}
165 
getAttachmentImpl() const166 rx::FramebufferAttachmentObjectImpl *Surface::getAttachmentImpl() const
167 {
168     return mImplementation;
169 }
170 
destroyImpl(const Display * display)171 Error Surface::destroyImpl(const Display *display)
172 {
173     if (mImplementation)
174     {
175         mImplementation->destroy(display);
176     }
177 
178     ASSERT(!mTexture);
179 
180     SafeDelete(mImplementation);
181 
182     delete this;
183     return NoError();
184 }
185 
postSwap(const gl::Context * context)186 void Surface::postSwap(const gl::Context *context)
187 {
188     if (mRobustResourceInitialization && mState.swapBehavior != EGL_BUFFER_PRESERVED)
189     {
190         mColorInitState        = gl::InitState::MayNeedInit;
191         mDepthStencilInitState = gl::InitState::MayNeedInit;
192         onStateChange(angle::SubjectMessage::SubjectChanged);
193     }
194 
195     mBufferAgeQueriedSinceLastSwap = false;
196 
197     mIsDamageRegionSet = false;
198 }
199 
initialize(const Display * display)200 Error Surface::initialize(const Display *display)
201 {
202     GLenum overrideRenderTargetFormat = mState.config->renderTargetFormat;
203 
204     // To account for color space differences, override the renderTargetFormat with the
205     // non-linear format. If no suitable non-linear format was found, return
206     // EGL_BAD_MATCH error
207     if (!gl::ColorspaceFormatOverride(mGLColorspace, &overrideRenderTargetFormat))
208     {
209         return egl::Error(EGL_BAD_MATCH);
210     }
211 
212     // If an override is required update mState.config as well
213     if (mState.config->renderTargetFormat != overrideRenderTargetFormat)
214     {
215         egl::Config *overrideConfig        = new egl::Config(*(mState.config));
216         overrideConfig->renderTargetFormat = overrideRenderTargetFormat;
217         delete mState.config;
218         mState.config = overrideConfig;
219 
220         mColorFormat = gl::Format(mState.config->renderTargetFormat);
221         mDSFormat    = gl::Format(mState.config->depthStencilFormat);
222     }
223 
224     ANGLE_TRY(mImplementation->initialize(display));
225 
226     // Initialized here since impl is nullptr in the constructor.
227     // Must happen after implementation initialize for Android.
228     mState.swapBehavior = mImplementation->getSwapBehavior();
229 
230     if (mBuftype == EGL_IOSURFACE_ANGLE)
231     {
232         GLenum internalFormat =
233             static_cast<GLenum>(mState.attributes.get(EGL_TEXTURE_INTERNAL_FORMAT_ANGLE));
234         GLenum type = static_cast<GLenum>(mState.attributes.get(EGL_TEXTURE_TYPE_ANGLE));
235 
236         // GL_RGBA + GL_HALF_FLOAT is not a valid format/type combination in GLES like it is in
237         // desktop GL. Adjust the frontend format to be sized RGBA16F.
238         if (internalFormat == GL_RGBA && type == GL_HALF_FLOAT)
239         {
240             internalFormat = GL_RGBA16F;
241         }
242         mColorFormat = gl::Format(internalFormat, type);
243     }
244     if (mBuftype == EGL_D3D_TEXTURE_ANGLE)
245     {
246         const angle::Format *colorFormat = mImplementation->getD3DTextureColorFormat();
247         ASSERT(colorFormat != nullptr);
248         GLenum internalFormat = colorFormat->fboImplementationInternalFormat;
249         mColorFormat          = gl::Format(internalFormat, colorFormat->componentType);
250         mGLColorspace         = EGL_GL_COLORSPACE_LINEAR;
251         if (mColorFormat.info->colorEncoding == GL_SRGB)
252         {
253             mGLColorspace = EGL_GL_COLORSPACE_SRGB;
254         }
255     }
256 
257     if (mType == EGL_WINDOW_BIT && display->getExtensions().getFrameTimestamps)
258     {
259         mState.supportedCompositorTimings = mImplementation->getSupportedCompositorTimings();
260         mState.supportedTimestamps        = mImplementation->getSupportedTimestamps();
261     }
262 
263     mImplObserverBinding.bind(mImplementation);
264 
265     return NoError();
266 }
267 
makeCurrent(const gl::Context * context)268 Error Surface::makeCurrent(const gl::Context *context)
269 {
270     if (isLocked())
271     {
272         return egl::Error(EGL_BAD_ACCESS);
273     }
274     ANGLE_TRY(mImplementation->makeCurrent(context));
275     mIsCurrentOnAnyContext = true;
276     addRef();
277     return NoError();
278 }
279 
unMakeCurrent(const gl::Context * context)280 Error Surface::unMakeCurrent(const gl::Context *context)
281 {
282     ANGLE_TRY(mImplementation->unMakeCurrent(context));
283     mIsCurrentOnAnyContext = false;
284     return releaseRef(context->getDisplay());
285 }
286 
releaseRef(const Display * display)287 Error Surface::releaseRef(const Display *display)
288 {
289     ASSERT(mRefCount > 0);
290     mRefCount--;
291     if (mRefCount == 0 && mDestroyed)
292     {
293         ASSERT(display);
294         return destroyImpl(display);
295     }
296 
297     return NoError();
298 }
299 
onDestroy(const Display * display)300 Error Surface::onDestroy(const Display *display)
301 {
302     mDestroyed = true;
303     if (mRefCount == 0)
304     {
305         return destroyImpl(display);
306     }
307     return NoError();
308 }
309 
setLabel(EGLLabelKHR label)310 void Surface::setLabel(EGLLabelKHR label)
311 {
312     mState.label = label;
313 }
314 
getLabel() const315 EGLLabelKHR Surface::getLabel() const
316 {
317     return mState.label;
318 }
319 
getType() const320 EGLint Surface::getType() const
321 {
322     return mType;
323 }
324 
prepareSwap(const gl::Context * context)325 Error Surface::prepareSwap(const gl::Context *context)
326 {
327     ANGLE_TRACE_EVENT0("gpu.angle", "egl::Surface::prepareSwap");
328     return mImplementation->prepareSwap(context);
329 }
330 
swap(gl::Context * context)331 Error Surface::swap(gl::Context *context)
332 {
333     ANGLE_TRACE_EVENT0("gpu.angle", "egl::Surface::swap");
334     context->onPreSwap();
335 
336     context->getState().getOverlay()->onSwap();
337 
338     ANGLE_TRY(updatePropertiesOnSwap(context));
339 
340     rx::SurfaceSwapFeedback feedback;
341     ANGLE_TRY(mImplementation->swap(context, &feedback));
342     if (feedback.swapChainImageChanged)
343     {
344         context->onSwapChainImageChanged();
345     }
346 
347     postSwap(context);
348     return NoError();
349 }
350 
swapWithDamage(gl::Context * context,const EGLint * rects,EGLint n_rects)351 Error Surface::swapWithDamage(gl::Context *context, const EGLint *rects, EGLint n_rects)
352 {
353     ANGLE_TRACE_EVENT0("gpu.angle", "egl::Surface::swapWithDamage");
354     context->onPreSwap();
355 
356     context->getState().getOverlay()->onSwap();
357 
358     ANGLE_TRY(updatePropertiesOnSwap(context));
359 
360     rx::SurfaceSwapFeedback feedback;
361     ANGLE_TRY(mImplementation->swapWithDamage(context, rects, n_rects, &feedback));
362     if (feedback.swapChainImageChanged)
363     {
364         context->onSwapChainImageChanged();
365     }
366 
367     postSwap(context);
368     return NoError();
369 }
370 
postSubBuffer(const gl::Context * context,EGLint x,EGLint y,EGLint width,EGLint height)371 Error Surface::postSubBuffer(const gl::Context *context,
372                              EGLint x,
373                              EGLint y,
374                              EGLint width,
375                              EGLint height)
376 {
377     if (width == 0 || height == 0)
378     {
379         return egl::NoError();
380     }
381 
382     context->getState().getOverlay()->onSwap();
383 
384     ANGLE_TRY(updatePropertiesOnSwap(context));
385     ANGLE_TRY(mImplementation->postSubBuffer(context, x, y, width, height));
386     postSwap(context);
387     return NoError();
388 }
389 
setPresentationTime(EGLnsecsANDROID time)390 Error Surface::setPresentationTime(EGLnsecsANDROID time)
391 {
392     return mImplementation->setPresentationTime(time);
393 }
394 
querySurfacePointerANGLE(EGLint attribute,void ** value)395 Error Surface::querySurfacePointerANGLE(EGLint attribute, void **value)
396 {
397     return mImplementation->querySurfacePointerANGLE(attribute, value);
398 }
399 
isPostSubBufferSupported() const400 EGLint Surface::isPostSubBufferSupported() const
401 {
402     return mPostSubBufferRequested && mImplementation->isPostSubBufferSupported();
403 }
404 
setRequestedSwapInterval(EGLint interval)405 void Surface::setRequestedSwapInterval(EGLint interval)
406 {
407     mRequestedSwapInterval = interval;
408 }
409 
setSwapInterval(const Display * display,EGLint interval)410 void Surface::setSwapInterval(const Display *display, EGLint interval)
411 {
412     mImplementation->setSwapInterval(display, interval);
413     mState.swapInterval = interval;
414 }
415 
setMipmapLevel(EGLint level)416 void Surface::setMipmapLevel(EGLint level)
417 {
418     // Level is set but ignored
419     UNIMPLEMENTED();
420     mMipmapLevel = level;
421 }
422 
setMultisampleResolve(EGLenum resolve)423 void Surface::setMultisampleResolve(EGLenum resolve)
424 {
425     // Behaviour is set but ignored
426     UNIMPLEMENTED();
427     mMultisampleResolve = resolve;
428 }
429 
setSwapBehavior(EGLenum behavior)430 void Surface::setSwapBehavior(EGLenum behavior)
431 {
432     // Behaviour is set but ignored
433     UNIMPLEMENTED();
434     mState.swapBehavior = behavior;
435 }
436 
setFixedWidth(EGLint width)437 void Surface::setFixedWidth(EGLint width)
438 {
439     mFixedWidth = width;
440     mImplementation->setFixedWidth(width);
441 }
442 
setFixedHeight(EGLint height)443 void Surface::setFixedHeight(EGLint height)
444 {
445     mFixedHeight = height;
446     mImplementation->setFixedHeight(height);
447 }
448 
getConfig() const449 const Config *Surface::getConfig() const
450 {
451     return mState.config;
452 }
453 
getPixelAspectRatio() const454 EGLint Surface::getPixelAspectRatio() const
455 {
456     return mPixelAspectRatio;
457 }
458 
getRenderBuffer() const459 EGLenum Surface::getRenderBuffer() const
460 {
461     return mRenderBuffer;
462 }
463 
getRequestedRenderBuffer() const464 EGLenum Surface::getRequestedRenderBuffer() const
465 {
466     return mRequestedRenderBuffer;
467 }
468 
getSwapBehavior() const469 EGLenum Surface::getSwapBehavior() const
470 {
471     return mState.swapBehavior;
472 }
473 
getTextureFormat() const474 TextureFormat Surface::getTextureFormat() const
475 {
476     return mTextureFormat;
477 }
478 
getTextureTarget() const479 EGLenum Surface::getTextureTarget() const
480 {
481     return mTextureTarget;
482 }
483 
getLargestPbuffer() const484 bool Surface::getLargestPbuffer() const
485 {
486     return mLargestPbuffer;
487 }
488 
getGLColorspace() const489 EGLenum Surface::getGLColorspace() const
490 {
491     return mGLColorspace;
492 }
493 
getVGAlphaFormat() const494 EGLenum Surface::getVGAlphaFormat() const
495 {
496     return mVGAlphaFormat;
497 }
498 
getVGColorspace() const499 EGLenum Surface::getVGColorspace() const
500 {
501     return mVGColorspace;
502 }
503 
getMipmapTexture() const504 bool Surface::getMipmapTexture() const
505 {
506     return mMipmapTexture;
507 }
508 
getMipmapLevel() const509 EGLint Surface::getMipmapLevel() const
510 {
511     return mMipmapLevel;
512 }
513 
getHorizontalResolution() const514 EGLint Surface::getHorizontalResolution() const
515 {
516     return mHorizontalResolution;
517 }
518 
getVerticalResolution() const519 EGLint Surface::getVerticalResolution() const
520 {
521     return mVerticalResolution;
522 }
523 
getMultisampleResolve() const524 EGLenum Surface::getMultisampleResolve() const
525 {
526     return mMultisampleResolve;
527 }
528 
isFixedSize() const529 EGLint Surface::isFixedSize() const
530 {
531     return mFixedSize;
532 }
533 
getWidth() const534 EGLint Surface::getWidth() const
535 {
536     return mFixedSize ? static_cast<EGLint>(mFixedWidth) : mImplementation->getWidth();
537 }
538 
getHeight() const539 EGLint Surface::getHeight() const
540 {
541     return mFixedSize ? static_cast<EGLint>(mFixedHeight) : mImplementation->getHeight();
542 }
543 
getUserWidth(const egl::Display * display,EGLint * value) const544 egl::Error Surface::getUserWidth(const egl::Display *display, EGLint *value) const
545 {
546     if (mFixedSize)
547     {
548         *value = static_cast<EGLint>(mFixedWidth);
549         return NoError();
550     }
551     else
552     {
553         return mImplementation->getUserWidth(display, value);
554     }
555 }
556 
getUserHeight(const egl::Display * display,EGLint * value) const557 egl::Error Surface::getUserHeight(const egl::Display *display, EGLint *value) const
558 {
559     if (mFixedSize)
560     {
561         *value = static_cast<EGLint>(mFixedHeight);
562         return NoError();
563     }
564     else
565     {
566         return mImplementation->getUserHeight(display, value);
567     }
568 }
569 
bindTexImage(gl::Context * context,gl::Texture * texture,EGLint buffer)570 Error Surface::bindTexImage(gl::Context *context, gl::Texture *texture, EGLint buffer)
571 {
572     ASSERT(!mTexture);
573     ANGLE_TRY(mImplementation->bindTexImage(context, texture, buffer));
574     Surface *previousSurface = texture->getBoundSurface();
575     if (previousSurface != nullptr)
576     {
577         ANGLE_TRY(previousSurface->releaseTexImage(context, buffer));
578     }
579     if (texture->bindTexImageFromSurface(context, this) == angle::Result::Stop)
580     {
581         return Error(EGL_BAD_SURFACE);
582     }
583     mTexture = texture;
584     addRef();
585 
586     return NoError();
587 }
588 
releaseTexImage(const gl::Context * context,EGLint buffer)589 Error Surface::releaseTexImage(const gl::Context *context, EGLint buffer)
590 {
591     ASSERT(context);
592 
593     ANGLE_TRY(mImplementation->releaseTexImage(context, buffer));
594 
595     ASSERT(mTexture);
596     ANGLE_TRY(ResultToEGL(mTexture->releaseTexImageFromSurface(context)));
597 
598     return releaseTexImageFromTexture(context);
599 }
600 
getSyncValues(EGLuint64KHR * ust,EGLuint64KHR * msc,EGLuint64KHR * sbc)601 Error Surface::getSyncValues(EGLuint64KHR *ust, EGLuint64KHR *msc, EGLuint64KHR *sbc)
602 {
603     return mImplementation->getSyncValues(ust, msc, sbc);
604 }
605 
getMscRate(EGLint * numerator,EGLint * denominator)606 Error Surface::getMscRate(EGLint *numerator, EGLint *denominator)
607 {
608     return mImplementation->getMscRate(numerator, denominator);
609 }
610 
releaseTexImageFromTexture(const gl::Context * context)611 Error Surface::releaseTexImageFromTexture(const gl::Context *context)
612 {
613     ASSERT(mTexture);
614     mTexture = nullptr;
615     return releaseRef(context->getDisplay());
616 }
617 
isAttachmentSpecified(const gl::ImageIndex &) const618 bool Surface::isAttachmentSpecified(const gl::ImageIndex & /*imageIndex*/) const
619 {
620     // Surface is always specified even if it has 0 sizes.
621     return true;
622 }
623 
getAttachmentSize(const gl::ImageIndex &) const624 gl::Extents Surface::getAttachmentSize(const gl::ImageIndex & /*target*/) const
625 {
626     return gl::Extents(getWidth(), getHeight(), 1);
627 }
628 
getAttachmentFormat(GLenum binding,const gl::ImageIndex & target) const629 gl::Format Surface::getAttachmentFormat(GLenum binding, const gl::ImageIndex &target) const
630 {
631     return (binding == GL_BACK ? mColorFormat : mDSFormat);
632 }
633 
getAttachmentSamples(const gl::ImageIndex & target) const634 GLsizei Surface::getAttachmentSamples(const gl::ImageIndex &target) const
635 {
636     return getConfig()->samples;
637 }
638 
isRenderable(const gl::Context * context,GLenum binding,const gl::ImageIndex & imageIndex) const639 bool Surface::isRenderable(const gl::Context *context,
640                            GLenum binding,
641                            const gl::ImageIndex &imageIndex) const
642 {
643     return true;
644 }
645 
isYUV() const646 bool Surface::isYUV() const
647 {
648     // EGL_EXT_yuv_surface is not implemented.
649     return false;
650 }
651 
isExternalImageWithoutIndividualSync() const652 bool Surface::isExternalImageWithoutIndividualSync() const
653 {
654     return false;
655 }
656 
hasFrontBufferUsage() const657 bool Surface::hasFrontBufferUsage() const
658 {
659     return false;
660 }
661 
getId() const662 GLuint Surface::getId() const
663 {
664     return mState.id.value;
665 }
666 
getBufferAgeImpl(const gl::Context * context,EGLint * age) const667 Error Surface::getBufferAgeImpl(const gl::Context *context, EGLint *age) const
668 {
669     // When EGL_BUFFER_PRESERVED, the previous frame contents are copied to
670     // current frame, so the buffer age is always 1.
671     if (mState.swapBehavior == EGL_BUFFER_PRESERVED)
672     {
673         if (age != nullptr)
674         {
675             *age = 1;
676         }
677         return egl::NoError();
678     }
679     return mImplementation->getBufferAge(context, age);
680 }
681 
getBufferAge(const gl::Context * context,EGLint * age)682 Error Surface::getBufferAge(const gl::Context *context, EGLint *age)
683 {
684     Error err = getBufferAgeImpl(context, age);
685     if (!err.isError())
686     {
687         mBufferAgeQueriedSinceLastSwap = true;
688     }
689     return err;
690 }
691 
initState(GLenum binding,const gl::ImageIndex &) const692 gl::InitState Surface::initState(GLenum binding, const gl::ImageIndex & /*imageIndex*/) const
693 {
694     switch (binding)
695     {
696         case GL_BACK:
697             return mColorInitState;
698         case GL_DEPTH:
699         case GL_STENCIL:
700             return mDepthStencilInitState;
701         default:
702             UNREACHABLE();
703             return gl::InitState::Initialized;
704     }
705 }
706 
setInitState(GLenum binding,const gl::ImageIndex &,gl::InitState initState)707 void Surface::setInitState(GLenum binding,
708                            const gl::ImageIndex & /*imageIndex*/,
709                            gl::InitState initState)
710 {
711     switch (binding)
712     {
713         case GL_BACK:
714             mColorInitState = initState;
715             break;
716         case GL_DEPTH:
717         case GL_STENCIL:
718             mDepthStencilInitState = initState;
719             break;
720         default:
721             UNREACHABLE();
722             break;
723     }
724 }
725 
setTimestampsEnabled(bool enabled)726 void Surface::setTimestampsEnabled(bool enabled)
727 {
728     mImplementation->setTimestampsEnabled(enabled);
729     mState.timestampsEnabled = enabled;
730 }
731 
isTimestampsEnabled() const732 bool Surface::isTimestampsEnabled() const
733 {
734     return mState.timestampsEnabled;
735 }
736 
setAutoRefreshEnabled(bool enabled)737 Error Surface::setAutoRefreshEnabled(bool enabled)
738 {
739     ANGLE_TRY(mImplementation->setAutoRefreshEnabled(enabled));
740     mState.autoRefreshEnabled = enabled;
741     return NoError();
742 }
743 
hasProtectedContent() const744 bool Surface::hasProtectedContent() const
745 {
746     return mState.hasProtectedContent();
747 }
748 
getSupportedCompositorTimings() const749 const SupportedCompositorTiming &Surface::getSupportedCompositorTimings() const
750 {
751     return mState.supportedCompositorTimings;
752 }
753 
getCompositorTiming(EGLint numTimestamps,const EGLint * names,EGLnsecsANDROID * values) const754 Error Surface::getCompositorTiming(EGLint numTimestamps,
755                                    const EGLint *names,
756                                    EGLnsecsANDROID *values) const
757 {
758     return mImplementation->getCompositorTiming(numTimestamps, names, values);
759 }
760 
getNextFrameId(EGLuint64KHR * frameId) const761 Error Surface::getNextFrameId(EGLuint64KHR *frameId) const
762 {
763     return mImplementation->getNextFrameId(frameId);
764 }
765 
getSupportedTimestamps() const766 const SupportedTimestamps &Surface::getSupportedTimestamps() const
767 {
768     return mState.supportedTimestamps;
769 }
770 
getFrameTimestamps(EGLuint64KHR frameId,EGLint numTimestamps,const EGLint * timestamps,EGLnsecsANDROID * values) const771 Error Surface::getFrameTimestamps(EGLuint64KHR frameId,
772                                   EGLint numTimestamps,
773                                   const EGLint *timestamps,
774                                   EGLnsecsANDROID *values) const
775 {
776     return mImplementation->getFrameTimestamps(frameId, numTimestamps, timestamps, values);
777 }
778 
onSubjectStateChange(angle::SubjectIndex index,angle::SubjectMessage message)779 void Surface::onSubjectStateChange(angle::SubjectIndex index, angle::SubjectMessage message)
780 {
781     ASSERT(index == kSurfaceImplSubjectIndex);
782     switch (message)
783     {
784         case angle::SubjectMessage::SubjectChanged:
785             onStateChange(angle::SubjectMessage::ContentsChanged);
786             break;
787         case angle::SubjectMessage::SurfaceChanged:
788             onStateChange(angle::SubjectMessage::SurfaceChanged);
789             break;
790         default:
791             UNREACHABLE();
792             break;
793     }
794 }
795 
setRenderBuffer(EGLint renderBuffer)796 Error Surface::setRenderBuffer(EGLint renderBuffer)
797 {
798     ANGLE_TRY(mImplementation->setRenderBuffer(renderBuffer));
799     mRenderBuffer = renderBuffer;
800     return NoError();
801 }
802 
setRequestedRenderBuffer(EGLint requestedRenderBuffer)803 void Surface::setRequestedRenderBuffer(EGLint requestedRenderBuffer)
804 {
805     mRequestedRenderBuffer = requestedRenderBuffer;
806 }
807 
updatePropertiesOnSwap(const gl::Context * context)808 Error Surface::updatePropertiesOnSwap(const gl::Context *context)
809 {
810     if ((mRenderBuffer != mRequestedRenderBuffer) &&
811         context->getDisplay()->getExtensions().mutableRenderBufferKHR &&
812         (getConfig()->surfaceType & EGL_MUTABLE_RENDER_BUFFER_BIT_KHR))
813     {
814         ANGLE_TRY(setRenderBuffer(mRequestedRenderBuffer));
815     }
816     if (mState.swapInterval != mRequestedSwapInterval)
817     {
818         setSwapInterval(context->getDisplay(), mRequestedSwapInterval);
819     }
820     return NoError();
821 }
822 
isLocked() const823 bool Surface::isLocked() const
824 {
825     return (mLockBufferPtr != nullptr);
826 }
827 
getBitmapPitch() const828 EGLint Surface::getBitmapPitch() const
829 {
830     return mLockBufferPitch;
831 }
832 
getBitmapOrigin() const833 EGLint Surface::getBitmapOrigin() const
834 {
835     return mImplementation->origin();
836 }
837 
getRedOffset() const838 EGLint Surface::getRedOffset() const
839 {
840     const gl::InternalFormat &format = *mColorFormat.info;
841     if (gl::IsBGRAFormat(format.internalFormat))
842     {
843         return format.blueBits + format.greenBits;
844     }
845     else
846     {
847         return 0;
848     }
849 }
850 
getGreenOffset() const851 EGLint Surface::getGreenOffset() const
852 {
853     const gl::InternalFormat &format = *mColorFormat.info;
854     if (gl::IsBGRAFormat(format.internalFormat))
855     {
856         return format.blueBits;
857     }
858     else
859     {
860         return format.redBits;
861     }
862 }
863 
getBlueOffset() const864 EGLint Surface::getBlueOffset() const
865 {
866     const gl::InternalFormat &format = *mColorFormat.info;
867     if (gl::IsBGRAFormat(format.internalFormat))
868     {
869         return 0;
870     }
871     else
872     {
873         return format.redBits + format.greenBits;
874     }
875 }
876 
getAlphaOffset() const877 EGLint Surface::getAlphaOffset() const
878 {
879     const gl::InternalFormat &format = *mColorFormat.info;
880     if (format.isLUMA())
881     {
882         return format.luminanceBits;  // Luma always first, alpha optional
883     }
884     // For RGBA/BGRA alpha is last
885     return format.blueBits + format.greenBits + format.redBits;
886 }
887 
getLuminanceOffset() const888 EGLint Surface::getLuminanceOffset() const
889 {
890     return 0;
891 }
892 
getBitmapPixelSize() const893 EGLint Surface::getBitmapPixelSize() const
894 {
895     constexpr EGLint kBitsPerByte    = 8;
896     const gl::InternalFormat &format = *mColorFormat.info;
897     return (format.pixelBytes * kBitsPerByte);
898 }
899 
getBitmapPointer() const900 EGLAttribKHR Surface::getBitmapPointer() const
901 {
902     return static_cast<EGLAttribKHR>((intptr_t)mLockBufferPtr);
903 }
904 
getCompressionRate(const egl::Display * display) const905 EGLint Surface::getCompressionRate(const egl::Display *display) const
906 {
907     return mImplementation->getCompressionRate(display);
908 }
909 
lockSurfaceKHR(const egl::Display * display,const AttributeMap & attributes)910 egl::Error Surface::lockSurfaceKHR(const egl::Display *display, const AttributeMap &attributes)
911 {
912     EGLint lockBufferUsageHint = attributes.getAsInt(
913         EGL_LOCK_USAGE_HINT_KHR, (EGL_READ_SURFACE_BIT_KHR | EGL_WRITE_SURFACE_BIT_KHR));
914 
915     bool preservePixels = ((attributes.getAsInt(EGL_MAP_PRESERVE_PIXELS_KHR, false) == EGL_TRUE) ||
916                            (mState.swapBehavior == EGL_BUFFER_PRESERVED));
917 
918     return mImplementation->lockSurface(display, lockBufferUsageHint, preservePixels,
919                                         &mLockBufferPtr, &mLockBufferPitch);
920 }
921 
unlockSurfaceKHR(const egl::Display * display)922 egl::Error Surface::unlockSurfaceKHR(const egl::Display *display)
923 {
924     mLockBufferPtr   = nullptr;
925     mLockBufferPitch = 0;
926     return mImplementation->unlockSurface(display, true);
927 }
928 
WindowSurface(rx::EGLImplFactory * implFactory,SurfaceID id,const egl::Config * config,EGLNativeWindowType window,const AttributeMap & attribs,bool robustResourceInit)929 WindowSurface::WindowSurface(rx::EGLImplFactory *implFactory,
930                              SurfaceID id,
931                              const egl::Config *config,
932                              EGLNativeWindowType window,
933                              const AttributeMap &attribs,
934                              bool robustResourceInit)
935     : Surface(EGL_WINDOW_BIT, id, config, attribs, robustResourceInit)
936 {
937     mImplementation = implFactory->createWindowSurface(mState, window, attribs);
938 }
939 
setDamageRegion(const EGLint * rects,EGLint n_rects)940 void Surface::setDamageRegion(const EGLint *rects, EGLint n_rects)
941 {
942     mIsDamageRegionSet = true;
943 }
944 
~WindowSurface()945 WindowSurface::~WindowSurface() {}
946 
PbufferSurface(rx::EGLImplFactory * implFactory,SurfaceID id,const Config * config,const AttributeMap & attribs,bool robustResourceInit)947 PbufferSurface::PbufferSurface(rx::EGLImplFactory *implFactory,
948                                SurfaceID id,
949                                const Config *config,
950                                const AttributeMap &attribs,
951                                bool robustResourceInit)
952     : Surface(EGL_PBUFFER_BIT, id, config, attribs, robustResourceInit)
953 {
954     mImplementation = implFactory->createPbufferSurface(mState, attribs);
955 }
956 
PbufferSurface(rx::EGLImplFactory * implFactory,SurfaceID id,const Config * config,EGLenum buftype,EGLClientBuffer clientBuffer,const AttributeMap & attribs,bool robustResourceInit)957 PbufferSurface::PbufferSurface(rx::EGLImplFactory *implFactory,
958                                SurfaceID id,
959                                const Config *config,
960                                EGLenum buftype,
961                                EGLClientBuffer clientBuffer,
962                                const AttributeMap &attribs,
963                                bool robustResourceInit)
964     : Surface(EGL_PBUFFER_BIT, id, config, attribs, robustResourceInit, buftype)
965 {
966     mImplementation =
967         implFactory->createPbufferFromClientBuffer(mState, buftype, clientBuffer, attribs);
968 }
969 
~PbufferSurface()970 PbufferSurface::~PbufferSurface() {}
971 
PixmapSurface(rx::EGLImplFactory * implFactory,SurfaceID id,const Config * config,NativePixmapType nativePixmap,const AttributeMap & attribs,bool robustResourceInit)972 PixmapSurface::PixmapSurface(rx::EGLImplFactory *implFactory,
973                              SurfaceID id,
974                              const Config *config,
975                              NativePixmapType nativePixmap,
976                              const AttributeMap &attribs,
977                              bool robustResourceInit)
978     : Surface(EGL_PIXMAP_BIT, id, config, attribs, robustResourceInit)
979 {
980     mImplementation = implFactory->createPixmapSurface(mState, nativePixmap, attribs);
981 }
982 
~PixmapSurface()983 PixmapSurface::~PixmapSurface() {}
984 
985 // SurfaceDeleter implementation.
986 
SurfaceDeleter(const Display * display)987 SurfaceDeleter::SurfaceDeleter(const Display *display) : mDisplay(display) {}
988 
~SurfaceDeleter()989 SurfaceDeleter::~SurfaceDeleter() {}
990 
operator ()(Surface * surface)991 void SurfaceDeleter::operator()(Surface *surface)
992 {
993     ANGLE_SWALLOW_ERR(surface->onDestroy(mDisplay));
994 }
995 
996 }  // namespace egl
997