already_AddRefed<GLContext> GLContextProviderWGL::CreateOffscreen(const gfxIntSize& size, const SurfaceCaps& caps) { if (!sWGLLib.EnsureInitialized()) { return nullptr; } nsRefPtr<GLContextWGL> glContext; // Always try to create a pbuffer context first, because we // want the context isolation. if (sWGLLib.fCreatePbuffer && sWGLLib.fChoosePixelFormat) { gfxIntSize dummySize = gfxIntSize(16, 16); glContext = CreatePBufferOffscreenContext(dummySize, GetGlobalContextWGL()); } // If it failed, then create a window context and use a FBO. if (!glContext) { glContext = CreateWindowOffscreenContext(); } if (!glContext || !glContext->Init()) { return nullptr; } if (!glContext->InitOffscreen(ToIntSize(size), caps)) return nullptr; return glContext.forget(); }
void GLScreenBuffer::DeprecatedReadback(SharedSurface_GL* src, gfxImageSurface* dest) { MOZ_ASSERT(src && dest); MOZ_ASSERT(ToIntSize(dest->GetSize()) == src->Size()); MOZ_ASSERT(dest->Format() == (src->HasAlpha() ? gfxImageFormat::ARGB32 : gfxImageFormat::RGB24)); mGL->MakeCurrent(); bool needsSwap = src != SharedSurf(); if (needsSwap) { SharedSurf()->UnlockProd(); src->LockProd(); } ReadBuffer* buffer = CreateRead(src); MOZ_ASSERT(buffer); ScopedBindFramebuffer autoFB(mGL, buffer->FB()); ReadPixelsIntoImageSurface(mGL, dest); delete buffer; if (needsSwap) { src->UnlockProd(); SharedSurf()->LockProd(); } }
DIBTextureHost::DIBTextureHost(TextureFlags aFlags, const SurfaceDescriptorDIB& aDescriptor) : TextureHost(aFlags) , mIsLocked(false) { // We added an extra ref for transport, so we shouldn't AddRef now. mSurface = dont_AddRef(reinterpret_cast<gfxWindowsSurface*>(aDescriptor.surface())); MOZ_ASSERT(mSurface); mSize = ToIntSize(mSurface->GetSize()); mFormat = ImageFormatToSurfaceFormat( gfxPlatform::GetPlatform()->OptimalFormatForContent(mSurface->GetContentType())); }
// Run the test for a texture client and a surface void TestTextureClientSurface(TextureClient* texture, gfxImageSurface* surface) { // client allocation ASSERT_TRUE(texture->CanExposeDrawTarget()); texture->AllocateForSurface(ToIntSize(surface->GetSize())); ASSERT_TRUE(texture->IsAllocated()); ASSERT_TRUE(texture->Lock(OPEN_READ_WRITE)); // client painting RefPtr<DrawTarget> dt = texture->GetAsDrawTarget(); RefPtr<SourceSurface> source = gfxPlatform::GetPlatform()->GetSourceSurfaceForSurface(dt, surface); dt->CopySurface(source, IntRect(IntPoint(), source->GetSize()), IntPoint()); RefPtr<SourceSurface> snapshot = dt->Snapshot(); AssertSurfacesEqual(snapshot, source); dt = nullptr; // drop reference before calling Unlock() texture->Unlock(); // client serialization SurfaceDescriptor descriptor; ASSERT_TRUE(texture->ToSurfaceDescriptor(descriptor)); ASSERT_NE(descriptor.type(), SurfaceDescriptor::Tnull_t); // host deserialization RefPtr<TextureHost> host = CreateBackendIndependentTextureHost(descriptor, nullptr, texture->GetFlags()); ASSERT_TRUE(host.get() != nullptr); ASSERT_EQ(host->GetFlags(), texture->GetFlags()); // host read ASSERT_TRUE(host->Lock()); RefPtr<mozilla::gfx::DataSourceSurface> hostDataSurface = host->GetAsSurface(); host->Unlock(); nsRefPtr<gfxImageSurface> hostSurface = new gfxImageSurface(hostDataSurface->GetData(), ThebesIntSize(hostDataSurface->GetSize()), hostDataSurface->Stride(), SurfaceFormatToImageFormat(hostDataSurface->GetFormat())); AssertSurfacesEqual(surface, hostSurface.get()); }
void ReadPixelsIntoImageSurface(GLContext* gl, gfxImageSurface* dest) { gl->MakeCurrent(); MOZ_ASSERT(dest->GetSize() != gfxIntSize(0, 0)); /* gfxImageFormat::ARGB32: * RGBA+UByte: be[RGBA], le[ABGR] * RGBA+UInt: le[RGBA] * BGRA+UInt: le[BGRA] * BGRA+UIntRev: le[ARGB] * * gfxImageFormat::RGB16_565: * RGB+UShort: le[rrrrrggg,gggbbbbb] */ bool hasAlpha = dest->Format() == gfxImageFormat::ARGB32; int destPixelSize; GLenum destFormat; GLenum destType; switch (dest->Format()) { case gfxImageFormat::RGB24: // XRGB case gfxImageFormat::ARGB32: destPixelSize = 4; // Needs host (little) endian ARGB. destFormat = LOCAL_GL_BGRA; destType = LOCAL_GL_UNSIGNED_INT_8_8_8_8_REV; break; case gfxImageFormat::RGB16_565: destPixelSize = 2; destFormat = LOCAL_GL_RGB; destType = LOCAL_GL_UNSIGNED_SHORT_5_6_5_REV; break; default: MOZ_CRASH("Bad format."); } MOZ_ASSERT(dest->Stride() == dest->Width() * destPixelSize); GLenum readFormat = destFormat; GLenum readType = destType; bool needsTempSurf = !GetActualReadFormats(gl, destFormat, destType, readFormat, readType); nsAutoPtr<gfxImageSurface> tempSurf; gfxImageSurface* readSurf = nullptr; int readPixelSize = 0; if (needsTempSurf) { if (gl->DebugMode()) { NS_WARNING("Needing intermediary surface for ReadPixels. This will be slow!"); } SurfaceFormat readFormatGFX; switch (readFormat) { case LOCAL_GL_RGBA: case LOCAL_GL_BGRA: { readFormatGFX = hasAlpha ? SurfaceFormat::B8G8R8A8 : SurfaceFormat::B8G8R8X8; break; } case LOCAL_GL_RGB: { MOZ_ASSERT(readPixelSize == 2); MOZ_ASSERT(readType == LOCAL_GL_UNSIGNED_SHORT_5_6_5_REV); readFormatGFX = SurfaceFormat::R5G6B5; break; } default: { MOZ_CRASH("Bad read format."); } } switch (readType) { case LOCAL_GL_UNSIGNED_BYTE: { MOZ_ASSERT(readFormat == LOCAL_GL_RGBA); readPixelSize = 4; break; } case LOCAL_GL_UNSIGNED_INT_8_8_8_8_REV: { MOZ_ASSERT(readFormat == LOCAL_GL_BGRA); readPixelSize = 4; break; } case LOCAL_GL_UNSIGNED_SHORT_5_6_5_REV: { MOZ_ASSERT(readFormat == LOCAL_GL_RGB); readPixelSize = 2; break; } default: { MOZ_CRASH("Bad read type."); } } tempSurf = new gfxImageSurface(dest->GetSize(), SurfaceFormatToImageFormat(readFormatGFX), false); readSurf = tempSurf; } else { readPixelSize = destPixelSize; readSurf = dest; } MOZ_ASSERT(readPixelSize); GLint currentPackAlignment = 0; gl->fGetIntegerv(LOCAL_GL_PACK_ALIGNMENT, ¤tPackAlignment); if (currentPackAlignment != readPixelSize) gl->fPixelStorei(LOCAL_GL_PACK_ALIGNMENT, readPixelSize); GLsizei width = dest->Width(); GLsizei height = dest->Height(); readSurf->Flush(); gl->fReadPixels(0, 0, width, height, readFormat, readType, readSurf->Data()); readSurf->MarkDirty(); if (currentPackAlignment != readPixelSize) gl->fPixelStorei(LOCAL_GL_PACK_ALIGNMENT, currentPackAlignment); if (readSurf != dest) { MOZ_ASSERT(readFormat == LOCAL_GL_RGBA); MOZ_ASSERT(readType == LOCAL_GL_UNSIGNED_BYTE); // So we just copied in RGBA in big endian, or le: 0xAABBGGRR. // We want 0xAARRGGBB, so swap R and B: dest->Flush(); RefPtr<DataSourceSurface> readDSurf = Factory::CreateWrappingDataSourceSurface(readSurf->Data(), readSurf->Stride(), ToIntSize(readSurf->GetSize()), ImageFormatToSurfaceFormat(readSurf->Format())); SwapRAndBComponents(readDSurf); dest->MarkDirty(); gfxContext ctx(dest); ctx.SetOperator(gfxContext::OPERATOR_SOURCE); ctx.SetSource(readSurf); ctx.Paint(); } // Check if GL is giving back 1.0 alpha for // RGBA reads to RGBA images from no-alpha buffers. #ifdef XP_MACOSX if (gl->WorkAroundDriverBugs() && gl->Vendor() == gl::GLVendor::NVIDIA && dest->Format() == gfxImageFormat::ARGB32 && width && height) { GLint alphaBits = 0; gl->fGetIntegerv(LOCAL_GL_ALPHA_BITS, &alphaBits); if (!alphaBits) { const uint32_t alphaMask = gfxPackedPixelNoPreMultiply(0xff,0,0,0); dest->Flush(); uint32_t* itr = (uint32_t*)dest->Data(); uint32_t testPixel = *itr; if ((testPixel & alphaMask) != alphaMask) { // We need to set the alpha channel to 1.0 manually. uint32_t* itrEnd = itr + width*height; // Stride is guaranteed to be width*4. for (; itr != itrEnd; itr++) { *itr |= alphaMask; } } dest->MarkDirty(); } } #endif }
void CopyableCanvasLayer::UpdateSurface(gfxASurface* aDestSurface, Layer* aMaskLayer) { if (!IsDirty()) return; Painted(); if (mDrawTarget) { mDrawTarget->Flush(); mSurface = gfxPlatform::GetPlatform()->CreateThebesSurfaceAliasForDrawTarget_hack(mDrawTarget); } if (!mGLContext && aDestSurface) { nsRefPtr<gfxContext> tmpCtx = new gfxContext(aDestSurface); tmpCtx->SetOperator(gfxContext::OPERATOR_SOURCE); CopyableCanvasLayer::PaintWithOpacity(tmpCtx, 1.0f, aMaskLayer); return; } if (mGLContext) { nsRefPtr<gfxImageSurface> readSurf; nsRefPtr<gfxASurface> resultSurf; SharedSurface* sharedSurf = mGLContext->RequestFrame(); if (!sharedSurf) { NS_WARNING("Null frame received."); return; } IntSize readSize(ToIntSize(sharedSurf->Size())); gfxImageFormat format = (GetContentFlags() & CONTENT_OPAQUE) ? gfxImageFormatRGB24 : gfxImageFormatARGB32; if (aDestSurface) { resultSurf = aDestSurface; } else { resultSurf = GetTempSurface(readSize, format); } MOZ_ASSERT(resultSurf); if (resultSurf->CairoStatus() != 0) { MOZ_ASSERT(false, "Bad resultSurf->CairoStatus()."); return; } MOZ_ASSERT(sharedSurf->APIType() == APITypeT::OpenGL); SharedSurface_GL* surfGL = SharedSurface_GL::Cast(sharedSurf); if (surfGL->Type() == SharedSurfaceType::Basic) { SharedSurface_Basic* sharedSurf_Basic = SharedSurface_Basic::Cast(surfGL); readSurf = sharedSurf_Basic->GetData(); } else { if (ToIntSize(resultSurf->GetSize()) != readSize || !(readSurf = resultSurf->GetAsImageSurface()) || readSurf->Format() != format) { readSurf = GetTempSurface(readSize, format); } // Readback handles Flush/MarkDirty. mGLContext->Screen()->Readback(surfGL, readSurf); } MOZ_ASSERT(readSurf); bool needsPremult = surfGL->HasAlpha() && !mIsGLAlphaPremult; if (needsPremult) { readSurf->Flush(); gfxUtils::PremultiplyImageSurface(readSurf); readSurf->MarkDirty(); } if (readSurf != resultSurf) { readSurf->Flush(); nsRefPtr<gfxContext> ctx = new gfxContext(resultSurf); ctx->SetOperator(gfxContext::OPERATOR_SOURCE); ctx->SetSource(readSurf); ctx->Paint(); } // If !aDestSurface then we will end up painting using mSurface, so // stick our surface into mSurface, so that the Paint() path is the same. if (!aDestSurface) { mSurface = resultSurf; } } }