gfx/gl/SharedSurfaceGL.cpp

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

michael@0 1 /* -*- Mode: c++; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40; -*- */
michael@0 2 /* This Source Code Form is subject to the terms of the Mozilla Public
michael@0 3 * License, v. 2.0. If a copy of the MPL was not distributed with this
michael@0 4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
michael@0 5
michael@0 6 #include "SharedSurfaceGL.h"
michael@0 7 #include "GLContext.h"
michael@0 8 #include "GLBlitHelper.h"
michael@0 9 #include "ScopedGLHelpers.h"
michael@0 10 #include "gfxImageSurface.h"
michael@0 11 #include "mozilla/gfx/2D.h"
michael@0 12 #include "GLReadTexImageHelper.h"
michael@0 13
michael@0 14 using namespace mozilla::gfx;
michael@0 15
michael@0 16 namespace mozilla {
michael@0 17 namespace gl {
michael@0 18
michael@0 19 // |src| must begin and end locked, though we may
michael@0 20 // temporarily unlock it if we need to.
michael@0 21 void
michael@0 22 SharedSurface_GL::ProdCopy(SharedSurface_GL* src, SharedSurface_GL* dest,
michael@0 23 SurfaceFactory_GL* factory)
michael@0 24 {
michael@0 25 GLContext* gl = src->GL();
michael@0 26
michael@0 27 gl->MakeCurrent();
michael@0 28
michael@0 29 if (src->AttachType() == AttachmentType::Screen &&
michael@0 30 dest->AttachType() == AttachmentType::Screen)
michael@0 31 {
michael@0 32 // Here, we actually need to blit through a temp surface, so let's make one.
michael@0 33 nsAutoPtr<SharedSurface_GLTexture> tempSurf(
michael@0 34 SharedSurface_GLTexture::Create(gl, gl,
michael@0 35 factory->Formats(),
michael@0 36 src->Size(),
michael@0 37 factory->Caps().alpha));
michael@0 38
michael@0 39 ProdCopy(src, tempSurf, factory);
michael@0 40 ProdCopy(tempSurf, dest, factory);
michael@0 41 return;
michael@0 42 }
michael@0 43
michael@0 44 if (src->AttachType() == AttachmentType::Screen) {
michael@0 45 SharedSurface_GL* origLocked = gl->GetLockedSurface();
michael@0 46 bool srcNeedsUnlock = false;
michael@0 47 bool origNeedsRelock = false;
michael@0 48 if (origLocked != src) {
michael@0 49 if (origLocked) {
michael@0 50 origLocked->UnlockProd();
michael@0 51 origNeedsRelock = true;
michael@0 52 }
michael@0 53
michael@0 54 src->LockProd();
michael@0 55 srcNeedsUnlock = true;
michael@0 56 }
michael@0 57
michael@0 58 if (dest->AttachType() == AttachmentType::GLTexture) {
michael@0 59 GLuint destTex = dest->ProdTexture();
michael@0 60 GLenum destTarget = dest->ProdTextureTarget();
michael@0 61
michael@0 62 gl->BlitHelper()->BlitFramebufferToTexture(0, destTex, src->Size(), dest->Size(), destTarget);
michael@0 63 } else if (dest->AttachType() == AttachmentType::GLRenderbuffer) {
michael@0 64 GLuint destRB = dest->ProdRenderbuffer();
michael@0 65 ScopedFramebufferForRenderbuffer destWrapper(gl, destRB);
michael@0 66
michael@0 67 gl->BlitHelper()->BlitFramebufferToFramebuffer(0, destWrapper.FB(),
michael@0 68 src->Size(), dest->Size());
michael@0 69 } else {
michael@0 70 MOZ_CRASH("Unhandled dest->AttachType().");
michael@0 71 }
michael@0 72
michael@0 73 if (srcNeedsUnlock)
michael@0 74 src->UnlockProd();
michael@0 75
michael@0 76 if (origNeedsRelock)
michael@0 77 origLocked->LockProd();
michael@0 78
michael@0 79 return;
michael@0 80 }
michael@0 81
michael@0 82 if (dest->AttachType() == AttachmentType::Screen) {
michael@0 83 SharedSurface_GL* origLocked = gl->GetLockedSurface();
michael@0 84 bool destNeedsUnlock = false;
michael@0 85 bool origNeedsRelock = false;
michael@0 86 if (origLocked != dest) {
michael@0 87 if (origLocked) {
michael@0 88 origLocked->UnlockProd();
michael@0 89 origNeedsRelock = true;
michael@0 90 }
michael@0 91
michael@0 92 dest->LockProd();
michael@0 93 destNeedsUnlock = true;
michael@0 94 }
michael@0 95
michael@0 96 if (src->AttachType() == AttachmentType::GLTexture) {
michael@0 97 GLuint srcTex = src->ProdTexture();
michael@0 98 GLenum srcTarget = src->ProdTextureTarget();
michael@0 99
michael@0 100 gl->BlitHelper()->BlitTextureToFramebuffer(srcTex, 0, src->Size(), dest->Size(), srcTarget);
michael@0 101 } else if (src->AttachType() == AttachmentType::GLRenderbuffer) {
michael@0 102 GLuint srcRB = src->ProdRenderbuffer();
michael@0 103 ScopedFramebufferForRenderbuffer srcWrapper(gl, srcRB);
michael@0 104
michael@0 105 gl->BlitHelper()->BlitFramebufferToFramebuffer(srcWrapper.FB(), 0,
michael@0 106 src->Size(), dest->Size());
michael@0 107 } else {
michael@0 108 MOZ_CRASH("Unhandled src->AttachType().");
michael@0 109 }
michael@0 110
michael@0 111 if (destNeedsUnlock)
michael@0 112 dest->UnlockProd();
michael@0 113
michael@0 114 if (origNeedsRelock)
michael@0 115 origLocked->LockProd();
michael@0 116
michael@0 117 return;
michael@0 118 }
michael@0 119
michael@0 120 // Alright, done with cases involving Screen types.
michael@0 121 // Only {src,dest}x{texture,renderbuffer} left.
michael@0 122
michael@0 123 if (src->AttachType() == AttachmentType::GLTexture) {
michael@0 124 GLuint srcTex = src->ProdTexture();
michael@0 125 GLenum srcTarget = src->ProdTextureTarget();
michael@0 126
michael@0 127 if (dest->AttachType() == AttachmentType::GLTexture) {
michael@0 128 GLuint destTex = dest->ProdTexture();
michael@0 129 GLenum destTarget = dest->ProdTextureTarget();
michael@0 130
michael@0 131 gl->BlitHelper()->BlitTextureToTexture(srcTex, destTex,
michael@0 132 src->Size(), dest->Size(),
michael@0 133 srcTarget, destTarget);
michael@0 134
michael@0 135 return;
michael@0 136 }
michael@0 137
michael@0 138 if (dest->AttachType() == AttachmentType::GLRenderbuffer) {
michael@0 139 GLuint destRB = dest->ProdRenderbuffer();
michael@0 140 ScopedFramebufferForRenderbuffer destWrapper(gl, destRB);
michael@0 141
michael@0 142 gl->BlitHelper()->BlitTextureToFramebuffer(srcTex, destWrapper.FB(),
michael@0 143 src->Size(), dest->Size(), srcTarget);
michael@0 144
michael@0 145 return;
michael@0 146 }
michael@0 147
michael@0 148 MOZ_CRASH("Unhandled dest->AttachType().");
michael@0 149 }
michael@0 150
michael@0 151 if (src->AttachType() == AttachmentType::GLRenderbuffer) {
michael@0 152 GLuint srcRB = src->ProdRenderbuffer();
michael@0 153 ScopedFramebufferForRenderbuffer srcWrapper(gl, srcRB);
michael@0 154
michael@0 155 if (dest->AttachType() == AttachmentType::GLTexture) {
michael@0 156 GLuint destTex = dest->ProdTexture();
michael@0 157 GLenum destTarget = dest->ProdTextureTarget();
michael@0 158
michael@0 159 gl->BlitHelper()->BlitFramebufferToTexture(srcWrapper.FB(), destTex,
michael@0 160 src->Size(), dest->Size(), destTarget);
michael@0 161
michael@0 162 return;
michael@0 163 }
michael@0 164
michael@0 165 if (dest->AttachType() == AttachmentType::GLRenderbuffer) {
michael@0 166 GLuint destRB = dest->ProdRenderbuffer();
michael@0 167 ScopedFramebufferForRenderbuffer destWrapper(gl, destRB);
michael@0 168
michael@0 169 gl->BlitHelper()->BlitFramebufferToFramebuffer(srcWrapper.FB(), destWrapper.FB(),
michael@0 170 src->Size(), dest->Size());
michael@0 171
michael@0 172 return;
michael@0 173 }
michael@0 174
michael@0 175 MOZ_CRASH("Unhandled dest->AttachType().");
michael@0 176 }
michael@0 177
michael@0 178 MOZ_CRASH("Unhandled src->AttachType().");
michael@0 179 }
michael@0 180
michael@0 181 void
michael@0 182 SharedSurface_GL::LockProd()
michael@0 183 {
michael@0 184 MOZ_ASSERT(!mIsLocked);
michael@0 185
michael@0 186 LockProdImpl();
michael@0 187
michael@0 188 mGL->LockSurface(this);
michael@0 189 mIsLocked = true;
michael@0 190 }
michael@0 191
michael@0 192 void
michael@0 193 SharedSurface_GL::UnlockProd()
michael@0 194 {
michael@0 195 if (!mIsLocked)
michael@0 196 return;
michael@0 197
michael@0 198 UnlockProdImpl();
michael@0 199
michael@0 200 mGL->UnlockSurface(this);
michael@0 201 mIsLocked = false;
michael@0 202 }
michael@0 203
michael@0 204
michael@0 205 SurfaceFactory_GL::SurfaceFactory_GL(GLContext* gl,
michael@0 206 SharedSurfaceType type,
michael@0 207 const SurfaceCaps& caps)
michael@0 208 : SurfaceFactory(type, caps)
michael@0 209 , mGL(gl)
michael@0 210 , mFormats(gl->ChooseGLFormats(caps))
michael@0 211 {
michael@0 212 ChooseBufferBits(caps, mDrawCaps, mReadCaps);
michael@0 213 }
michael@0 214
michael@0 215 void
michael@0 216 SurfaceFactory_GL::ChooseBufferBits(const SurfaceCaps& caps,
michael@0 217 SurfaceCaps& drawCaps,
michael@0 218 SurfaceCaps& readCaps) const
michael@0 219 {
michael@0 220 SurfaceCaps screenCaps;
michael@0 221
michael@0 222 screenCaps.color = caps.color;
michael@0 223 screenCaps.alpha = caps.alpha;
michael@0 224 screenCaps.bpp16 = caps.bpp16;
michael@0 225
michael@0 226 screenCaps.depth = caps.depth;
michael@0 227 screenCaps.stencil = caps.stencil;
michael@0 228
michael@0 229 screenCaps.antialias = caps.antialias;
michael@0 230 screenCaps.preserve = caps.preserve;
michael@0 231
michael@0 232 if (caps.antialias) {
michael@0 233 drawCaps = screenCaps;
michael@0 234 readCaps.Clear();
michael@0 235
michael@0 236 // Color caps need to be duplicated in readCaps.
michael@0 237 readCaps.color = caps.color;
michael@0 238 readCaps.alpha = caps.alpha;
michael@0 239 readCaps.bpp16 = caps.bpp16;
michael@0 240 } else {
michael@0 241 drawCaps.Clear();
michael@0 242 readCaps = screenCaps;
michael@0 243 }
michael@0 244 }
michael@0 245
michael@0 246
michael@0 247 SharedSurface_Basic*
michael@0 248 SharedSurface_Basic::Create(GLContext* gl,
michael@0 249 const GLFormats& formats,
michael@0 250 const IntSize& size,
michael@0 251 bool hasAlpha)
michael@0 252 {
michael@0 253 gl->MakeCurrent();
michael@0 254 GLuint tex = CreateTexture(gl, formats.color_texInternalFormat,
michael@0 255 formats.color_texFormat,
michael@0 256 formats.color_texType,
michael@0 257 size);
michael@0 258
michael@0 259 SurfaceFormat format = SurfaceFormat::B8G8R8X8;
michael@0 260 switch (formats.color_texInternalFormat) {
michael@0 261 case LOCAL_GL_RGB:
michael@0 262 case LOCAL_GL_RGB8:
michael@0 263 if (formats.color_texType == LOCAL_GL_UNSIGNED_SHORT_5_6_5)
michael@0 264 format = SurfaceFormat::R5G6B5;
michael@0 265 else
michael@0 266 format = SurfaceFormat::B8G8R8X8;
michael@0 267 break;
michael@0 268 case LOCAL_GL_RGBA:
michael@0 269 case LOCAL_GL_RGBA8:
michael@0 270 format = SurfaceFormat::B8G8R8A8;
michael@0 271 break;
michael@0 272 default:
michael@0 273 MOZ_CRASH("Unhandled Tex format.");
michael@0 274 }
michael@0 275 return new SharedSurface_Basic(gl, size, hasAlpha, format, tex);
michael@0 276 }
michael@0 277
michael@0 278 SharedSurface_Basic::SharedSurface_Basic(GLContext* gl,
michael@0 279 const IntSize& size,
michael@0 280 bool hasAlpha,
michael@0 281 SurfaceFormat format,
michael@0 282 GLuint tex)
michael@0 283 : SharedSurface_GL(SharedSurfaceType::Basic,
michael@0 284 AttachmentType::GLTexture,
michael@0 285 gl,
michael@0 286 size,
michael@0 287 hasAlpha)
michael@0 288 , mTex(tex), mFB(0)
michael@0 289 {
michael@0 290 mGL->MakeCurrent();
michael@0 291 mGL->fGenFramebuffers(1, &mFB);
michael@0 292
michael@0 293 ScopedBindFramebuffer autoFB(mGL, mFB);
michael@0 294 mGL->fFramebufferTexture2D(LOCAL_GL_FRAMEBUFFER,
michael@0 295 LOCAL_GL_COLOR_ATTACHMENT0,
michael@0 296 LOCAL_GL_TEXTURE_2D,
michael@0 297 mTex,
michael@0 298 0);
michael@0 299
michael@0 300 GLenum status = mGL->fCheckFramebufferStatus(LOCAL_GL_FRAMEBUFFER);
michael@0 301 if (status != LOCAL_GL_FRAMEBUFFER_COMPLETE) {
michael@0 302 mGL->fDeleteFramebuffers(1, &mFB);
michael@0 303 mFB = 0;
michael@0 304 }
michael@0 305
michael@0 306 mData = Factory::CreateDataSourceSurfaceWithStride(size, format,
michael@0 307 GetAlignedStride<4>(size.width * BytesPerPixel(format)));
michael@0 308 }
michael@0 309
michael@0 310 SharedSurface_Basic::~SharedSurface_Basic()
michael@0 311 {
michael@0 312 if (!mGL->MakeCurrent())
michael@0 313 return;
michael@0 314
michael@0 315 if (mFB)
michael@0 316 mGL->fDeleteFramebuffers(1, &mFB);
michael@0 317
michael@0 318 mGL->fDeleteTextures(1, &mTex);
michael@0 319 }
michael@0 320
michael@0 321 void
michael@0 322 SharedSurface_Basic::Fence()
michael@0 323 {
michael@0 324 mGL->MakeCurrent();
michael@0 325
michael@0 326 ScopedBindFramebuffer autoFB(mGL, mFB);
michael@0 327
michael@0 328 DataSourceSurface::MappedSurface map;
michael@0 329 mData->Map(DataSourceSurface::MapType::WRITE, &map);
michael@0 330 nsRefPtr<gfxImageSurface> wrappedData =
michael@0 331 new gfxImageSurface(map.mData,
michael@0 332 ThebesIntSize(mData->GetSize()),
michael@0 333 map.mStride,
michael@0 334 SurfaceFormatToImageFormat(mData->GetFormat()));
michael@0 335 ReadPixelsIntoImageSurface(mGL, wrappedData);
michael@0 336 mData->Unmap();
michael@0 337 }
michael@0 338
michael@0 339
michael@0 340
michael@0 341 SharedSurface_GLTexture*
michael@0 342 SharedSurface_GLTexture::Create(GLContext* prodGL,
michael@0 343 GLContext* consGL,
michael@0 344 const GLFormats& formats,
michael@0 345 const gfx::IntSize& size,
michael@0 346 bool hasAlpha,
michael@0 347 GLuint texture)
michael@0 348 {
michael@0 349 MOZ_ASSERT(prodGL);
michael@0 350 MOZ_ASSERT(!consGL || prodGL->SharesWith(consGL));
michael@0 351
michael@0 352 prodGL->MakeCurrent();
michael@0 353
michael@0 354 GLuint tex = texture;
michael@0 355
michael@0 356 bool ownsTex = false;
michael@0 357
michael@0 358 if (!tex) {
michael@0 359 tex = CreateTextureForOffscreen(prodGL, formats, size);
michael@0 360 ownsTex = true;
michael@0 361 }
michael@0 362
michael@0 363 return new SharedSurface_GLTexture(prodGL, consGL, size, hasAlpha, tex, ownsTex);
michael@0 364 }
michael@0 365
michael@0 366 SharedSurface_GLTexture::~SharedSurface_GLTexture()
michael@0 367 {
michael@0 368 if (!mGL->MakeCurrent())
michael@0 369 return;
michael@0 370
michael@0 371 if (mOwnsTex) {
michael@0 372 mGL->fDeleteTextures(1, &mTex);
michael@0 373 }
michael@0 374
michael@0 375 if (mSync) {
michael@0 376 mGL->fDeleteSync(mSync);
michael@0 377 }
michael@0 378 }
michael@0 379
michael@0 380 void
michael@0 381 SharedSurface_GLTexture::Fence()
michael@0 382 {
michael@0 383 MutexAutoLock lock(mMutex);
michael@0 384 mGL->MakeCurrent();
michael@0 385
michael@0 386 if (mConsGL && mGL->IsExtensionSupported(GLContext::ARB_sync)) {
michael@0 387 if (mSync) {
michael@0 388 mGL->fDeleteSync(mSync);
michael@0 389 mSync = 0;
michael@0 390 }
michael@0 391
michael@0 392 mSync = mGL->fFenceSync(LOCAL_GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
michael@0 393 if (mSync) {
michael@0 394 mGL->fFlush();
michael@0 395 return;
michael@0 396 }
michael@0 397 }
michael@0 398 MOZ_ASSERT(!mSync);
michael@0 399
michael@0 400 mGL->fFinish();
michael@0 401 }
michael@0 402
michael@0 403 bool
michael@0 404 SharedSurface_GLTexture::WaitSync()
michael@0 405 {
michael@0 406 MutexAutoLock lock(mMutex);
michael@0 407 if (!mSync) {
michael@0 408 // We must have used glFinish instead of glFenceSync.
michael@0 409 return true;
michael@0 410 }
michael@0 411
michael@0 412 mConsGL->MakeCurrent();
michael@0 413 MOZ_ASSERT(mConsGL->IsExtensionSupported(GLContext::ARB_sync));
michael@0 414
michael@0 415 mConsGL->fWaitSync(mSync,
michael@0 416 0,
michael@0 417 LOCAL_GL_TIMEOUT_IGNORED);
michael@0 418 mConsGL->fDeleteSync(mSync);
michael@0 419 mSync = 0;
michael@0 420
michael@0 421 return true;
michael@0 422 }
michael@0 423
michael@0 424 GLuint
michael@0 425 SharedSurface_GLTexture::ConsTexture(GLContext* consGL)
michael@0 426 {
michael@0 427 MutexAutoLock lock(mMutex);
michael@0 428 MOZ_ASSERT(consGL);
michael@0 429 MOZ_ASSERT(mGL->SharesWith(consGL));
michael@0 430 MOZ_ASSERT_IF(mConsGL, consGL == mConsGL);
michael@0 431
michael@0 432 mConsGL = consGL;
michael@0 433
michael@0 434 return mTex;
michael@0 435 }
michael@0 436
michael@0 437 } /* namespace gfx */
michael@0 438 } /* namespace mozilla */

mercurial