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