1 //
2 // Copyright (c) 2002-2014 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 <iostream>
16
17 #include "libANGLE/Config.h"
18 #include "libANGLE/Context.h"
19 #include "libANGLE/Display.h"
20 #include "libANGLE/Framebuffer.h"
21 #include "libANGLE/Texture.h"
22 #include "libANGLE/Thread.h"
23 #include "libANGLE/formatutils.h"
24 #include "libANGLE/renderer/EGLImplFactory.h"
25
26 namespace egl
27 {
28
SurfaceState(const egl::Config * configIn,const AttributeMap & attributesIn)29 SurfaceState::SurfaceState(const egl::Config *configIn, const AttributeMap &attributesIn)
30 : defaultFramebuffer(nullptr), config(configIn), attributes(attributesIn)
31 {
32 }
33
Surface(EGLint surfaceType,const egl::Config * config,const AttributeMap & attributes)34 Surface::Surface(EGLint surfaceType, const egl::Config *config, const AttributeMap &attributes)
35 : FramebufferAttachmentObject(),
36 mState(config, attributes),
37 mImplementation(nullptr),
38 mCurrentCount(0),
39 mDestroyed(false),
40 mType(surfaceType),
41 mPostSubBufferRequested(false),
42 mLargestPbuffer(false),
43 mGLColorspace(EGL_GL_COLORSPACE_LINEAR),
44 mVGAlphaFormat(EGL_VG_ALPHA_FORMAT_NONPRE),
45 mVGColorspace(EGL_VG_COLORSPACE_sRGB),
46 mMipmapTexture(false),
47 mMipmapLevel(0),
48 mHorizontalResolution(EGL_UNKNOWN),
49 mVerticalResolution(EGL_UNKNOWN),
50 mMultisampleResolve(EGL_MULTISAMPLE_RESOLVE_DEFAULT),
51 mFixedSize(false),
52 mFixedWidth(0),
53 mFixedHeight(0),
54 mTextureFormat(EGL_NO_TEXTURE),
55 mTextureTarget(EGL_NO_TEXTURE),
56 // FIXME: Determine actual pixel aspect ratio
57 mPixelAspectRatio(static_cast<EGLint>(1.0 * EGL_DISPLAY_SCALING)),
58 mRenderBuffer(EGL_BACK_BUFFER),
59 mSwapBehavior(EGL_NONE),
60 mOrientation(0),
61 mTexture(),
62 mBackFormat(config->renderTargetFormat),
63 mDSFormat(config->depthStencilFormat)
64 {
65 mPostSubBufferRequested = (attributes.get(EGL_POST_SUB_BUFFER_SUPPORTED_NV, EGL_FALSE) == EGL_TRUE);
66 mFlexibleSurfaceCompatibilityRequested =
67 (attributes.get(EGL_FLEXIBLE_SURFACE_COMPATIBILITY_SUPPORTED_ANGLE, EGL_FALSE) == EGL_TRUE);
68
69 if (mType == EGL_PBUFFER_BIT)
70 {
71 mLargestPbuffer = (attributes.get(EGL_LARGEST_PBUFFER, EGL_FALSE) == EGL_TRUE);
72 }
73
74 mGLColorspace =
75 static_cast<EGLenum>(attributes.get(EGL_GL_COLORSPACE, EGL_GL_COLORSPACE_LINEAR));
76 mVGAlphaFormat =
77 static_cast<EGLenum>(attributes.get(EGL_VG_ALPHA_FORMAT, EGL_VG_ALPHA_FORMAT_NONPRE));
78 mVGColorspace = static_cast<EGLenum>(attributes.get(EGL_VG_COLORSPACE, EGL_VG_COLORSPACE_sRGB));
79 mMipmapTexture = (attributes.get(EGL_MIPMAP_TEXTURE, EGL_FALSE) == EGL_TRUE);
80
81 mDirectComposition = (attributes.get(EGL_DIRECT_COMPOSITION_ANGLE, EGL_FALSE) == EGL_TRUE);
82
83 mRobustResourceInitialization =
84 (attributes.get(EGL_ROBUST_RESOURCE_INITIALIZATION_ANGLE, EGL_FALSE) == EGL_TRUE);
85
86 mFixedSize = (attributes.get(EGL_FIXED_SIZE_ANGLE, EGL_FALSE) == EGL_TRUE);
87 if (mFixedSize)
88 {
89 mFixedWidth = static_cast<size_t>(attributes.get(EGL_WIDTH, 0));
90 mFixedHeight = static_cast<size_t>(attributes.get(EGL_HEIGHT, 0));
91 }
92
93 if (mType != EGL_WINDOW_BIT)
94 {
95 mTextureFormat = static_cast<EGLenum>(attributes.get(EGL_TEXTURE_FORMAT, EGL_NO_TEXTURE));
96 mTextureTarget = static_cast<EGLenum>(attributes.get(EGL_TEXTURE_TARGET, EGL_NO_TEXTURE));
97 }
98
99 mOrientation = static_cast<EGLint>(attributes.get(EGL_SURFACE_ORIENTATION_ANGLE, 0));
100 }
101
~Surface()102 Surface::~Surface()
103 {
104 }
105
getAttachmentImpl() const106 rx::FramebufferAttachmentObjectImpl *Surface::getAttachmentImpl() const
107 {
108 return mImplementation;
109 }
110
destroyImpl(const Display * display)111 Error Surface::destroyImpl(const Display *display)
112 {
113 if (mState.defaultFramebuffer)
114 {
115 mState.defaultFramebuffer->destroyDefault(display);
116 }
117 if (mImplementation)
118 {
119 mImplementation->destroy(display);
120 }
121
122 if (mTexture.get())
123 {
124 if (mImplementation)
125 {
126 ANGLE_TRY(mImplementation->releaseTexImage(EGL_BACK_BUFFER));
127 }
128 auto glErr = mTexture->releaseTexImageFromSurface(display->getProxyContext());
129 if (glErr.isError())
130 {
131 return Error(EGL_BAD_SURFACE);
132 }
133 mTexture.set(nullptr, nullptr);
134 }
135
136 if (mState.defaultFramebuffer)
137 {
138 mState.defaultFramebuffer->onDestroy(display->getProxyContext());
139 }
140 SafeDelete(mState.defaultFramebuffer);
141 SafeDelete(mImplementation);
142
143 delete this;
144 return NoError();
145 }
146
initialize(const Display * display)147 Error Surface::initialize(const Display *display)
148 {
149 ANGLE_TRY(mImplementation->initialize(display));
150
151 // Initialized here since impl is nullptr in the constructor.
152 // Must happen after implementation initialize for Android.
153 mSwapBehavior = mImplementation->getSwapBehavior();
154
155 // Must happen after implementation initialize for OSX.
156 mState.defaultFramebuffer = createDefaultFramebuffer(display);
157 ASSERT(mState.defaultFramebuffer != nullptr);
158
159 return NoError();
160 }
161
setIsCurrent(const gl::Context * context,bool isCurrent)162 Error Surface::setIsCurrent(const gl::Context *context, bool isCurrent)
163 {
164 if (isCurrent)
165 {
166 mCurrentCount++;
167 return NoError();
168 }
169
170 ASSERT(mCurrentCount > 0);
171 mCurrentCount--;
172 if (mCurrentCount == 0 && mDestroyed)
173 {
174 ASSERT(context);
175 return destroyImpl(context->getCurrentDisplay());
176 }
177 return NoError();
178 }
179
onDestroy(const Display * display)180 Error Surface::onDestroy(const Display *display)
181 {
182 mDestroyed = true;
183 if (mCurrentCount == 0)
184 {
185 return destroyImpl(display);
186 }
187 return NoError();
188 }
189
getType() const190 EGLint Surface::getType() const
191 {
192 return mType;
193 }
194
swap(const gl::Context * context)195 Error Surface::swap(const gl::Context *context)
196 {
197 return mImplementation->swap(context);
198 }
199
swapWithDamage(const gl::Context * context,EGLint * rects,EGLint n_rects)200 Error Surface::swapWithDamage(const gl::Context *context, EGLint *rects, EGLint n_rects)
201 {
202 return mImplementation->swapWithDamage(context, rects, n_rects);
203 }
204
postSubBuffer(const gl::Context * context,EGLint x,EGLint y,EGLint width,EGLint height)205 Error Surface::postSubBuffer(const gl::Context *context,
206 EGLint x,
207 EGLint y,
208 EGLint width,
209 EGLint height)
210 {
211 return mImplementation->postSubBuffer(context, x, y, width, height);
212 }
213
querySurfacePointerANGLE(EGLint attribute,void ** value)214 Error Surface::querySurfacePointerANGLE(EGLint attribute, void **value)
215 {
216 return mImplementation->querySurfacePointerANGLE(attribute, value);
217 }
218
isPostSubBufferSupported() const219 EGLint Surface::isPostSubBufferSupported() const
220 {
221 return mPostSubBufferRequested && mImplementation->isPostSubBufferSupported();
222 }
223
setSwapInterval(EGLint interval)224 void Surface::setSwapInterval(EGLint interval)
225 {
226 mImplementation->setSwapInterval(interval);
227 }
228
setMipmapLevel(EGLint level)229 void Surface::setMipmapLevel(EGLint level)
230 {
231 // Level is set but ignored
232 UNIMPLEMENTED();
233 mMipmapLevel = level;
234 }
235
setMultisampleResolve(EGLenum resolve)236 void Surface::setMultisampleResolve(EGLenum resolve)
237 {
238 // Behaviour is set but ignored
239 UNIMPLEMENTED();
240 mMultisampleResolve = resolve;
241 }
242
setSwapBehavior(EGLenum behavior)243 void Surface::setSwapBehavior(EGLenum behavior)
244 {
245 // Behaviour is set but ignored
246 UNIMPLEMENTED();
247 mSwapBehavior = behavior;
248 }
249
getConfig() const250 const Config *Surface::getConfig() const
251 {
252 return mState.config;
253 }
254
getPixelAspectRatio() const255 EGLint Surface::getPixelAspectRatio() const
256 {
257 return mPixelAspectRatio;
258 }
259
getRenderBuffer() const260 EGLenum Surface::getRenderBuffer() const
261 {
262 return mRenderBuffer;
263 }
264
getSwapBehavior() const265 EGLenum Surface::getSwapBehavior() const
266 {
267 return mSwapBehavior;
268 }
269
getTextureFormat() const270 EGLenum Surface::getTextureFormat() const
271 {
272 return mTextureFormat;
273 }
274
getTextureTarget() const275 EGLenum Surface::getTextureTarget() const
276 {
277 return mTextureTarget;
278 }
279
getLargestPbuffer() const280 bool Surface::getLargestPbuffer() const
281 {
282 return mLargestPbuffer;
283 }
284
getGLColorspace() const285 EGLenum Surface::getGLColorspace() const
286 {
287 return mGLColorspace;
288 }
289
getVGAlphaFormat() const290 EGLenum Surface::getVGAlphaFormat() const
291 {
292 return mVGAlphaFormat;
293 }
294
getVGColorspace() const295 EGLenum Surface::getVGColorspace() const
296 {
297 return mVGColorspace;
298 }
299
getMipmapTexture() const300 bool Surface::getMipmapTexture() const
301 {
302 return mMipmapTexture;
303 }
304
getMipmapLevel() const305 EGLint Surface::getMipmapLevel() const
306 {
307 return mMipmapLevel;
308 }
309
getHorizontalResolution() const310 EGLint Surface::getHorizontalResolution() const
311 {
312 return mHorizontalResolution;
313 }
314
getVerticalResolution() const315 EGLint Surface::getVerticalResolution() const
316 {
317 return mVerticalResolution;
318 }
319
getMultisampleResolve() const320 EGLenum Surface::getMultisampleResolve() const
321 {
322 return mMultisampleResolve;
323 }
324
isFixedSize() const325 EGLint Surface::isFixedSize() const
326 {
327 return mFixedSize;
328 }
329
getWidth() const330 EGLint Surface::getWidth() const
331 {
332 return mFixedSize ? static_cast<EGLint>(mFixedWidth) : mImplementation->getWidth();
333 }
334
getHeight() const335 EGLint Surface::getHeight() const
336 {
337 return mFixedSize ? static_cast<EGLint>(mFixedHeight) : mImplementation->getHeight();
338 }
339
bindTexImage(const gl::Context * context,gl::Texture * texture,EGLint buffer)340 Error Surface::bindTexImage(const gl::Context *context, gl::Texture *texture, EGLint buffer)
341 {
342 ASSERT(!mTexture.get());
343 ANGLE_TRY(mImplementation->bindTexImage(texture, buffer));
344
345 auto glErr = texture->bindTexImageFromSurface(context, this);
346 if (glErr.isError())
347 {
348 return Error(EGL_BAD_SURFACE);
349 }
350 mTexture.set(context, texture);
351
352 return NoError();
353 }
354
releaseTexImage(const gl::Context * context,EGLint buffer)355 Error Surface::releaseTexImage(const gl::Context *context, EGLint buffer)
356 {
357 ASSERT(context);
358
359 ANGLE_TRY(mImplementation->releaseTexImage(buffer));
360
361 ASSERT(mTexture.get());
362 auto glErr = mTexture->releaseTexImageFromSurface(context);
363 if (glErr.isError())
364 {
365 return Error(EGL_BAD_SURFACE);
366 }
367 mTexture.set(context, nullptr);
368
369 return NoError();
370 }
371
getSyncValues(EGLuint64KHR * ust,EGLuint64KHR * msc,EGLuint64KHR * sbc)372 Error Surface::getSyncValues(EGLuint64KHR *ust, EGLuint64KHR *msc, EGLuint64KHR *sbc)
373 {
374 return mImplementation->getSyncValues(ust, msc, sbc);
375 }
376
releaseTexImageFromTexture(const gl::Context * context)377 void Surface::releaseTexImageFromTexture(const gl::Context *context)
378 {
379 ASSERT(mTexture.get());
380 mTexture.set(context, nullptr);
381 }
382
getAttachmentSize(const gl::ImageIndex &) const383 gl::Extents Surface::getAttachmentSize(const gl::ImageIndex & /*target*/) const
384 {
385 return gl::Extents(getWidth(), getHeight(), 1);
386 }
387
getAttachmentFormat(GLenum binding,const gl::ImageIndex & target) const388 const gl::Format &Surface::getAttachmentFormat(GLenum binding, const gl::ImageIndex &target) const
389 {
390 return (binding == GL_BACK ? mBackFormat : mDSFormat);
391 }
392
getAttachmentSamples(const gl::ImageIndex & target) const393 GLsizei Surface::getAttachmentSamples(const gl::ImageIndex &target) const
394 {
395 return getConfig()->samples;
396 }
397
getId() const398 GLuint Surface::getId() const
399 {
400 UNREACHABLE();
401 return 0;
402 }
403
createDefaultFramebuffer(const Display * display)404 gl::Framebuffer *Surface::createDefaultFramebuffer(const Display *display)
405 {
406 return new gl::Framebuffer(display, this);
407 }
408
initState(const gl::ImageIndex &) const409 gl::InitState Surface::initState(const gl::ImageIndex & /*imageIndex*/) const
410 {
411 // TODO(jmadill): Lazy surface init.
412 return gl::InitState::Initialized;
413 }
414
setInitState(const gl::ImageIndex &,gl::InitState)415 void Surface::setInitState(const gl::ImageIndex & /*imageIndex*/, gl::InitState /*initState*/)
416 {
417 // No-op.
418 }
419
WindowSurface(rx::EGLImplFactory * implFactory,const egl::Config * config,EGLNativeWindowType window,const AttributeMap & attribs)420 WindowSurface::WindowSurface(rx::EGLImplFactory *implFactory,
421 const egl::Config *config,
422 EGLNativeWindowType window,
423 const AttributeMap &attribs)
424 : Surface(EGL_WINDOW_BIT, config, attribs)
425 {
426 mImplementation = implFactory->createWindowSurface(mState, window, attribs);
427 }
428
~WindowSurface()429 WindowSurface::~WindowSurface()
430 {
431 }
432
PbufferSurface(rx::EGLImplFactory * implFactory,const Config * config,const AttributeMap & attribs)433 PbufferSurface::PbufferSurface(rx::EGLImplFactory *implFactory,
434 const Config *config,
435 const AttributeMap &attribs)
436 : Surface(EGL_PBUFFER_BIT, config, attribs)
437 {
438 mImplementation = implFactory->createPbufferSurface(mState, attribs);
439 }
440
PbufferSurface(rx::EGLImplFactory * implFactory,const Config * config,EGLenum buftype,EGLClientBuffer clientBuffer,const AttributeMap & attribs)441 PbufferSurface::PbufferSurface(rx::EGLImplFactory *implFactory,
442 const Config *config,
443 EGLenum buftype,
444 EGLClientBuffer clientBuffer,
445 const AttributeMap &attribs)
446 : Surface(EGL_PBUFFER_BIT, config, attribs)
447 {
448 mImplementation =
449 implFactory->createPbufferFromClientBuffer(mState, buftype, clientBuffer, attribs);
450 }
451
~PbufferSurface()452 PbufferSurface::~PbufferSurface()
453 {
454 }
455
PixmapSurface(rx::EGLImplFactory * implFactory,const Config * config,NativePixmapType nativePixmap,const AttributeMap & attribs)456 PixmapSurface::PixmapSurface(rx::EGLImplFactory *implFactory,
457 const Config *config,
458 NativePixmapType nativePixmap,
459 const AttributeMap &attribs)
460 : Surface(EGL_PIXMAP_BIT, config, attribs)
461 {
462 mImplementation = implFactory->createPixmapSurface(mState, nativePixmap, attribs);
463 }
464
~PixmapSurface()465 PixmapSurface::~PixmapSurface()
466 {
467 }
468
469 // SurfaceDeleter implementation.
470
SurfaceDeleter(const Display * display)471 SurfaceDeleter::SurfaceDeleter(const Display *display) : mDisplay(display)
472 {
473 }
474
~SurfaceDeleter()475 SurfaceDeleter::~SurfaceDeleter()
476 {
477 }
478
operator ()(Surface * surface)479 void SurfaceDeleter::operator()(Surface *surface)
480 {
481 ANGLE_SWALLOW_ERR(surface->onDestroy(mDisplay));
482 }
483
484 } // namespace egl
485