xref: /aosp_15_r20/external/angle/src/libANGLE/Surface.cpp (revision 8975f5c5ed3d1c378011245431ada316dfb6f244)
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 {
43     directComposition = attributes.get(EGL_DIRECT_COMPOSITION_ANGLE, EGL_FALSE) == EGL_TRUE;
44 }
45 
~SurfaceState()46 SurfaceState::~SurfaceState()
47 {
48     delete config;
49 }
50 
isRobustResourceInitEnabled() const51 bool SurfaceState::isRobustResourceInitEnabled() const
52 {
53     return attributes.get(EGL_ROBUST_RESOURCE_INITIALIZATION_ANGLE, EGL_FALSE) == EGL_TRUE;
54 }
55 
hasProtectedContent() const56 bool SurfaceState::hasProtectedContent() const
57 {
58     return attributes.get(EGL_PROTECTED_CONTENT_EXT, EGL_FALSE) == EGL_TRUE;
59 }
60 
getPreferredSwapInterval() const61 EGLint SurfaceState::getPreferredSwapInterval() const
62 {
63     return attributes.getAsInt(EGL_SWAP_INTERVAL_ANGLE, 1);
64 }
65 
Surface(EGLint surfaceType,SurfaceID id,const egl::Config * config,const AttributeMap & attributes,bool forceRobustResourceInit,EGLenum buftype)66 Surface::Surface(EGLint surfaceType,
67                  SurfaceID id,
68                  const egl::Config *config,
69                  const AttributeMap &attributes,
70                  bool forceRobustResourceInit,
71                  EGLenum buftype)
72     : FramebufferAttachmentObject(),
73       mState(id, config, attributes),
74       mImplementation(nullptr),
75       mRefCount(0),
76       mDestroyed(false),
77       mType(surfaceType),
78       mBuftype(buftype),
79       mPostSubBufferRequested(false),
80       mLargestPbuffer(false),
81       mGLColorspace(EGL_GL_COLORSPACE_LINEAR),
82       mVGAlphaFormat(EGL_VG_ALPHA_FORMAT_NONPRE),
83       mVGColorspace(EGL_VG_COLORSPACE_sRGB),
84       mMipmapTexture(false),
85       mMipmapLevel(0),
86       mHorizontalResolution(EGL_UNKNOWN),
87       mVerticalResolution(EGL_UNKNOWN),
88       mMultisampleResolve(EGL_MULTISAMPLE_RESOLVE_DEFAULT),
89       mFixedSize(false),
90       mFixedWidth(0),
91       mFixedHeight(0),
92       mTextureFormat(TextureFormat::NoTexture),
93       mTextureTarget(EGL_NO_TEXTURE),
94       // FIXME: Determine actual pixel aspect ratio
95       mPixelAspectRatio(static_cast<EGLint>(1.0 * EGL_DISPLAY_SCALING)),
96       mRenderBuffer(EGL_BACK_BUFFER),
97       mOrientation(0),
98       mTexture(nullptr),
99       mColorFormat(config->renderTargetFormat),
100       mDSFormat(config->depthStencilFormat),
101       mIsCurrentOnAnyContext(false),
102       mLockBufferPtr(nullptr),
103       mLockBufferPitch(0),
104       mBufferAgeQueriedSinceLastSwap(false),
105       mIsDamageRegionSet(false),
106       mColorInitState(gl::InitState::Initialized),
107       mDepthStencilInitState(gl::InitState::Initialized),
108       mImplObserverBinding(this, kSurfaceImplSubjectIndex)
109 {
110     mPostSubBufferRequested =
111         (attributes.get(EGL_POST_SUB_BUFFER_SUPPORTED_NV, EGL_FALSE) == EGL_TRUE);
112 
113     if (mType == EGL_PBUFFER_BIT)
114     {
115         mLargestPbuffer = (attributes.get(EGL_LARGEST_PBUFFER, EGL_FALSE) == EGL_TRUE);
116     }
117 
118     if (mType == EGL_PIXMAP_BIT)
119     {
120         mRenderBuffer = EGL_SINGLE_BUFFER;
121     }
122 
123     if (mType == EGL_WINDOW_BIT)
124     {
125         mRenderBuffer = mState.attributes.getAsInt(EGL_RENDER_BUFFER, EGL_BACK_BUFFER);
126     }
127 
128     mGLColorspace =
129         static_cast<EGLenum>(attributes.get(EGL_GL_COLORSPACE, EGL_GL_COLORSPACE_LINEAR));
130     mVGAlphaFormat =
131         static_cast<EGLenum>(attributes.get(EGL_VG_ALPHA_FORMAT, EGL_VG_ALPHA_FORMAT_NONPRE));
132     mVGColorspace = static_cast<EGLenum>(attributes.get(EGL_VG_COLORSPACE, EGL_VG_COLORSPACE_sRGB));
133     mMipmapTexture = (attributes.get(EGL_MIPMAP_TEXTURE, EGL_FALSE) == EGL_TRUE);
134 
135     mRobustResourceInitialization =
136         forceRobustResourceInit ||
137         (attributes.get(EGL_ROBUST_RESOURCE_INITIALIZATION_ANGLE, EGL_FALSE) == EGL_TRUE);
138     if (mRobustResourceInitialization)
139     {
140         mColorInitState        = gl::InitState::MayNeedInit;
141         mDepthStencilInitState = gl::InitState::MayNeedInit;
142     }
143 
144     mFixedSize = (attributes.get(EGL_FIXED_SIZE_ANGLE, EGL_FALSE) == EGL_TRUE);
145     if (mFixedSize)
146     {
147         mFixedWidth  = static_cast<size_t>(attributes.get(EGL_WIDTH, 0));
148         mFixedHeight = static_cast<size_t>(attributes.get(EGL_HEIGHT, 0));
149     }
150 
151     if (mType != EGL_WINDOW_BIT)
152     {
153         mTextureFormat = attributes.getAsPackedEnum(EGL_TEXTURE_FORMAT, TextureFormat::NoTexture);
154         mTextureTarget = static_cast<EGLenum>(attributes.get(EGL_TEXTURE_TARGET, EGL_NO_TEXTURE));
155     }
156 
157     mOrientation = static_cast<EGLint>(attributes.get(EGL_SURFACE_ORIENTATION_ANGLE, 0));
158 
159     mTextureOffset.x = static_cast<int>(mState.attributes.get(EGL_TEXTURE_OFFSET_X_ANGLE, 0));
160     mTextureOffset.y = static_cast<int>(mState.attributes.get(EGL_TEXTURE_OFFSET_Y_ANGLE, 0));
161 }
162 
~Surface()163 Surface::~Surface() {}
164 
getAttachmentImpl() const165 rx::FramebufferAttachmentObjectImpl *Surface::getAttachmentImpl() const
166 {
167     return mImplementation;
168 }
169 
destroyImpl(const Display * display)170 Error Surface::destroyImpl(const Display *display)
171 {
172     if (mImplementation)
173     {
174         mImplementation->destroy(display);
175     }
176 
177     ASSERT(!mTexture);
178 
179     SafeDelete(mImplementation);
180 
181     delete this;
182     return NoError();
183 }
184 
postSwap(const gl::Context * context)185 void Surface::postSwap(const gl::Context *context)
186 {
187     if (mRobustResourceInitialization && mState.swapBehavior != EGL_BUFFER_PRESERVED)
188     {
189         mColorInitState        = gl::InitState::MayNeedInit;
190         mDepthStencilInitState = gl::InitState::MayNeedInit;
191         onStateChange(angle::SubjectMessage::SubjectChanged);
192     }
193 
194     mBufferAgeQueriedSinceLastSwap = false;
195 
196     mIsDamageRegionSet = false;
197 }
198 
initialize(const Display * display)199 Error Surface::initialize(const Display *display)
200 {
201     GLenum overrideRenderTargetFormat = mState.config->renderTargetFormat;
202 
203     // To account for color space differences, override the renderTargetFormat with the
204     // non-linear format. If no suitable non-linear format was found, return
205     // EGL_BAD_MATCH error
206     if (!gl::ColorspaceFormatOverride(mGLColorspace, &overrideRenderTargetFormat))
207     {
208         return egl::EglBadMatch();
209     }
210 
211     // If an override is required update mState.config as well
212     if (mState.config->renderTargetFormat != overrideRenderTargetFormat)
213     {
214         egl::Config *overrideConfig        = new egl::Config(*(mState.config));
215         overrideConfig->renderTargetFormat = overrideRenderTargetFormat;
216         delete mState.config;
217         mState.config = overrideConfig;
218 
219         mColorFormat = gl::Format(mState.config->renderTargetFormat);
220         mDSFormat    = gl::Format(mState.config->depthStencilFormat);
221     }
222 
223     ANGLE_TRY(mImplementation->initialize(display));
224 
225     // Initialized here since impl is nullptr in the constructor.
226     // Must happen after implementation initialize for Android.
227     mState.swapBehavior = mImplementation->getSwapBehavior();
228 
229     if (mBuftype == EGL_IOSURFACE_ANGLE)
230     {
231         GLenum internalFormat =
232             static_cast<GLenum>(mState.attributes.get(EGL_TEXTURE_INTERNAL_FORMAT_ANGLE));
233         GLenum type = static_cast<GLenum>(mState.attributes.get(EGL_TEXTURE_TYPE_ANGLE));
234 
235         // GL_RGBA + GL_HALF_FLOAT is not a valid format/type combination in GLES like it is in
236         // desktop GL. Adjust the frontend format to be sized RGBA16F.
237         if (internalFormat == GL_RGBA && type == GL_HALF_FLOAT)
238         {
239             internalFormat = GL_RGBA16F;
240         }
241         mColorFormat = gl::Format(internalFormat, type);
242     }
243     if (mBuftype == EGL_D3D_TEXTURE_ANGLE)
244     {
245         const angle::Format *colorFormat = mImplementation->getD3DTextureColorFormat();
246         ASSERT(colorFormat != nullptr);
247         GLenum internalFormat = colorFormat->fboImplementationInternalFormat;
248         mColorFormat          = gl::Format(internalFormat, colorFormat->componentType);
249         mGLColorspace         = EGL_GL_COLORSPACE_LINEAR;
250         if (mColorFormat.info->colorEncoding == GL_SRGB)
251         {
252             mGLColorspace = EGL_GL_COLORSPACE_SRGB;
253         }
254     }
255 
256     if (mType == EGL_WINDOW_BIT && display->getExtensions().getFrameTimestamps)
257     {
258         mState.supportedCompositorTimings = mImplementation->getSupportedCompositorTimings();
259         mState.supportedTimestamps        = mImplementation->getSupportedTimestamps();
260     }
261 
262     mImplObserverBinding.bind(mImplementation);
263 
264     return NoError();
265 }
266 
makeCurrent(const gl::Context * context)267 Error Surface::makeCurrent(const gl::Context *context)
268 {
269     if (isLocked())
270     {
271         return EglBadAccess();
272     }
273     ANGLE_TRY(mImplementation->makeCurrent(context));
274     mIsCurrentOnAnyContext = true;
275     addRef();
276     return NoError();
277 }
278 
unMakeCurrent(const gl::Context * context)279 Error Surface::unMakeCurrent(const gl::Context *context)
280 {
281     ANGLE_TRY(mImplementation->unMakeCurrent(context));
282     mIsCurrentOnAnyContext = false;
283     return releaseRef(context->getDisplay());
284 }
285 
releaseRef(const Display * display)286 Error Surface::releaseRef(const Display *display)
287 {
288     ASSERT(mRefCount > 0);
289     mRefCount--;
290     if (mRefCount == 0 && mDestroyed)
291     {
292         ASSERT(display);
293         return destroyImpl(display);
294     }
295 
296     return NoError();
297 }
298 
onDestroy(const Display * display)299 Error Surface::onDestroy(const Display *display)
300 {
301     mDestroyed = true;
302     if (mRefCount == 0)
303     {
304         return destroyImpl(display);
305     }
306     return NoError();
307 }
308 
setLabel(EGLLabelKHR label)309 void Surface::setLabel(EGLLabelKHR label)
310 {
311     mState.label = label;
312 }
313 
getLabel() const314 EGLLabelKHR Surface::getLabel() const
315 {
316     return mState.label;
317 }
318 
getType() const319 EGLint Surface::getType() const
320 {
321     return mType;
322 }
323 
prepareSwap(const gl::Context * context)324 Error Surface::prepareSwap(const gl::Context *context)
325 {
326     ANGLE_TRACE_EVENT0("gpu.angle", "egl::Surface::prepareSwap");
327     return mImplementation->prepareSwap(context);
328 }
329 
swap(gl::Context * context)330 Error Surface::swap(gl::Context *context)
331 {
332     ANGLE_TRACE_EVENT0("gpu.angle", "egl::Surface::swap");
333     context->onPreSwap();
334 
335     context->getState().getOverlay()->onSwap();
336 
337     ANGLE_TRY(mImplementation->swap(context));
338     postSwap(context);
339     return NoError();
340 }
341 
swapWithDamage(gl::Context * context,const EGLint * rects,EGLint n_rects)342 Error Surface::swapWithDamage(gl::Context *context, const EGLint *rects, EGLint n_rects)
343 {
344     ANGLE_TRACE_EVENT0("gpu.angle", "egl::Surface::swapWithDamage");
345     context->onPreSwap();
346 
347     context->getState().getOverlay()->onSwap();
348 
349     ANGLE_TRY(mImplementation->swapWithDamage(context, rects, n_rects));
350     postSwap(context);
351     return NoError();
352 }
353 
swapWithFrameToken(gl::Context * context,EGLFrameTokenANGLE frameToken)354 Error Surface::swapWithFrameToken(gl::Context *context, EGLFrameTokenANGLE frameToken)
355 {
356     ANGLE_TRACE_EVENT0("gpu.angle", "egl::Surface::swapWithFrameToken");
357     context->onPreSwap();
358 
359     context->getState().getOverlay()->onSwap();
360 
361     ANGLE_TRY(mImplementation->swapWithFrameToken(context, frameToken));
362     postSwap(context);
363     return NoError();
364 }
365 
postSubBuffer(const gl::Context * context,EGLint x,EGLint y,EGLint width,EGLint height)366 Error Surface::postSubBuffer(const gl::Context *context,
367                              EGLint x,
368                              EGLint y,
369                              EGLint width,
370                              EGLint height)
371 {
372     if (width == 0 || height == 0)
373     {
374         return egl::NoError();
375     }
376 
377     context->getState().getOverlay()->onSwap();
378 
379     ANGLE_TRY(mImplementation->postSubBuffer(context, x, y, width, height));
380     postSwap(context);
381     return NoError();
382 }
383 
setPresentationTime(EGLnsecsANDROID time)384 Error Surface::setPresentationTime(EGLnsecsANDROID time)
385 {
386     return mImplementation->setPresentationTime(time);
387 }
388 
querySurfacePointerANGLE(EGLint attribute,void ** value)389 Error Surface::querySurfacePointerANGLE(EGLint attribute, void **value)
390 {
391     return mImplementation->querySurfacePointerANGLE(attribute, value);
392 }
393 
isPostSubBufferSupported() const394 EGLint Surface::isPostSubBufferSupported() const
395 {
396     return mPostSubBufferRequested && mImplementation->isPostSubBufferSupported();
397 }
398 
setSwapInterval(const Display * display,EGLint interval)399 void Surface::setSwapInterval(const Display *display, EGLint interval)
400 {
401     mImplementation->setSwapInterval(display, interval);
402 }
403 
setMipmapLevel(EGLint level)404 void Surface::setMipmapLevel(EGLint level)
405 {
406     // Level is set but ignored
407     UNIMPLEMENTED();
408     mMipmapLevel = level;
409 }
410 
setMultisampleResolve(EGLenum resolve)411 void Surface::setMultisampleResolve(EGLenum resolve)
412 {
413     // Behaviour is set but ignored
414     UNIMPLEMENTED();
415     mMultisampleResolve = resolve;
416 }
417 
setSwapBehavior(EGLenum behavior)418 void Surface::setSwapBehavior(EGLenum behavior)
419 {
420     // Behaviour is set but ignored
421     UNIMPLEMENTED();
422     mState.swapBehavior = behavior;
423 }
424 
setFixedWidth(EGLint width)425 void Surface::setFixedWidth(EGLint width)
426 {
427     mFixedWidth = width;
428     mImplementation->setFixedWidth(width);
429 }
430 
setFixedHeight(EGLint height)431 void Surface::setFixedHeight(EGLint height)
432 {
433     mFixedHeight = height;
434     mImplementation->setFixedHeight(height);
435 }
436 
getConfig() const437 const Config *Surface::getConfig() const
438 {
439     return mState.config;
440 }
441 
getPixelAspectRatio() const442 EGLint Surface::getPixelAspectRatio() const
443 {
444     return mPixelAspectRatio;
445 }
446 
getRenderBuffer() const447 EGLenum Surface::getRenderBuffer() const
448 {
449     return mRenderBuffer;
450 }
451 
getSwapBehavior() const452 EGLenum Surface::getSwapBehavior() const
453 {
454     return mState.swapBehavior;
455 }
456 
getTextureFormat() const457 TextureFormat Surface::getTextureFormat() const
458 {
459     return mTextureFormat;
460 }
461 
getTextureTarget() const462 EGLenum Surface::getTextureTarget() const
463 {
464     return mTextureTarget;
465 }
466 
getLargestPbuffer() const467 bool Surface::getLargestPbuffer() const
468 {
469     return mLargestPbuffer;
470 }
471 
getGLColorspace() const472 EGLenum Surface::getGLColorspace() const
473 {
474     return mGLColorspace;
475 }
476 
getVGAlphaFormat() const477 EGLenum Surface::getVGAlphaFormat() const
478 {
479     return mVGAlphaFormat;
480 }
481 
getVGColorspace() const482 EGLenum Surface::getVGColorspace() const
483 {
484     return mVGColorspace;
485 }
486 
getMipmapTexture() const487 bool Surface::getMipmapTexture() const
488 {
489     return mMipmapTexture;
490 }
491 
getMipmapLevel() const492 EGLint Surface::getMipmapLevel() const
493 {
494     return mMipmapLevel;
495 }
496 
getHorizontalResolution() const497 EGLint Surface::getHorizontalResolution() const
498 {
499     return mHorizontalResolution;
500 }
501 
getVerticalResolution() const502 EGLint Surface::getVerticalResolution() const
503 {
504     return mVerticalResolution;
505 }
506 
getMultisampleResolve() const507 EGLenum Surface::getMultisampleResolve() const
508 {
509     return mMultisampleResolve;
510 }
511 
isFixedSize() const512 EGLint Surface::isFixedSize() const
513 {
514     return mFixedSize;
515 }
516 
getWidth() const517 EGLint Surface::getWidth() const
518 {
519     return mFixedSize ? static_cast<EGLint>(mFixedWidth) : mImplementation->getWidth();
520 }
521 
getHeight() const522 EGLint Surface::getHeight() const
523 {
524     return mFixedSize ? static_cast<EGLint>(mFixedHeight) : mImplementation->getHeight();
525 }
526 
getUserWidth(const egl::Display * display,EGLint * value) const527 egl::Error Surface::getUserWidth(const egl::Display *display, EGLint *value) const
528 {
529     if (mFixedSize)
530     {
531         *value = static_cast<EGLint>(mFixedWidth);
532         return NoError();
533     }
534     else
535     {
536         return mImplementation->getUserWidth(display, value);
537     }
538 }
539 
getUserHeight(const egl::Display * display,EGLint * value) const540 egl::Error Surface::getUserHeight(const egl::Display *display, EGLint *value) const
541 {
542     if (mFixedSize)
543     {
544         *value = static_cast<EGLint>(mFixedHeight);
545         return NoError();
546     }
547     else
548     {
549         return mImplementation->getUserHeight(display, value);
550     }
551 }
552 
bindTexImage(gl::Context * context,gl::Texture * texture,EGLint buffer)553 Error Surface::bindTexImage(gl::Context *context, gl::Texture *texture, EGLint buffer)
554 {
555     ASSERT(!mTexture);
556     ANGLE_TRY(mImplementation->bindTexImage(context, texture, buffer));
557     Surface *previousSurface = texture->getBoundSurface();
558     if (previousSurface != nullptr)
559     {
560         ANGLE_TRY(previousSurface->releaseTexImage(context, buffer));
561     }
562     if (texture->bindTexImageFromSurface(context, this) == angle::Result::Stop)
563     {
564         return Error(EGL_BAD_SURFACE);
565     }
566     mTexture = texture;
567     addRef();
568 
569     return NoError();
570 }
571 
releaseTexImage(const gl::Context * context,EGLint buffer)572 Error Surface::releaseTexImage(const gl::Context *context, EGLint buffer)
573 {
574     ASSERT(context);
575 
576     ANGLE_TRY(mImplementation->releaseTexImage(context, buffer));
577 
578     ASSERT(mTexture);
579     ANGLE_TRY(ResultToEGL(mTexture->releaseTexImageFromSurface(context)));
580 
581     return releaseTexImageFromTexture(context);
582 }
583 
getSyncValues(EGLuint64KHR * ust,EGLuint64KHR * msc,EGLuint64KHR * sbc)584 Error Surface::getSyncValues(EGLuint64KHR *ust, EGLuint64KHR *msc, EGLuint64KHR *sbc)
585 {
586     return mImplementation->getSyncValues(ust, msc, sbc);
587 }
588 
getMscRate(EGLint * numerator,EGLint * denominator)589 Error Surface::getMscRate(EGLint *numerator, EGLint *denominator)
590 {
591     return mImplementation->getMscRate(numerator, denominator);
592 }
593 
releaseTexImageFromTexture(const gl::Context * context)594 Error Surface::releaseTexImageFromTexture(const gl::Context *context)
595 {
596     ASSERT(mTexture);
597     mTexture = nullptr;
598     return releaseRef(context->getDisplay());
599 }
600 
getAttachmentSize(const gl::ImageIndex &) const601 gl::Extents Surface::getAttachmentSize(const gl::ImageIndex & /*target*/) const
602 {
603     return gl::Extents(getWidth(), getHeight(), 1);
604 }
605 
getAttachmentFormat(GLenum binding,const gl::ImageIndex & target) const606 gl::Format Surface::getAttachmentFormat(GLenum binding, const gl::ImageIndex &target) const
607 {
608     return (binding == GL_BACK ? mColorFormat : mDSFormat);
609 }
610 
getAttachmentSamples(const gl::ImageIndex & target) const611 GLsizei Surface::getAttachmentSamples(const gl::ImageIndex &target) const
612 {
613     return getConfig()->samples;
614 }
615 
isRenderable(const gl::Context * context,GLenum binding,const gl::ImageIndex & imageIndex) const616 bool Surface::isRenderable(const gl::Context *context,
617                            GLenum binding,
618                            const gl::ImageIndex &imageIndex) const
619 {
620     return true;
621 }
622 
isYUV() const623 bool Surface::isYUV() const
624 {
625     // EGL_EXT_yuv_surface is not implemented.
626     return false;
627 }
628 
isExternalImageWithoutIndividualSync() const629 bool Surface::isExternalImageWithoutIndividualSync() const
630 {
631     return false;
632 }
633 
hasFrontBufferUsage() const634 bool Surface::hasFrontBufferUsage() const
635 {
636     return false;
637 }
638 
getId() const639 GLuint Surface::getId() const
640 {
641     return mState.id.value;
642 }
643 
getBufferAgeImpl(const gl::Context * context,EGLint * age) const644 Error Surface::getBufferAgeImpl(const gl::Context *context, EGLint *age) const
645 {
646     // When EGL_BUFFER_PRESERVED, the previous frame contents are copied to
647     // current frame, so the buffer age is always 1.
648     if (mState.swapBehavior == EGL_BUFFER_PRESERVED)
649     {
650         if (age != nullptr)
651         {
652             *age = 1;
653         }
654         return egl::NoError();
655     }
656     return mImplementation->getBufferAge(context, age);
657 }
658 
getBufferAge(const gl::Context * context,EGLint * age)659 Error Surface::getBufferAge(const gl::Context *context, EGLint *age)
660 {
661     Error err = getBufferAgeImpl(context, age);
662     if (!err.isError())
663     {
664         mBufferAgeQueriedSinceLastSwap = true;
665     }
666     return err;
667 }
668 
initState(GLenum binding,const gl::ImageIndex &) const669 gl::InitState Surface::initState(GLenum binding, const gl::ImageIndex & /*imageIndex*/) const
670 {
671     switch (binding)
672     {
673         case GL_BACK:
674             return mColorInitState;
675         case GL_DEPTH:
676         case GL_STENCIL:
677             return mDepthStencilInitState;
678         default:
679             UNREACHABLE();
680             return gl::InitState::Initialized;
681     }
682 }
683 
setInitState(GLenum binding,const gl::ImageIndex &,gl::InitState initState)684 void Surface::setInitState(GLenum binding,
685                            const gl::ImageIndex & /*imageIndex*/,
686                            gl::InitState initState)
687 {
688     switch (binding)
689     {
690         case GL_BACK:
691             mColorInitState = initState;
692             break;
693         case GL_DEPTH:
694         case GL_STENCIL:
695             mDepthStencilInitState = initState;
696             break;
697         default:
698             UNREACHABLE();
699             break;
700     }
701 }
702 
setTimestampsEnabled(bool enabled)703 void Surface::setTimestampsEnabled(bool enabled)
704 {
705     mImplementation->setTimestampsEnabled(enabled);
706     mState.timestampsEnabled = enabled;
707 }
708 
isTimestampsEnabled() const709 bool Surface::isTimestampsEnabled() const
710 {
711     return mState.timestampsEnabled;
712 }
713 
setAutoRefreshEnabled(bool enabled)714 Error Surface::setAutoRefreshEnabled(bool enabled)
715 {
716     ANGLE_TRY(mImplementation->setAutoRefreshEnabled(enabled));
717     mState.autoRefreshEnabled = enabled;
718     return NoError();
719 }
720 
hasProtectedContent() const721 bool Surface::hasProtectedContent() const
722 {
723     return mState.hasProtectedContent();
724 }
725 
getSupportedCompositorTimings() const726 const SupportedCompositorTiming &Surface::getSupportedCompositorTimings() const
727 {
728     return mState.supportedCompositorTimings;
729 }
730 
getCompositorTiming(EGLint numTimestamps,const EGLint * names,EGLnsecsANDROID * values) const731 Error Surface::getCompositorTiming(EGLint numTimestamps,
732                                    const EGLint *names,
733                                    EGLnsecsANDROID *values) const
734 {
735     return mImplementation->getCompositorTiming(numTimestamps, names, values);
736 }
737 
getNextFrameId(EGLuint64KHR * frameId) const738 Error Surface::getNextFrameId(EGLuint64KHR *frameId) const
739 {
740     return mImplementation->getNextFrameId(frameId);
741 }
742 
getSupportedTimestamps() const743 const SupportedTimestamps &Surface::getSupportedTimestamps() const
744 {
745     return mState.supportedTimestamps;
746 }
747 
getFrameTimestamps(EGLuint64KHR frameId,EGLint numTimestamps,const EGLint * timestamps,EGLnsecsANDROID * values) const748 Error Surface::getFrameTimestamps(EGLuint64KHR frameId,
749                                   EGLint numTimestamps,
750                                   const EGLint *timestamps,
751                                   EGLnsecsANDROID *values) const
752 {
753     return mImplementation->getFrameTimestamps(frameId, numTimestamps, timestamps, values);
754 }
755 
onSubjectStateChange(angle::SubjectIndex index,angle::SubjectMessage message)756 void Surface::onSubjectStateChange(angle::SubjectIndex index, angle::SubjectMessage message)
757 {
758     ASSERT(index == kSurfaceImplSubjectIndex);
759     switch (message)
760     {
761         case angle::SubjectMessage::SubjectChanged:
762             onStateChange(angle::SubjectMessage::ContentsChanged);
763             break;
764         case angle::SubjectMessage::SurfaceChanged:
765             onStateChange(angle::SubjectMessage::SurfaceChanged);
766             break;
767         case angle::SubjectMessage::SwapchainImageChanged:
768             onStateChange(angle::SubjectMessage::SwapchainImageChanged);
769             break;
770         default:
771             UNREACHABLE();
772             break;
773     }
774 }
775 
setRenderBuffer(EGLint renderBuffer)776 Error Surface::setRenderBuffer(EGLint renderBuffer)
777 {
778     ANGLE_TRY(mImplementation->setRenderBuffer(renderBuffer));
779     mRenderBuffer = renderBuffer;
780     return NoError();
781 }
782 
isLocked() const783 bool Surface::isLocked() const
784 {
785     return (mLockBufferPtr != nullptr);
786 }
787 
getBitmapPitch() const788 EGLint Surface::getBitmapPitch() const
789 {
790     return mLockBufferPitch;
791 }
792 
getBitmapOrigin() const793 EGLint Surface::getBitmapOrigin() const
794 {
795     return mImplementation->origin();
796 }
797 
getRedOffset() const798 EGLint Surface::getRedOffset() const
799 {
800     const gl::InternalFormat &format = *mColorFormat.info;
801     if (gl::IsBGRAFormat(format.internalFormat))
802     {
803         return format.blueBits + format.greenBits;
804     }
805     else
806     {
807         return 0;
808     }
809 }
810 
getGreenOffset() const811 EGLint Surface::getGreenOffset() const
812 {
813     const gl::InternalFormat &format = *mColorFormat.info;
814     if (gl::IsBGRAFormat(format.internalFormat))
815     {
816         return format.blueBits;
817     }
818     else
819     {
820         return format.redBits;
821     }
822 }
823 
getBlueOffset() const824 EGLint Surface::getBlueOffset() const
825 {
826     const gl::InternalFormat &format = *mColorFormat.info;
827     if (gl::IsBGRAFormat(format.internalFormat))
828     {
829         return 0;
830     }
831     else
832     {
833         return format.redBits + format.greenBits;
834     }
835 }
836 
getAlphaOffset() const837 EGLint Surface::getAlphaOffset() const
838 {
839     const gl::InternalFormat &format = *mColorFormat.info;
840     if (format.isLUMA())
841     {
842         return format.luminanceBits;  // Luma always first, alpha optional
843     }
844     // For RGBA/BGRA alpha is last
845     return format.blueBits + format.greenBits + format.redBits;
846 }
847 
getLuminanceOffset() const848 EGLint Surface::getLuminanceOffset() const
849 {
850     return 0;
851 }
852 
getBitmapPixelSize() const853 EGLint Surface::getBitmapPixelSize() const
854 {
855     constexpr EGLint kBitsPerByte    = 8;
856     const gl::InternalFormat &format = *mColorFormat.info;
857     return (format.pixelBytes * kBitsPerByte);
858 }
859 
getBitmapPointer() const860 EGLAttribKHR Surface::getBitmapPointer() const
861 {
862     return static_cast<EGLAttribKHR>((intptr_t)mLockBufferPtr);
863 }
864 
lockSurfaceKHR(const egl::Display * display,const AttributeMap & attributes)865 egl::Error Surface::lockSurfaceKHR(const egl::Display *display, const AttributeMap &attributes)
866 {
867     EGLint lockBufferUsageHint = attributes.getAsInt(
868         EGL_LOCK_USAGE_HINT_KHR, (EGL_READ_SURFACE_BIT_KHR | EGL_WRITE_SURFACE_BIT_KHR));
869 
870     bool preservePixels = ((attributes.getAsInt(EGL_MAP_PRESERVE_PIXELS_KHR, false) == EGL_TRUE) ||
871                            (mState.swapBehavior == EGL_BUFFER_PRESERVED));
872 
873     return mImplementation->lockSurface(display, lockBufferUsageHint, preservePixels,
874                                         &mLockBufferPtr, &mLockBufferPitch);
875 }
876 
unlockSurfaceKHR(const egl::Display * display)877 egl::Error Surface::unlockSurfaceKHR(const egl::Display *display)
878 {
879     mLockBufferPtr   = nullptr;
880     mLockBufferPitch = 0;
881     return mImplementation->unlockSurface(display, true);
882 }
883 
WindowSurface(rx::EGLImplFactory * implFactory,SurfaceID id,const egl::Config * config,EGLNativeWindowType window,const AttributeMap & attribs,bool robustResourceInit)884 WindowSurface::WindowSurface(rx::EGLImplFactory *implFactory,
885                              SurfaceID id,
886                              const egl::Config *config,
887                              EGLNativeWindowType window,
888                              const AttributeMap &attribs,
889                              bool robustResourceInit)
890     : Surface(EGL_WINDOW_BIT, id, config, attribs, robustResourceInit)
891 {
892     mImplementation = implFactory->createWindowSurface(mState, window, attribs);
893 }
894 
setDamageRegion(const EGLint * rects,EGLint n_rects)895 void Surface::setDamageRegion(const EGLint *rects, EGLint n_rects)
896 {
897     mIsDamageRegionSet = true;
898 }
899 
~WindowSurface()900 WindowSurface::~WindowSurface() {}
901 
PbufferSurface(rx::EGLImplFactory * implFactory,SurfaceID id,const Config * config,const AttributeMap & attribs,bool robustResourceInit)902 PbufferSurface::PbufferSurface(rx::EGLImplFactory *implFactory,
903                                SurfaceID id,
904                                const Config *config,
905                                const AttributeMap &attribs,
906                                bool robustResourceInit)
907     : Surface(EGL_PBUFFER_BIT, id, config, attribs, robustResourceInit)
908 {
909     mImplementation = implFactory->createPbufferSurface(mState, attribs);
910 }
911 
PbufferSurface(rx::EGLImplFactory * implFactory,SurfaceID id,const Config * config,EGLenum buftype,EGLClientBuffer clientBuffer,const AttributeMap & attribs,bool robustResourceInit)912 PbufferSurface::PbufferSurface(rx::EGLImplFactory *implFactory,
913                                SurfaceID id,
914                                const Config *config,
915                                EGLenum buftype,
916                                EGLClientBuffer clientBuffer,
917                                const AttributeMap &attribs,
918                                bool robustResourceInit)
919     : Surface(EGL_PBUFFER_BIT, id, config, attribs, robustResourceInit, buftype)
920 {
921     mImplementation =
922         implFactory->createPbufferFromClientBuffer(mState, buftype, clientBuffer, attribs);
923 }
924 
~PbufferSurface()925 PbufferSurface::~PbufferSurface() {}
926 
PixmapSurface(rx::EGLImplFactory * implFactory,SurfaceID id,const Config * config,NativePixmapType nativePixmap,const AttributeMap & attribs,bool robustResourceInit)927 PixmapSurface::PixmapSurface(rx::EGLImplFactory *implFactory,
928                              SurfaceID id,
929                              const Config *config,
930                              NativePixmapType nativePixmap,
931                              const AttributeMap &attribs,
932                              bool robustResourceInit)
933     : Surface(EGL_PIXMAP_BIT, id, config, attribs, robustResourceInit)
934 {
935     mImplementation = implFactory->createPixmapSurface(mState, nativePixmap, attribs);
936 }
937 
~PixmapSurface()938 PixmapSurface::~PixmapSurface() {}
939 
940 // SurfaceDeleter implementation.
941 
SurfaceDeleter(const Display * display)942 SurfaceDeleter::SurfaceDeleter(const Display *display) : mDisplay(display) {}
943 
~SurfaceDeleter()944 SurfaceDeleter::~SurfaceDeleter() {}
945 
operator ()(Surface * surface)946 void SurfaceDeleter::operator()(Surface *surface)
947 {
948     ANGLE_SWALLOW_ERR(surface->onDestroy(mDisplay));
949 }
950 
951 }  // namespace egl
952