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(EGLint interval)399 void Surface::setSwapInterval(EGLint interval)
400 {
401 mImplementation->setSwapInterval(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
558 if (texture->bindTexImageFromSurface(context, this) == angle::Result::Stop)
559 {
560 return Error(EGL_BAD_SURFACE);
561 }
562 mTexture = texture;
563 addRef();
564
565 return NoError();
566 }
567
releaseTexImage(const gl::Context * context,EGLint buffer)568 Error Surface::releaseTexImage(const gl::Context *context, EGLint buffer)
569 {
570 ASSERT(context);
571
572 ANGLE_TRY(mImplementation->releaseTexImage(context, buffer));
573
574 ASSERT(mTexture);
575 ANGLE_TRY(ResultToEGL(mTexture->releaseTexImageFromSurface(context)));
576
577 return releaseTexImageFromTexture(context);
578 }
579
getSyncValues(EGLuint64KHR * ust,EGLuint64KHR * msc,EGLuint64KHR * sbc)580 Error Surface::getSyncValues(EGLuint64KHR *ust, EGLuint64KHR *msc, EGLuint64KHR *sbc)
581 {
582 return mImplementation->getSyncValues(ust, msc, sbc);
583 }
584
getMscRate(EGLint * numerator,EGLint * denominator)585 Error Surface::getMscRate(EGLint *numerator, EGLint *denominator)
586 {
587 return mImplementation->getMscRate(numerator, denominator);
588 }
589
releaseTexImageFromTexture(const gl::Context * context)590 Error Surface::releaseTexImageFromTexture(const gl::Context *context)
591 {
592 ASSERT(mTexture);
593 mTexture = nullptr;
594 return releaseRef(context->getDisplay());
595 }
596
getAttachmentSize(const gl::ImageIndex &) const597 gl::Extents Surface::getAttachmentSize(const gl::ImageIndex & /*target*/) const
598 {
599 return gl::Extents(getWidth(), getHeight(), 1);
600 }
601
getAttachmentFormat(GLenum binding,const gl::ImageIndex & target) const602 gl::Format Surface::getAttachmentFormat(GLenum binding, const gl::ImageIndex &target) const
603 {
604 return (binding == GL_BACK ? mColorFormat : mDSFormat);
605 }
606
getAttachmentSamples(const gl::ImageIndex & target) const607 GLsizei Surface::getAttachmentSamples(const gl::ImageIndex &target) const
608 {
609 return getConfig()->samples;
610 }
611
isRenderable(const gl::Context * context,GLenum binding,const gl::ImageIndex & imageIndex) const612 bool Surface::isRenderable(const gl::Context *context,
613 GLenum binding,
614 const gl::ImageIndex &imageIndex) const
615 {
616 return true;
617 }
618
isYUV() const619 bool Surface::isYUV() const
620 {
621 // EGL_EXT_yuv_surface is not implemented.
622 return false;
623 }
624
isExternalImageWithoutIndividualSync() const625 bool Surface::isExternalImageWithoutIndividualSync() const
626 {
627 return false;
628 }
629
hasFrontBufferUsage() const630 bool Surface::hasFrontBufferUsage() const
631 {
632 return false;
633 }
634
getId() const635 GLuint Surface::getId() const
636 {
637 return mState.id.value;
638 }
639
getBufferAgeImpl(const gl::Context * context,EGLint * age) const640 Error Surface::getBufferAgeImpl(const gl::Context *context, EGLint *age) const
641 {
642 // When EGL_BUFFER_PRESERVED, the previous frame contents are copied to
643 // current frame, so the buffer age is always 1.
644 if (mState.swapBehavior == EGL_BUFFER_PRESERVED)
645 {
646 if (age != nullptr)
647 {
648 *age = 1;
649 }
650 return egl::NoError();
651 }
652 return mImplementation->getBufferAge(context, age);
653 }
654
getBufferAge(const gl::Context * context,EGLint * age)655 Error Surface::getBufferAge(const gl::Context *context, EGLint *age)
656 {
657 Error err = getBufferAgeImpl(context, age);
658 if (!err.isError())
659 {
660 mBufferAgeQueriedSinceLastSwap = true;
661 }
662 return err;
663 }
664
initState(GLenum binding,const gl::ImageIndex &) const665 gl::InitState Surface::initState(GLenum binding, const gl::ImageIndex & /*imageIndex*/) const
666 {
667 switch (binding)
668 {
669 case GL_BACK:
670 return mColorInitState;
671 case GL_DEPTH:
672 case GL_STENCIL:
673 return mDepthStencilInitState;
674 default:
675 UNREACHABLE();
676 return gl::InitState::Initialized;
677 }
678 }
679
setInitState(GLenum binding,const gl::ImageIndex &,gl::InitState initState)680 void Surface::setInitState(GLenum binding,
681 const gl::ImageIndex & /*imageIndex*/,
682 gl::InitState initState)
683 {
684 switch (binding)
685 {
686 case GL_BACK:
687 mColorInitState = initState;
688 break;
689 case GL_DEPTH:
690 case GL_STENCIL:
691 mDepthStencilInitState = initState;
692 break;
693 default:
694 UNREACHABLE();
695 break;
696 }
697 }
698
setTimestampsEnabled(bool enabled)699 void Surface::setTimestampsEnabled(bool enabled)
700 {
701 mImplementation->setTimestampsEnabled(enabled);
702 mState.timestampsEnabled = enabled;
703 }
704
isTimestampsEnabled() const705 bool Surface::isTimestampsEnabled() const
706 {
707 return mState.timestampsEnabled;
708 }
709
setAutoRefreshEnabled(bool enabled)710 Error Surface::setAutoRefreshEnabled(bool enabled)
711 {
712 ANGLE_TRY(mImplementation->setAutoRefreshEnabled(enabled));
713 mState.autoRefreshEnabled = enabled;
714 return NoError();
715 }
716
hasProtectedContent() const717 bool Surface::hasProtectedContent() const
718 {
719 return mState.hasProtectedContent();
720 }
721
getSupportedCompositorTimings() const722 const SupportedCompositorTiming &Surface::getSupportedCompositorTimings() const
723 {
724 return mState.supportedCompositorTimings;
725 }
726
getCompositorTiming(EGLint numTimestamps,const EGLint * names,EGLnsecsANDROID * values) const727 Error Surface::getCompositorTiming(EGLint numTimestamps,
728 const EGLint *names,
729 EGLnsecsANDROID *values) const
730 {
731 return mImplementation->getCompositorTiming(numTimestamps, names, values);
732 }
733
getNextFrameId(EGLuint64KHR * frameId) const734 Error Surface::getNextFrameId(EGLuint64KHR *frameId) const
735 {
736 return mImplementation->getNextFrameId(frameId);
737 }
738
getSupportedTimestamps() const739 const SupportedTimestamps &Surface::getSupportedTimestamps() const
740 {
741 return mState.supportedTimestamps;
742 }
743
getFrameTimestamps(EGLuint64KHR frameId,EGLint numTimestamps,const EGLint * timestamps,EGLnsecsANDROID * values) const744 Error Surface::getFrameTimestamps(EGLuint64KHR frameId,
745 EGLint numTimestamps,
746 const EGLint *timestamps,
747 EGLnsecsANDROID *values) const
748 {
749 return mImplementation->getFrameTimestamps(frameId, numTimestamps, timestamps, values);
750 }
751
onSubjectStateChange(angle::SubjectIndex index,angle::SubjectMessage message)752 void Surface::onSubjectStateChange(angle::SubjectIndex index, angle::SubjectMessage message)
753 {
754 ASSERT(index == kSurfaceImplSubjectIndex);
755 switch (message)
756 {
757 case angle::SubjectMessage::SubjectChanged:
758 onStateChange(angle::SubjectMessage::ContentsChanged);
759 break;
760 case angle::SubjectMessage::SurfaceChanged:
761 onStateChange(angle::SubjectMessage::SurfaceChanged);
762 break;
763 case angle::SubjectMessage::SwapchainImageChanged:
764 onStateChange(angle::SubjectMessage::SwapchainImageChanged);
765 break;
766 default:
767 UNREACHABLE();
768 break;
769 }
770 }
771
setRenderBuffer(EGLint renderBuffer)772 Error Surface::setRenderBuffer(EGLint renderBuffer)
773 {
774 ANGLE_TRY(mImplementation->setRenderBuffer(renderBuffer));
775 mRenderBuffer = renderBuffer;
776 return NoError();
777 }
778
isLocked() const779 bool Surface::isLocked() const
780 {
781 return (mLockBufferPtr != nullptr);
782 }
783
getBitmapPitch() const784 EGLint Surface::getBitmapPitch() const
785 {
786 return mLockBufferPitch;
787 }
788
getBitmapOrigin() const789 EGLint Surface::getBitmapOrigin() const
790 {
791 return mImplementation->origin();
792 }
793
getRedOffset() const794 EGLint Surface::getRedOffset() const
795 {
796 const gl::InternalFormat &format = *mColorFormat.info;
797 if (gl::IsBGRAFormat(format.internalFormat))
798 {
799 return format.blueBits + format.greenBits;
800 }
801 else
802 {
803 return 0;
804 }
805 }
806
getGreenOffset() const807 EGLint Surface::getGreenOffset() const
808 {
809 const gl::InternalFormat &format = *mColorFormat.info;
810 if (gl::IsBGRAFormat(format.internalFormat))
811 {
812 return format.blueBits;
813 }
814 else
815 {
816 return format.redBits;
817 }
818 }
819
getBlueOffset() const820 EGLint Surface::getBlueOffset() const
821 {
822 const gl::InternalFormat &format = *mColorFormat.info;
823 if (gl::IsBGRAFormat(format.internalFormat))
824 {
825 return 0;
826 }
827 else
828 {
829 return format.redBits + format.greenBits;
830 }
831 }
832
getAlphaOffset() const833 EGLint Surface::getAlphaOffset() const
834 {
835 const gl::InternalFormat &format = *mColorFormat.info;
836 if (format.isLUMA())
837 {
838 return format.luminanceBits; // Luma always first, alpha optional
839 }
840 // For RGBA/BGRA alpha is last
841 return format.blueBits + format.greenBits + format.redBits;
842 }
843
getLuminanceOffset() const844 EGLint Surface::getLuminanceOffset() const
845 {
846 return 0;
847 }
848
getBitmapPixelSize() const849 EGLint Surface::getBitmapPixelSize() const
850 {
851 constexpr EGLint kBitsPerByte = 8;
852 const gl::InternalFormat &format = *mColorFormat.info;
853 return (format.pixelBytes * kBitsPerByte);
854 }
855
getBitmapPointer() const856 EGLAttribKHR Surface::getBitmapPointer() const
857 {
858 return static_cast<EGLAttribKHR>((intptr_t)mLockBufferPtr);
859 }
860
lockSurfaceKHR(const egl::Display * display,const AttributeMap & attributes)861 egl::Error Surface::lockSurfaceKHR(const egl::Display *display, const AttributeMap &attributes)
862 {
863 EGLint lockBufferUsageHint = attributes.getAsInt(
864 EGL_LOCK_USAGE_HINT_KHR, (EGL_READ_SURFACE_BIT_KHR | EGL_WRITE_SURFACE_BIT_KHR));
865
866 bool preservePixels = ((attributes.getAsInt(EGL_MAP_PRESERVE_PIXELS_KHR, false) == EGL_TRUE) ||
867 (mState.swapBehavior == EGL_BUFFER_PRESERVED));
868
869 return mImplementation->lockSurface(display, lockBufferUsageHint, preservePixels,
870 &mLockBufferPtr, &mLockBufferPitch);
871 }
872
unlockSurfaceKHR(const egl::Display * display)873 egl::Error Surface::unlockSurfaceKHR(const egl::Display *display)
874 {
875 mLockBufferPtr = nullptr;
876 mLockBufferPitch = 0;
877 return mImplementation->unlockSurface(display, true);
878 }
879
WindowSurface(rx::EGLImplFactory * implFactory,SurfaceID id,const egl::Config * config,EGLNativeWindowType window,const AttributeMap & attribs,bool robustResourceInit)880 WindowSurface::WindowSurface(rx::EGLImplFactory *implFactory,
881 SurfaceID id,
882 const egl::Config *config,
883 EGLNativeWindowType window,
884 const AttributeMap &attribs,
885 bool robustResourceInit)
886 : Surface(EGL_WINDOW_BIT, id, config, attribs, robustResourceInit)
887 {
888 mImplementation = implFactory->createWindowSurface(mState, window, attribs);
889 }
890
setDamageRegion(const EGLint * rects,EGLint n_rects)891 void Surface::setDamageRegion(const EGLint *rects, EGLint n_rects)
892 {
893 mIsDamageRegionSet = true;
894 }
895
~WindowSurface()896 WindowSurface::~WindowSurface() {}
897
PbufferSurface(rx::EGLImplFactory * implFactory,SurfaceID id,const Config * config,const AttributeMap & attribs,bool robustResourceInit)898 PbufferSurface::PbufferSurface(rx::EGLImplFactory *implFactory,
899 SurfaceID id,
900 const Config *config,
901 const AttributeMap &attribs,
902 bool robustResourceInit)
903 : Surface(EGL_PBUFFER_BIT, id, config, attribs, robustResourceInit)
904 {
905 mImplementation = implFactory->createPbufferSurface(mState, attribs);
906 }
907
PbufferSurface(rx::EGLImplFactory * implFactory,SurfaceID id,const Config * config,EGLenum buftype,EGLClientBuffer clientBuffer,const AttributeMap & attribs,bool robustResourceInit)908 PbufferSurface::PbufferSurface(rx::EGLImplFactory *implFactory,
909 SurfaceID id,
910 const Config *config,
911 EGLenum buftype,
912 EGLClientBuffer clientBuffer,
913 const AttributeMap &attribs,
914 bool robustResourceInit)
915 : Surface(EGL_PBUFFER_BIT, id, config, attribs, robustResourceInit, buftype)
916 {
917 mImplementation =
918 implFactory->createPbufferFromClientBuffer(mState, buftype, clientBuffer, attribs);
919 }
920
~PbufferSurface()921 PbufferSurface::~PbufferSurface() {}
922
PixmapSurface(rx::EGLImplFactory * implFactory,SurfaceID id,const Config * config,NativePixmapType nativePixmap,const AttributeMap & attribs,bool robustResourceInit)923 PixmapSurface::PixmapSurface(rx::EGLImplFactory *implFactory,
924 SurfaceID id,
925 const Config *config,
926 NativePixmapType nativePixmap,
927 const AttributeMap &attribs,
928 bool robustResourceInit)
929 : Surface(EGL_PIXMAP_BIT, id, config, attribs, robustResourceInit)
930 {
931 mImplementation = implFactory->createPixmapSurface(mState, nativePixmap, attribs);
932 }
933
~PixmapSurface()934 PixmapSurface::~PixmapSurface() {}
935
936 // SurfaceDeleter implementation.
937
SurfaceDeleter(const Display * display)938 SurfaceDeleter::SurfaceDeleter(const Display *display) : mDisplay(display) {}
939
~SurfaceDeleter()940 SurfaceDeleter::~SurfaceDeleter() {}
941
operator ()(Surface * surface)942 void SurfaceDeleter::operator()(Surface *surface)
943 {
944 ANGLE_SWALLOW_ERR(surface->onDestroy(mDisplay));
945 }
946
947 } // namespace egl
948