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 CanvasLayerD3D10::UpdateSurface() { if (!mDirty) return; mDirty = false; if (mDrawTarget) { mDrawTarget->Flush(); } else if (mIsD2DTexture) { mSurface->Flush(); return; } else if (mUsingSharedTexture) { // need to sync on the d3d9 device if (mGLContext) { mGLContext->MakeCurrent(); mGLContext->GuaranteeResolve(); } return; } if (mGLContext) { // WebGL reads entire surface. D3D10_MAPPED_TEXTURE2D map; HRESULT hr = mTexture->Map(0, D3D10_MAP_WRITE_DISCARD, 0, &map); if (FAILED(hr)) { NS_WARNING("Failed to map CanvasLayer texture."); return; } const bool stridesMatch = map.RowPitch == mBounds.width * 4; uint8_t *destination; if (!stridesMatch) { destination = GetTempBlob(mBounds.width * mBounds.height * 4); } else { DiscardTempBlob(); destination = (uint8_t*)map.pData; } 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*)map.pData + map.RowPitch * y, destination + mBounds.width * 4 * y, mBounds.width * 4); } } mTexture->Unmap(0); } else if (mSurface) { RECT r; r.left = 0; r.top = 0; r.right = mBounds.width; r.bottom = mBounds.height; D3D10_MAPPED_TEXTURE2D map; HRESULT hr = mTexture->Map(0, D3D10_MAP_WRITE_DISCARD, 0, &map); if (FAILED(hr)) { NS_WARNING("Failed to lock CanvasLayer texture."); return; } nsRefPtr<gfxImageSurface> dstSurface; dstSurface = new gfxImageSurface((unsigned char*)map.pData, gfxIntSize(mBounds.width, mBounds.height), map.RowPitch, gfxASurface::ImageFormatARGB32); nsRefPtr<gfxContext> ctx = new gfxContext(dstSurface); ctx->SetOperator(gfxContext::OPERATOR_SOURCE); ctx->SetSource(mSurface); ctx->Paint(); mTexture->Unmap(0); } }
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); } } }
void CanvasLayerD3D10::UpdateSurface() { if (!mDirty) return; mDirty = false; if (mDrawTarget) { mDrawTarget->Flush(); return; } if (mIsD2DTexture) { mSurface->Flush(); return; } if (mUsingSharedTexture) { // need to sync on the d3d9 device if (mGLContext) { mGLContext->MakeCurrent(); mGLContext->GuaranteeResolve(); } return; } if (mGLContext) { // WebGL reads entire surface. D3D10_MAPPED_TEXTURE2D map; HRESULT hr = mTexture->Map(0, D3D10_MAP_WRITE_DISCARD, 0, &map); if (FAILED(hr)) { NS_WARNING("Failed to map CanvasLayer texture."); return; } const bool stridesMatch = map.RowPitch == mBounds.width * 4; PRUint8 *destination; if (!stridesMatch) { destination = GetTempBlob(mBounds.width * mBounds.height * 4); } else { DiscardTempBlob(); destination = (PRUint8*)map.pData; } 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 = nsnull; // 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*)map.pData + map.RowPitch * y, destination + mBounds.width * 4 * y, mBounds.width * 4); } } mTexture->Unmap(0); } else if (mSurface) { RECT r; r.left = 0; r.top = 0; r.right = mBounds.width; r.bottom = mBounds.height; D3D10_MAPPED_TEXTURE2D map; HRESULT hr = mTexture->Map(0, D3D10_MAP_WRITE_DISCARD, 0, &map); if (FAILED(hr)) { NS_WARNING("Failed to lock CanvasLayer texture."); return; } nsRefPtr<gfxImageSurface> dstSurface; dstSurface = new gfxImageSurface((unsigned char*)map.pData, gfxIntSize(mBounds.width, mBounds.height), map.RowPitch, gfxASurface::ImageFormatARGB32); nsRefPtr<gfxContext> ctx = new gfxContext(dstSurface); ctx->SetOperator(gfxContext::OPERATOR_SOURCE); ctx->SetSource(mSurface); ctx->Paint(); mTexture->Unmap(0); } }