SimpleTiledLayerTile SimpleTiledLayerBuffer::ValidateTile(SimpleTiledLayerTile aTile, const nsIntPoint& aTileOrigin, const nsIntRegion& aDirtyRegion) { PROFILER_LABEL("SimpleTiledLayerBuffer", "ValidateTile"); static gfx::IntSize kTileSize(gfxPrefs::LayersTileWidth(), gfxPrefs::LayersTileHeight()); gfx::SurfaceFormat tileFormat = gfxPlatform::GetPlatform()->Optimal2DFormatForContent(GetContentType()); // if this is true, we're using a separate buffer to do our drawing first bool doBufferedDrawing = true; bool fullPaint = false; RefPtr<TextureClient> textureClient = mManager->GetSimpleTileTexturePool(tileFormat)->GetTextureClientWithAutoRecycle(); if (!textureClient) { NS_WARNING("TextureClient allocation failed"); return SimpleTiledLayerTile(); } if (!textureClient->Lock(OPEN_READ_WRITE)) { NS_WARNING("TextureClient lock failed"); return SimpleTiledLayerTile(); } if (!textureClient->CanExposeDrawTarget()) { doBufferedDrawing = false; } RefPtr<DrawTarget> drawTarget; unsigned char *bufferData = nullptr; // these are set/updated differently based on doBufferedDrawing nsIntRect drawBounds; nsIntRegion drawRegion; nsIntRegion invalidateRegion; RefPtr<DrawTarget> srcDT; uint8_t* srcData = nullptr; int32_t srcStride = 0; gfx::IntSize srcSize; gfx::SurfaceFormat srcFormat = gfx::SurfaceFormat::UNKNOWN; if (doBufferedDrawing) { // try to directly access the pixels of the TextureClient srcDT = textureClient->GetAsDrawTarget(); if (srcDT->LockBits(&srcData, &srcSize, &srcStride, &srcFormat)) { if (!aTile.mCachedBuffer) { aTile.mCachedBuffer = SharedBuffer::Create(srcStride * srcSize.height); fullPaint = true; } bufferData = (unsigned char*) aTile.mCachedBuffer->Data(); drawTarget = gfxPlatform::GetPlatform()->CreateDrawTargetForData(bufferData, kTileSize, srcStride, tileFormat); if (fullPaint) { drawBounds = nsIntRect(aTileOrigin.x, aTileOrigin.y, GetScaledTileSize().width, GetScaledTileSize().height); drawRegion = nsIntRegion(drawBounds); } else { drawBounds = aDirtyRegion.GetBounds(); drawRegion = nsIntRegion(drawBounds); if (GetContentType() == gfxContentType::COLOR_ALPHA) drawTarget->ClearRect(Rect(drawBounds.x - aTileOrigin.x, drawBounds.y - aTileOrigin.y, drawBounds.width, drawBounds.height)); } } else { // failed to obtain the client as an ImageSurface doBufferedDrawing = false; } } // this might get set above if we couldn't extract out a buffer if (!doBufferedDrawing) { drawTarget = textureClient->GetAsDrawTarget(); fullPaint = true; drawBounds = nsIntRect(aTileOrigin.x, aTileOrigin.y, GetScaledTileSize().width, GetScaledTileSize().height); drawRegion = nsIntRegion(drawBounds); if (GetContentType() == gfxContentType::COLOR_ALPHA) drawTarget->ClearRect(Rect(0, 0, drawBounds.width, drawBounds.height)); } // do the drawing RefPtr<gfxContext> ctxt = new gfxContext(drawTarget); ctxt->Scale(mResolution, mResolution); ctxt->Translate(gfxPoint(-aTileOrigin.x, -aTileOrigin.y)); mCallback(mThebesLayer, ctxt, drawRegion, fullPaint ? DrawRegionClip::CLIP_NONE : DrawRegionClip::DRAW_SNAPPED, // XXX DRAW or DRAW_SNAPPED? invalidateRegion, mCallbackData); ctxt = nullptr; if (doBufferedDrawing) { memcpy(srcData, bufferData, srcSize.height * srcStride); bufferData = nullptr; srcDT->ReleaseBits(srcData); srcDT = nullptr; } drawTarget = nullptr; textureClient->Unlock(); if (!mCompositableClient->AddTextureClient(textureClient)) { NS_WARNING("Failed to add tile TextureClient [simple]"); return SimpleTiledLayerTile(); } // aTile.mCachedBuffer was set earlier aTile.mTileBuffer = textureClient; aTile.mManager = mManager; aTile.mLastUpdate = TimeStamp::Now(); return aTile; }
SimpleTiledLayerTile SimpleTiledLayerBuffer::ValidateTile(SimpleTiledLayerTile aTile, const nsIntPoint& aTileOrigin, const nsIntRegion& aDirtyRegion) { PROFILER_LABEL("SimpleTiledLayerBuffer", "ValidateTile"); static gfx::IntSize kTileSize(TILEDLAYERBUFFER_TILE_SIZE, TILEDLAYERBUFFER_TILE_SIZE); gfx::SurfaceFormat tileFormat = gfxPlatform::GetPlatform()->Optimal2DFormatForContent(GetContentType()); // if this is true, we're using a separate buffer to do our drawing first bool doBufferedDrawing = true; bool fullPaint = false; RefPtr<TextureClient> textureClient = mManager->GetSimpleTileTexturePool(tileFormat)->GetTextureClientWithAutoRecycle(); if (!textureClient) { NS_WARNING("TextureClient allocation failed"); return SimpleTiledLayerTile(); } if (!textureClient->Lock(OPEN_WRITE)) { NS_WARNING("TextureClient lock failed"); return SimpleTiledLayerTile(); } TextureClientSurface *textureClientSurf = textureClient->AsTextureClientSurface(); if (!textureClientSurf) { doBufferedDrawing = false; } RefPtr<DrawTarget> drawTarget; nsRefPtr<gfxImageSurface> clientAsImageSurface; unsigned char *bufferData = nullptr; // these are set/updated differently based on doBufferedDrawing nsIntRect drawBounds; nsIntRegion drawRegion; nsIntRegion invalidateRegion; if (doBufferedDrawing) { // try to obtain the TextureClient as an ImageSurface, so that we can // access the pixels directly nsRefPtr<gfxASurface> asurf = textureClientSurf->GetAsSurface(); clientAsImageSurface = asurf ? asurf->GetAsImageSurface() : nullptr; if (clientAsImageSurface) { int32_t bufferStride = clientAsImageSurface->Stride(); if (!aTile.mCachedBuffer) { aTile.mCachedBuffer = SharedBuffer::Create(clientAsImageSurface->GetDataSize()); fullPaint = true; } bufferData = (unsigned char*) aTile.mCachedBuffer->Data(); drawTarget = gfxPlatform::GetPlatform()->CreateDrawTargetForData(bufferData, kTileSize, bufferStride, tileFormat); if (fullPaint) { drawBounds = nsIntRect(aTileOrigin.x, aTileOrigin.y, GetScaledTileLength(), GetScaledTileLength()); drawRegion = nsIntRegion(drawBounds); } else { drawBounds = aDirtyRegion.GetBounds(); drawRegion = nsIntRegion(drawBounds); if (GetContentType() == gfxContentType::COLOR_ALPHA) drawTarget->ClearRect(Rect(drawBounds.x - aTileOrigin.x, drawBounds.y - aTileOrigin.y, drawBounds.width, drawBounds.height)); } } else { // failed to obtain the client as an ImageSurface doBufferedDrawing = false; } } // this might get set above if we couldn't extract out a buffer if (!doBufferedDrawing) { drawTarget = textureClient->AsTextureClientDrawTarget()->GetAsDrawTarget(); fullPaint = true; drawBounds = nsIntRect(aTileOrigin.x, aTileOrigin.y, GetScaledTileLength(), GetScaledTileLength()); drawRegion = nsIntRegion(drawBounds); if (GetContentType() == gfxContentType::COLOR_ALPHA) drawTarget->ClearRect(Rect(0, 0, drawBounds.width, drawBounds.height)); } // do the drawing RefPtr<gfxContext> ctxt = new gfxContext(drawTarget); ctxt->Scale(mResolution, mResolution); ctxt->Translate(gfxPoint(-aTileOrigin.x, -aTileOrigin.y)); mCallback(mThebesLayer, ctxt, drawRegion, fullPaint ? DrawRegionClip::CLIP_NONE : DrawRegionClip::DRAW_SNAPPED, // XXX DRAW or DRAW_SNAPPED? invalidateRegion, mCallbackData); ctxt = nullptr; drawTarget = nullptr; if (doBufferedDrawing) { memcpy(clientAsImageSurface->Data(), bufferData, clientAsImageSurface->GetDataSize()); clientAsImageSurface = nullptr; bufferData = nullptr; } textureClient->Unlock(); if (!mCompositableClient->AddTextureClient(textureClient)) { NS_WARNING("Failed to add tile TextureClient [simple]"); return SimpleTiledLayerTile(); } // aTile.mCachedBuffer was set earlier aTile.mTileBuffer = textureClient; aTile.mManager = mManager; aTile.mLastUpdate = TimeStamp::Now(); return aTile; }