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/Thread.h"
21 #include "libANGLE/formatutils.h"
22 #include "libANGLE/renderer/EGLImplFactory.h"
23 #include "libANGLE/trace.h"
24
25 namespace egl
26 {
27
SurfaceState(const egl::Config * configIn,const AttributeMap & attributesIn)28 SurfaceState::SurfaceState(const egl::Config *configIn, const AttributeMap &attributesIn)
29 : label(nullptr), config(configIn), attributes(attributesIn), timestampsEnabled(false)
30 {}
31
32 SurfaceState::~SurfaceState() = default;
33
Surface(EGLint surfaceType,const egl::Config * config,const AttributeMap & attributes,EGLenum buftype)34 Surface::Surface(EGLint surfaceType,
35 const egl::Config *config,
36 const AttributeMap &attributes,
37 EGLenum buftype)
38 : FramebufferAttachmentObject(),
39 mState(config, attributes),
40 mImplementation(nullptr),
41 mRefCount(0),
42 mDestroyed(false),
43 mType(surfaceType),
44 mBuftype(buftype),
45 mPostSubBufferRequested(false),
46 mLargestPbuffer(false),
47 mGLColorspace(EGL_GL_COLORSPACE_LINEAR),
48 mVGAlphaFormat(EGL_VG_ALPHA_FORMAT_NONPRE),
49 mVGColorspace(EGL_VG_COLORSPACE_sRGB),
50 mMipmapTexture(false),
51 mMipmapLevel(0),
52 mHorizontalResolution(EGL_UNKNOWN),
53 mVerticalResolution(EGL_UNKNOWN),
54 mMultisampleResolve(EGL_MULTISAMPLE_RESOLVE_DEFAULT),
55 mFixedSize(false),
56 mFixedWidth(0),
57 mFixedHeight(0),
58 mTextureFormat(TextureFormat::NoTexture),
59 mTextureTarget(EGL_NO_TEXTURE),
60 // FIXME: Determine actual pixel aspect ratio
61 mPixelAspectRatio(static_cast<EGLint>(1.0 * EGL_DISPLAY_SCALING)),
62 mRenderBuffer(EGL_BACK_BUFFER),
63 mSwapBehavior(EGL_NONE),
64 mOrientation(0),
65 mTexture(nullptr),
66 mColorFormat(config->renderTargetFormat),
67 mDSFormat(config->depthStencilFormat),
68 mInitState(gl::InitState::Initialized)
69 {
70 mPostSubBufferRequested =
71 (attributes.get(EGL_POST_SUB_BUFFER_SUPPORTED_NV, EGL_FALSE) == EGL_TRUE);
72 mFlexibleSurfaceCompatibilityRequested =
73 (attributes.get(EGL_FLEXIBLE_SURFACE_COMPATIBILITY_SUPPORTED_ANGLE, EGL_FALSE) == EGL_TRUE);
74
75 if (mType == EGL_PBUFFER_BIT)
76 {
77 mLargestPbuffer = (attributes.get(EGL_LARGEST_PBUFFER, EGL_FALSE) == EGL_TRUE);
78 }
79
80 mGLColorspace =
81 static_cast<EGLenum>(attributes.get(EGL_GL_COLORSPACE, EGL_GL_COLORSPACE_LINEAR));
82 mVGAlphaFormat =
83 static_cast<EGLenum>(attributes.get(EGL_VG_ALPHA_FORMAT, EGL_VG_ALPHA_FORMAT_NONPRE));
84 mVGColorspace = static_cast<EGLenum>(attributes.get(EGL_VG_COLORSPACE, EGL_VG_COLORSPACE_sRGB));
85 mMipmapTexture = (attributes.get(EGL_MIPMAP_TEXTURE, EGL_FALSE) == EGL_TRUE);
86
87 mDirectComposition = (attributes.get(EGL_DIRECT_COMPOSITION_ANGLE, EGL_FALSE) == EGL_TRUE);
88
89 mRobustResourceInitialization =
90 (attributes.get(EGL_ROBUST_RESOURCE_INITIALIZATION_ANGLE, EGL_FALSE) == EGL_TRUE);
91 if (mRobustResourceInitialization)
92 {
93 mInitState = gl::InitState::MayNeedInit;
94 }
95
96 mFixedSize = (attributes.get(EGL_FIXED_SIZE_ANGLE, EGL_FALSE) == EGL_TRUE);
97 if (mFixedSize)
98 {
99 mFixedWidth = static_cast<size_t>(attributes.get(EGL_WIDTH, 0));
100 mFixedHeight = static_cast<size_t>(attributes.get(EGL_HEIGHT, 0));
101 }
102
103 if (mType != EGL_WINDOW_BIT)
104 {
105 mTextureFormat = attributes.getAsPackedEnum(EGL_TEXTURE_FORMAT, TextureFormat::NoTexture);
106 mTextureTarget = static_cast<EGLenum>(attributes.get(EGL_TEXTURE_TARGET, EGL_NO_TEXTURE));
107 }
108
109 mOrientation = static_cast<EGLint>(attributes.get(EGL_SURFACE_ORIENTATION_ANGLE, 0));
110 }
111
~Surface()112 Surface::~Surface() {}
113
getAttachmentImpl() const114 rx::FramebufferAttachmentObjectImpl *Surface::getAttachmentImpl() const
115 {
116 return mImplementation;
117 }
118
destroyImpl(const Display * display)119 Error Surface::destroyImpl(const Display *display)
120 {
121 if (mImplementation)
122 {
123 mImplementation->destroy(display);
124 }
125
126 ASSERT(!mTexture);
127
128 SafeDelete(mImplementation);
129
130 delete this;
131 return NoError();
132 }
133
postSwap(const gl::Context * context)134 void Surface::postSwap(const gl::Context *context)
135 {
136 if (mRobustResourceInitialization && mSwapBehavior != EGL_BUFFER_PRESERVED)
137 {
138 mInitState = gl::InitState::MayNeedInit;
139 onStateChange(angle::SubjectMessage::SubjectChanged);
140 }
141
142 context->onPostSwap();
143 }
144
initialize(const Display * display)145 Error Surface::initialize(const Display *display)
146 {
147 ANGLE_TRY(mImplementation->initialize(display));
148
149 // Initialized here since impl is nullptr in the constructor.
150 // Must happen after implementation initialize for Android.
151 mSwapBehavior = mImplementation->getSwapBehavior();
152
153 if (mBuftype == EGL_IOSURFACE_ANGLE)
154 {
155 GLenum internalFormat =
156 static_cast<GLenum>(mState.attributes.get(EGL_TEXTURE_INTERNAL_FORMAT_ANGLE));
157 GLenum type = static_cast<GLenum>(mState.attributes.get(EGL_TEXTURE_TYPE_ANGLE));
158 mColorFormat = gl::Format(internalFormat, type);
159 }
160 if (mBuftype == EGL_D3D_TEXTURE_ANGLE)
161 {
162 const angle::Format *colorFormat = mImplementation->getD3DTextureColorFormat();
163 ASSERT(colorFormat != nullptr);
164 GLenum internalFormat = colorFormat->fboImplementationInternalFormat;
165 mColorFormat = gl::Format(internalFormat, colorFormat->componentType);
166 mGLColorspace = EGL_GL_COLORSPACE_LINEAR;
167 if (mColorFormat.info->colorEncoding == GL_SRGB)
168 {
169 mGLColorspace = EGL_GL_COLORSPACE_SRGB;
170 }
171 }
172
173 if (mType == EGL_WINDOW_BIT && display->getExtensions().getFrameTimestamps)
174 {
175 mState.supportedCompositorTimings = mImplementation->getSupportedCompositorTimings();
176 mState.supportedTimestamps = mImplementation->getSupportedTimestamps();
177 }
178
179 return NoError();
180 }
181
makeCurrent(const gl::Context * context)182 Error Surface::makeCurrent(const gl::Context *context)
183 {
184 ANGLE_TRY(mImplementation->makeCurrent(context));
185
186 mRefCount++;
187 return NoError();
188 }
189
unMakeCurrent(const gl::Context * context)190 Error Surface::unMakeCurrent(const gl::Context *context)
191 {
192 ANGLE_TRY(mImplementation->unMakeCurrent(context));
193 return releaseRef(context->getDisplay());
194 }
195
releaseRef(const Display * display)196 Error Surface::releaseRef(const Display *display)
197 {
198 ASSERT(mRefCount > 0);
199 mRefCount--;
200 if (mRefCount == 0 && mDestroyed)
201 {
202 ASSERT(display);
203 return destroyImpl(display);
204 }
205
206 return NoError();
207 }
208
onDestroy(const Display * display)209 Error Surface::onDestroy(const Display *display)
210 {
211 mDestroyed = true;
212 if (mRefCount == 0)
213 {
214 return destroyImpl(display);
215 }
216 return NoError();
217 }
218
setLabel(EGLLabelKHR label)219 void Surface::setLabel(EGLLabelKHR label)
220 {
221 mState.label = label;
222 }
223
getLabel() const224 EGLLabelKHR Surface::getLabel() const
225 {
226 return mState.label;
227 }
228
getType() const229 EGLint Surface::getType() const
230 {
231 return mType;
232 }
233
swap(const gl::Context * context)234 Error Surface::swap(const gl::Context *context)
235 {
236 ANGLE_TRACE_EVENT0("gpu.angle", "egl::Surface::swap");
237
238 ANGLE_TRY(mImplementation->swap(context));
239 postSwap(context);
240 return NoError();
241 }
242
swapWithDamage(const gl::Context * context,EGLint * rects,EGLint n_rects)243 Error Surface::swapWithDamage(const gl::Context *context, EGLint *rects, EGLint n_rects)
244 {
245 ANGLE_TRY(mImplementation->swapWithDamage(context, rects, n_rects));
246 postSwap(context);
247 return NoError();
248 }
249
postSubBuffer(const gl::Context * context,EGLint x,EGLint y,EGLint width,EGLint height)250 Error Surface::postSubBuffer(const gl::Context *context,
251 EGLint x,
252 EGLint y,
253 EGLint width,
254 EGLint height)
255 {
256 if (width == 0 || height == 0)
257 {
258 return egl::NoError();
259 }
260
261 ANGLE_TRY(mImplementation->postSubBuffer(context, x, y, width, height));
262 postSwap(context);
263 return NoError();
264 }
265
setPresentationTime(EGLnsecsANDROID time)266 Error Surface::setPresentationTime(EGLnsecsANDROID time)
267 {
268 return mImplementation->setPresentationTime(time);
269 }
270
querySurfacePointerANGLE(EGLint attribute,void ** value)271 Error Surface::querySurfacePointerANGLE(EGLint attribute, void **value)
272 {
273 return mImplementation->querySurfacePointerANGLE(attribute, value);
274 }
275
isPostSubBufferSupported() const276 EGLint Surface::isPostSubBufferSupported() const
277 {
278 return mPostSubBufferRequested && mImplementation->isPostSubBufferSupported();
279 }
280
setSwapInterval(EGLint interval)281 void Surface::setSwapInterval(EGLint interval)
282 {
283 mImplementation->setSwapInterval(interval);
284 }
285
setMipmapLevel(EGLint level)286 void Surface::setMipmapLevel(EGLint level)
287 {
288 // Level is set but ignored
289 UNIMPLEMENTED();
290 mMipmapLevel = level;
291 }
292
setMultisampleResolve(EGLenum resolve)293 void Surface::setMultisampleResolve(EGLenum resolve)
294 {
295 // Behaviour is set but ignored
296 UNIMPLEMENTED();
297 mMultisampleResolve = resolve;
298 }
299
setSwapBehavior(EGLenum behavior)300 void Surface::setSwapBehavior(EGLenum behavior)
301 {
302 // Behaviour is set but ignored
303 UNIMPLEMENTED();
304 mSwapBehavior = behavior;
305 }
306
setFixedWidth(EGLint width)307 void Surface::setFixedWidth(EGLint width)
308 {
309 mFixedWidth = width;
310 mImplementation->setFixedWidth(width);
311 }
312
setFixedHeight(EGLint height)313 void Surface::setFixedHeight(EGLint height)
314 {
315 mFixedHeight = height;
316 mImplementation->setFixedHeight(height);
317 }
318
getConfig() const319 const Config *Surface::getConfig() const
320 {
321 return mState.config;
322 }
323
getPixelAspectRatio() const324 EGLint Surface::getPixelAspectRatio() const
325 {
326 return mPixelAspectRatio;
327 }
328
getRenderBuffer() const329 EGLenum Surface::getRenderBuffer() const
330 {
331 return mRenderBuffer;
332 }
333
getSwapBehavior() const334 EGLenum Surface::getSwapBehavior() const
335 {
336 return mSwapBehavior;
337 }
338
getTextureFormat() const339 TextureFormat Surface::getTextureFormat() const
340 {
341 return mTextureFormat;
342 }
343
getTextureTarget() const344 EGLenum Surface::getTextureTarget() const
345 {
346 return mTextureTarget;
347 }
348
getLargestPbuffer() const349 bool Surface::getLargestPbuffer() const
350 {
351 return mLargestPbuffer;
352 }
353
getGLColorspace() const354 EGLenum Surface::getGLColorspace() const
355 {
356 return mGLColorspace;
357 }
358
getVGAlphaFormat() const359 EGLenum Surface::getVGAlphaFormat() const
360 {
361 return mVGAlphaFormat;
362 }
363
getVGColorspace() const364 EGLenum Surface::getVGColorspace() const
365 {
366 return mVGColorspace;
367 }
368
getMipmapTexture() const369 bool Surface::getMipmapTexture() const
370 {
371 return mMipmapTexture;
372 }
373
getMipmapLevel() const374 EGLint Surface::getMipmapLevel() const
375 {
376 return mMipmapLevel;
377 }
378
getHorizontalResolution() const379 EGLint Surface::getHorizontalResolution() const
380 {
381 return mHorizontalResolution;
382 }
383
getVerticalResolution() const384 EGLint Surface::getVerticalResolution() const
385 {
386 return mVerticalResolution;
387 }
388
getMultisampleResolve() const389 EGLenum Surface::getMultisampleResolve() const
390 {
391 return mMultisampleResolve;
392 }
393
isFixedSize() const394 EGLint Surface::isFixedSize() const
395 {
396 return mFixedSize;
397 }
398
getWidth() const399 EGLint Surface::getWidth() const
400 {
401 return mFixedSize ? static_cast<EGLint>(mFixedWidth) : mImplementation->getWidth();
402 }
403
getHeight() const404 EGLint Surface::getHeight() const
405 {
406 return mFixedSize ? static_cast<EGLint>(mFixedHeight) : mImplementation->getHeight();
407 }
408
bindTexImage(gl::Context * context,gl::Texture * texture,EGLint buffer)409 Error Surface::bindTexImage(gl::Context *context, gl::Texture *texture, EGLint buffer)
410 {
411 ASSERT(!mTexture);
412 ANGLE_TRY(mImplementation->bindTexImage(context, texture, buffer));
413
414 if (texture->bindTexImageFromSurface(context, this) == angle::Result::Stop)
415 {
416 return Error(EGL_BAD_SURFACE);
417 }
418 mTexture = texture;
419 mRefCount++;
420
421 return NoError();
422 }
423
releaseTexImage(const gl::Context * context,EGLint buffer)424 Error Surface::releaseTexImage(const gl::Context *context, EGLint buffer)
425 {
426 ASSERT(context);
427
428 ANGLE_TRY(mImplementation->releaseTexImage(context, buffer));
429
430 ASSERT(mTexture);
431 ANGLE_TRY(ResultToEGL(mTexture->releaseTexImageFromSurface(context)));
432
433 return releaseTexImageFromTexture(context);
434 }
435
getSyncValues(EGLuint64KHR * ust,EGLuint64KHR * msc,EGLuint64KHR * sbc)436 Error Surface::getSyncValues(EGLuint64KHR *ust, EGLuint64KHR *msc, EGLuint64KHR *sbc)
437 {
438 return mImplementation->getSyncValues(ust, msc, sbc);
439 }
440
releaseTexImageFromTexture(const gl::Context * context)441 Error Surface::releaseTexImageFromTexture(const gl::Context *context)
442 {
443 ASSERT(mTexture);
444 mTexture = nullptr;
445 return releaseRef(context->getDisplay());
446 }
447
getAttachmentSize(const gl::ImageIndex &) const448 gl::Extents Surface::getAttachmentSize(const gl::ImageIndex & /*target*/) const
449 {
450 return gl::Extents(getWidth(), getHeight(), 1);
451 }
452
getAttachmentFormat(GLenum binding,const gl::ImageIndex & target) const453 gl::Format Surface::getAttachmentFormat(GLenum binding, const gl::ImageIndex &target) const
454 {
455 return (binding == GL_BACK ? mColorFormat : mDSFormat);
456 }
457
getAttachmentSamples(const gl::ImageIndex & target) const458 GLsizei Surface::getAttachmentSamples(const gl::ImageIndex &target) const
459 {
460 return getConfig()->samples;
461 }
462
isRenderable(const gl::Context * context,GLenum binding,const gl::ImageIndex & imageIndex) const463 bool Surface::isRenderable(const gl::Context *context,
464 GLenum binding,
465 const gl::ImageIndex &imageIndex) const
466 {
467 return true;
468 }
469
getId() const470 GLuint Surface::getId() const
471 {
472 UNREACHABLE();
473 return 0;
474 }
475
createDefaultFramebuffer(const gl::Context * context)476 gl::Framebuffer *Surface::createDefaultFramebuffer(const gl::Context *context)
477 {
478 return new gl::Framebuffer(context, this);
479 }
480
initState(const gl::ImageIndex &) const481 gl::InitState Surface::initState(const gl::ImageIndex & /*imageIndex*/) const
482 {
483 return mInitState;
484 }
485
setInitState(const gl::ImageIndex &,gl::InitState initState)486 void Surface::setInitState(const gl::ImageIndex & /*imageIndex*/, gl::InitState initState)
487 {
488 mInitState = initState;
489 }
490
setTimestampsEnabled(bool enabled)491 void Surface::setTimestampsEnabled(bool enabled)
492 {
493 mImplementation->setTimestampsEnabled(enabled);
494 mState.timestampsEnabled = enabled;
495 }
496
isTimestampsEnabled() const497 bool Surface::isTimestampsEnabled() const
498 {
499 return mState.timestampsEnabled;
500 }
501
getSupportedCompositorTimings() const502 const SupportedCompositorTiming &Surface::getSupportedCompositorTimings() const
503 {
504 return mState.supportedCompositorTimings;
505 }
506
getCompositorTiming(EGLint numTimestamps,const EGLint * names,EGLnsecsANDROID * values) const507 Error Surface::getCompositorTiming(EGLint numTimestamps,
508 const EGLint *names,
509 EGLnsecsANDROID *values) const
510 {
511 return mImplementation->getCompositorTiming(numTimestamps, names, values);
512 }
513
getNextFrameId(EGLuint64KHR * frameId) const514 Error Surface::getNextFrameId(EGLuint64KHR *frameId) const
515 {
516 return mImplementation->getNextFrameId(frameId);
517 }
518
getSupportedTimestamps() const519 const SupportedTimestamps &Surface::getSupportedTimestamps() const
520 {
521 return mState.supportedTimestamps;
522 }
523
getFrameTimestamps(EGLuint64KHR frameId,EGLint numTimestamps,const EGLint * timestamps,EGLnsecsANDROID * values) const524 Error Surface::getFrameTimestamps(EGLuint64KHR frameId,
525 EGLint numTimestamps,
526 const EGLint *timestamps,
527 EGLnsecsANDROID *values) const
528 {
529 return mImplementation->getFrameTimestamps(frameId, numTimestamps, timestamps, values);
530 }
531
WindowSurface(rx::EGLImplFactory * implFactory,const egl::Config * config,EGLNativeWindowType window,const AttributeMap & attribs)532 WindowSurface::WindowSurface(rx::EGLImplFactory *implFactory,
533 const egl::Config *config,
534 EGLNativeWindowType window,
535 const AttributeMap &attribs)
536 : Surface(EGL_WINDOW_BIT, config, attribs)
537 {
538 mImplementation = implFactory->createWindowSurface(mState, window, attribs);
539 }
540
~WindowSurface()541 WindowSurface::~WindowSurface() {}
542
PbufferSurface(rx::EGLImplFactory * implFactory,const Config * config,const AttributeMap & attribs)543 PbufferSurface::PbufferSurface(rx::EGLImplFactory *implFactory,
544 const Config *config,
545 const AttributeMap &attribs)
546 : Surface(EGL_PBUFFER_BIT, config, attribs)
547 {
548 mImplementation = implFactory->createPbufferSurface(mState, attribs);
549 }
550
PbufferSurface(rx::EGLImplFactory * implFactory,const Config * config,EGLenum buftype,EGLClientBuffer clientBuffer,const AttributeMap & attribs)551 PbufferSurface::PbufferSurface(rx::EGLImplFactory *implFactory,
552 const Config *config,
553 EGLenum buftype,
554 EGLClientBuffer clientBuffer,
555 const AttributeMap &attribs)
556 : Surface(EGL_PBUFFER_BIT, config, attribs, buftype)
557 {
558 mImplementation =
559 implFactory->createPbufferFromClientBuffer(mState, buftype, clientBuffer, attribs);
560 }
561
~PbufferSurface()562 PbufferSurface::~PbufferSurface() {}
563
PixmapSurface(rx::EGLImplFactory * implFactory,const Config * config,NativePixmapType nativePixmap,const AttributeMap & attribs)564 PixmapSurface::PixmapSurface(rx::EGLImplFactory *implFactory,
565 const Config *config,
566 NativePixmapType nativePixmap,
567 const AttributeMap &attribs)
568 : Surface(EGL_PIXMAP_BIT, config, attribs)
569 {
570 mImplementation = implFactory->createPixmapSurface(mState, nativePixmap, attribs);
571 }
572
~PixmapSurface()573 PixmapSurface::~PixmapSurface() {}
574
575 // SurfaceDeleter implementation.
576
SurfaceDeleter(const Display * display)577 SurfaceDeleter::SurfaceDeleter(const Display *display) : mDisplay(display) {}
578
~SurfaceDeleter()579 SurfaceDeleter::~SurfaceDeleter() {}
580
operator ()(Surface * surface)581 void SurfaceDeleter::operator()(Surface *surface)
582 {
583 ANGLE_SWALLOW_ERR(surface->onDestroy(mDisplay));
584 }
585
586 } // namespace egl
587