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