void CanvasLayerD3D9::UpdateSurface() { if (!IsDirty() && mTexture) return; Painted(); if (!mTexture) { CreateTexture(); if (!mTexture) { NS_WARNING("CanvasLayerD3D9::Updated called but no texture present and creation failed!"); return; } } // WebGL reads entire surface. LockTextureRectD3D9 textureLock(mTexture); if (!textureLock.HasLock()) { NS_WARNING("Failed to lock CanvasLayer texture."); return; } D3DLOCKED_RECT rect = textureLock.GetLockRect(); IntSize boundsSize(mBounds.width, mBounds.height); RefPtr<DrawTarget> rectDt = Factory::CreateDrawTargetForData(BackendType::CAIRO, (uint8_t*)rect.pBits, boundsSize, rect.Pitch, SurfaceFormat::B8G8R8A8); if (mGLContext) { auto screen = mGLContext->Screen(); MOZ_ASSERT(screen); SharedSurface* surf = screen->Front()->Surf(); if (!surf) return; surf->WaitSync(); if (!ReadbackSharedSurface(surf, rectDt)) { NS_WARNING("Failed to readback into texture."); } } else { RefPtr<SourceSurface> surface = mDrawTarget->Snapshot(); Rect drawRect(0, 0, surface->GetSize().width, surface->GetSize().height); rectDt->DrawSurface(surface, drawRect, drawRect, DrawSurfaceOptions(), DrawOptions(1.0F, CompositionOp::OP_SOURCE)); rectDt->Flush(); } }
void CanvasLayerD3D9::UpdateSurface() { if (!IsDirty() && mTexture) return; Painted(); if (!mTexture) { CreateTexture(); if (!mTexture) { NS_WARNING("CanvasLayerD3D9::Updated called but no texture present and creation failed!"); return; } } RefPtr<SourceSurface> surface; if (mGLContext) { SharedSurface_GL* surf = mGLContext->RequestFrame(); if (!surf) return; SharedSurface_Basic* shareSurf = SharedSurface_Basic::Cast(surf); surface = shareSurf->GetData(); } else { surface = mDrawTarget->Snapshot(); } // WebGL reads entire surface. LockTextureRectD3D9 textureLock(mTexture); if (!textureLock.HasLock()) { NS_WARNING("Failed to lock CanvasLayer texture."); return; } D3DLOCKED_RECT rect = textureLock.GetLockRect(); RefPtr<DrawTarget> rectDt = Factory::CreateDrawTargetForData(BackendType::CAIRO, (uint8_t*)rect.pBits, surface->GetSize(), rect.Pitch, SurfaceFormat::B8G8R8A8); Rect drawRect(0, 0, surface->GetSize().width, surface->GetSize().height); rectDt->DrawSurface(surface, drawRect, drawRect, DrawSurfaceOptions(), DrawOptions(1.0F, CompositionOp::OP_SOURCE)); rectDt->Flush(); }
void CanvasLayerD3D9::UpdateSurface() { if (!IsDirty() && mTexture) return; Painted(); if (!mTexture) { CreateTexture(); if (!mTexture) { NS_WARNING("CanvasLayerD3D9::Updated called but no texture present and creation failed!"); return; } } if (mGLContext) { SharedSurface* surf = mGLContext->RequestFrame(); if (!surf) return; SharedSurface_Basic* shareSurf = SharedSurface_Basic::Cast(surf); // WebGL reads entire surface. LockTextureRectD3D9 textureLock(mTexture); if (!textureLock.HasLock()) { NS_WARNING("Failed to lock CanvasLayer texture."); return; } D3DLOCKED_RECT rect = textureLock.GetLockRect(); DataSourceSurface* frameData = shareSurf->GetData(); // Scope for gfxContext, so it's destroyed early. { RefPtr<DrawTarget> mapDt = Factory::CreateDrawTargetForData(BACKEND_CAIRO, (uint8_t*)rect.pBits, shareSurf->Size(), rect.Pitch, FORMAT_B8G8R8A8); nsRefPtr<gfxImageSurface> thebesFrameData = new gfxImageSurface(frameData->GetData(), ThebesIntSize(frameData->GetSize()), frameData->Stride(), SurfaceFormatToImageFormat(frameData->GetFormat())); nsRefPtr<gfxContext> ctx = new gfxContext(mapDt); ctx->SetOperator(gfxContext::OPERATOR_SOURCE); ctx->SetSource(thebesFrameData); ctx->Paint(); mapDt->Flush(); } } else { RECT r; r.left = mBounds.x; r.top = mBounds.y; r.right = mBounds.XMost(); r.bottom = mBounds.YMost(); LockTextureRectD3D9 textureLock(mTexture); if (!textureLock.HasLock()) { NS_WARNING("Failed to lock CanvasLayer texture."); return; } D3DLOCKED_RECT lockedRect = textureLock.GetLockRect(); nsRefPtr<gfxImageSurface> sourceSurface; if (mSurface->GetType() == gfxSurfaceTypeWin32) { sourceSurface = mSurface->GetAsImageSurface(); } else if (mSurface->GetType() == gfxSurfaceTypeImage) { sourceSurface = static_cast<gfxImageSurface*>(mSurface.get()); if (sourceSurface->Format() != gfxImageFormatARGB32 && sourceSurface->Format() != gfxImageFormatRGB24) { return; } } else { sourceSurface = new gfxImageSurface(gfxIntSize(mBounds.width, mBounds.height), gfxImageFormatARGB32); nsRefPtr<gfxContext> ctx = new gfxContext(sourceSurface); ctx->SetOperator(gfxContext::OPERATOR_SOURCE); ctx->SetSource(mSurface); ctx->Paint(); } uint8_t *startBits = sourceSurface->Data(); uint32_t sourceStride = sourceSurface->Stride(); if (sourceSurface->Format() != gfxImageFormatARGB32) { mHasAlpha = false; } else { mHasAlpha = true; } for (int y = 0; y < mBounds.height; y++) { memcpy((uint8_t*)lockedRect.pBits + lockedRect.Pitch * y, startBits + sourceStride * y, mBounds.width * 4); } } }
void CanvasLayerD3D9::UpdateSurface() { if (!IsDirty() && mTexture) return; Painted(); if (!mTexture) { CreateTexture(); if (!mTexture) { NS_WARNING("CanvasLayerD3D9::Updated called but no texture present and creation failed!"); return; } } if (mGLContext) { // WebGL reads entire surface. LockTextureRectD3D9 textureLock(mTexture); if (!textureLock.HasLock()) { NS_WARNING("Failed to lock CanvasLayer texture."); return; } D3DLOCKED_RECT r = textureLock.GetLockRect(); const bool stridesMatch = r.Pitch == mBounds.width * 4; uint8_t *destination; if (!stridesMatch) { destination = GetTempBlob(mBounds.width * mBounds.height * 4); } else { DiscardTempBlob(); destination = (uint8_t*)r.pBits; } mGLContext->MakeCurrent(); nsRefPtr<gfxImageSurface> tmpSurface = new gfxImageSurface(destination, gfxIntSize(mBounds.width, mBounds.height), mBounds.width * 4, gfxASurface::ImageFormatARGB32); mGLContext->ReadScreenIntoImageSurface(tmpSurface); tmpSurface = nullptr; if (!stridesMatch) { for (int y = 0; y < mBounds.height; y++) { memcpy((uint8_t*)r.pBits + r.Pitch * y, destination + mBounds.width * 4 * y, mBounds.width * 4); } } } else { RECT r; r.left = mBounds.x; r.top = mBounds.y; r.right = mBounds.XMost(); r.bottom = mBounds.YMost(); LockTextureRectD3D9 textureLock(mTexture); if (!textureLock.HasLock()) { NS_WARNING("Failed to lock CanvasLayer texture."); return; } D3DLOCKED_RECT lockedRect = textureLock.GetLockRect(); nsRefPtr<gfxImageSurface> sourceSurface; if (mSurface->GetType() == gfxASurface::SurfaceTypeWin32) { sourceSurface = mSurface->GetAsImageSurface(); } else if (mSurface->GetType() == gfxASurface::SurfaceTypeImage) { sourceSurface = static_cast<gfxImageSurface*>(mSurface.get()); if (sourceSurface->Format() != gfxASurface::ImageFormatARGB32 && sourceSurface->Format() != gfxASurface::ImageFormatRGB24) { return; } } else { sourceSurface = new gfxImageSurface(gfxIntSize(mBounds.width, mBounds.height), gfxASurface::ImageFormatARGB32); nsRefPtr<gfxContext> ctx = new gfxContext(sourceSurface); ctx->SetOperator(gfxContext::OPERATOR_SOURCE); ctx->SetSource(mSurface); ctx->Paint(); } uint8_t *startBits = sourceSurface->Data(); uint32_t sourceStride = sourceSurface->Stride(); if (sourceSurface->Format() != gfxASurface::ImageFormatARGB32) { mHasAlpha = false; } else { mHasAlpha = true; } for (int y = 0; y < mBounds.height; y++) { memcpy((uint8_t*)lockedRect.pBits + lockedRect.Pitch * y, startBits + sourceStride * y, mBounds.width * 4); } } }
void CanvasLayerD3D9::UpdateSurface() { if (!mDirty && mTexture) return; mDirty = false; if (!mTexture) { CreateTexture(); if (!mTexture) { NS_WARNING("CanvasLayerD3D9::Updated called but no texture present and creation failed!"); return; } } if (mGLContext) { // WebGL reads entire surface. LockTextureRectD3D9 textureLock(mTexture); if (!textureLock.HasLock()) { NS_WARNING("Failed to lock CanvasLayer texture."); return; } D3DLOCKED_RECT r = textureLock.GetLockRect(); const bool stridesMatch = r.Pitch == mBounds.width * 4; PRUint8 *destination; if (!stridesMatch) { destination = GetTempBlob(mBounds.width * mBounds.height * 4); } else { DiscardTempBlob(); destination = (PRUint8*)r.pBits; } mGLContext->MakeCurrent(); PRUint32 currentFramebuffer = 0; mGLContext->fGetIntegerv(LOCAL_GL_FRAMEBUFFER_BINDING, (GLint*)¤tFramebuffer); // Make sure that we read pixels from the correct framebuffer, regardless // of what's currently bound. if (currentFramebuffer != mCanvasFramebuffer) mGLContext->fBindFramebuffer(LOCAL_GL_FRAMEBUFFER, mCanvasFramebuffer); nsRefPtr<gfxImageSurface> tmpSurface = new gfxImageSurface(destination, gfxIntSize(mBounds.width, mBounds.height), mBounds.width * 4, gfxASurface::ImageFormatARGB32); mGLContext->ReadPixelsIntoImageSurface(0, 0, mBounds.width, mBounds.height, tmpSurface); tmpSurface = nullptr; // Put back the previous framebuffer binding. if (currentFramebuffer != mCanvasFramebuffer) mGLContext->fBindFramebuffer(LOCAL_GL_FRAMEBUFFER, currentFramebuffer); if (!stridesMatch) { for (int y = 0; y < mBounds.height; y++) { memcpy((PRUint8*)r.pBits + r.Pitch * y, destination + mBounds.width * 4 * y, mBounds.width * 4); } } } else { RECT r; r.left = mBounds.x; r.top = mBounds.y; r.right = mBounds.XMost(); r.bottom = mBounds.YMost(); LockTextureRectD3D9 textureLock(mTexture); if (!textureLock.HasLock()) { NS_WARNING("Failed to lock CanvasLayer texture."); return; } D3DLOCKED_RECT lockedRect = textureLock.GetLockRect(); nsRefPtr<gfxImageSurface> sourceSurface; if (mSurface->GetType() == gfxASurface::SurfaceTypeWin32) { sourceSurface = mSurface->GetAsImageSurface(); } else if (mSurface->GetType() == gfxASurface::SurfaceTypeImage) { sourceSurface = static_cast<gfxImageSurface*>(mSurface.get()); if (sourceSurface->Format() != gfxASurface::ImageFormatARGB32 && sourceSurface->Format() != gfxASurface::ImageFormatRGB24) { return; } } else { sourceSurface = new gfxImageSurface(gfxIntSize(mBounds.width, mBounds.height), gfxASurface::ImageFormatARGB32); nsRefPtr<gfxContext> ctx = new gfxContext(sourceSurface); ctx->SetOperator(gfxContext::OPERATOR_SOURCE); ctx->SetSource(mSurface); ctx->Paint(); } PRUint8 *startBits = sourceSurface->Data(); PRUint32 sourceStride = sourceSurface->Stride(); if (sourceSurface->Format() != gfxASurface::ImageFormatARGB32) { mHasAlpha = false; } else { mHasAlpha = true; } for (int y = 0; y < mBounds.height; y++) { memcpy((PRUint8*)lockedRect.pBits + lockedRect.Pitch * y, startBits + sourceStride * y, mBounds.width * 4); } } }