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