Fix unnecessary GetWritableBuffer() calls

Fixes unnecessary GetWritableBuffer() calls in fx_skia_device.cpp by
replacing (writable) SkBitmap with (read-only) SkImage for source images.

Bug: pdfium:2034
Change-Id: Ic247f2a676960f0b8b968c9df67f24cf16432df3
Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/108373
Commit-Queue: K. Moon <kmoon@chromium.org>
Reviewed-by: Nigi <nigi@chromium.org>
diff --git a/core/fxge/skia/fx_skia_device.cpp b/core/fxge/skia/fx_skia_device.cpp
index 2111d31..d0d224b 100644
--- a/core/fxge/skia/fx_skia_device.cpp
+++ b/core/fxge/skia/fx_skia_device.cpp
@@ -64,6 +64,7 @@
 #include "third_party/skia/include/core/SkPath.h"
 #include "third_party/skia/include/core/SkPathEffect.h"
 #include "third_party/skia/include/core/SkPathUtils.h"
+#include "third_party/skia/include/core/SkPixmap.h"
 #include "third_party/skia/include/core/SkRSXform.h"
 #include "third_party/skia/include/core/SkRect.h"
 #include "third_party/skia/include/core/SkRefCnt.h"
@@ -667,36 +668,37 @@
   paint->setBlendMode(GetSkiaBlendMode(blend_type));
 }
 
-bool Upsample(const RetainPtr<CFX_DIBBase>& pSource,
-              DataVector<uint32_t>& dst32_storage,
-              SkBitmap* skBitmap,
-              bool forceAlpha) {
-  // TODO(crbug.com/pdfium/2034): Does not need to use `GetWritableBuffer()`.
-  void* buffer = pSource->GetWritableBuffer().data();
-  if (!buffer)
-    return false;
-  SkColorType colorType = forceAlpha || pSource->IsMaskFormat()
+// TODO(crbug.com/pdfium/2034): Eliminate the need for `dst32_storage`.
+sk_sp<SkImage> Upsample(const RetainPtr<CFX_DIBBase>& source,
+                        DataVector<uint32_t>& dst32_storage,
+                        bool force_alpha) {
+  const void* buffer = source->GetBuffer().data();
+  if (!buffer) {
+    return nullptr;
+  }
+
+  SkColorType colorType = force_alpha || source->IsMaskFormat()
                               ? SkColorType::kAlpha_8_SkColorType
                               : SkColorType::kGray_8_SkColorType;
   SkAlphaType alphaType = kPremul_SkAlphaType;
-  int width = pSource->GetWidth();
-  int height = pSource->GetHeight();
-  int rowBytes = pSource->GetPitch();
-  switch (pSource->GetBPP()) {
+  int width = source->GetWidth();
+  int height = source->GetHeight();
+  int rowBytes = source->GetPitch();
+  switch (source->GetBPP()) {
     case 1: {
       // By default, the two colors for grayscale are 0xFF and 0x00 unless they
       // are specified in the palette.
       uint8_t color0 = 0x00;
       uint8_t color1 = 0xFF;
 
-      if (pSource->GetFormat() == FXDIB_Format::k1bppRgb &&
-          pSource->HasPalette()) {
-        uint32_t palette_color0 = pSource->GetPaletteArgb(0);
-        uint32_t palette_color1 = pSource->GetPaletteArgb(1);
+      if (source->GetFormat() == FXDIB_Format::k1bppRgb &&
+          source->HasPalette()) {
+        uint32_t palette_color0 = source->GetPaletteArgb(0);
+        uint32_t palette_color1 = source->GetPaletteArgb(1);
         bool use_gray_colors = IsRGBColorGrayScale(palette_color0) &&
                                IsRGBColorGrayScale(palette_color1);
         if (!use_gray_colors) {
-          dst32_storage = Fill32BppDestStorageWith1BppSource(pSource);
+          dst32_storage = Fill32BppDestStorageWith1BppSource(source);
           rowBytes = width * sizeof(uint32_t);
           colorType = kBGRA_8888_SkColorType;
           break;
@@ -722,14 +724,14 @@
     }
     case 8:
       // we upscale ctables to 32bit.
-      if (pSource->HasPalette()) {
-        const size_t src_palette_size = pSource->GetRequiredPaletteSize();
-        pdfium::span<const uint32_t> src_palette = pSource->GetPaletteSpan();
+      if (source->HasPalette()) {
+        const size_t src_palette_size = source->GetRequiredPaletteSize();
+        pdfium::span<const uint32_t> src_palette = source->GetPaletteSpan();
         CHECK_LE(src_palette_size, src_palette.size());
         if (src_palette_size < src_palette.size())
           src_palette = src_palette.first(src_palette_size);
 
-        dst32_storage = Fill32BppDestStorageWithPalette(pSource, src_palette);
+        dst32_storage = Fill32BppDestStorageWithPalette(source, src_palette);
         rowBytes = width * sizeof(uint32_t);
         colorType = kBGRA_8888_SkColorType;
       }
@@ -762,8 +764,9 @@
   }
   SkImageInfo imageInfo =
       SkImageInfo::Make(width, height, colorType, alphaType);
-  skBitmap->installPixels(imageInfo, buffer, rowBytes);
-  return true;
+  return SkImages::RasterFromPixmap(SkPixmap(imageInfo, buffer, rowBytes),
+                                    /*rasterReleaseProc=*/nullptr,
+                                    /*releaseContext=*/nullptr);
 }
 
 // Makes a bitmap filled with a solid color for debugging with `SkPicture`.
@@ -1115,15 +1118,15 @@
 
   // Storage vector must outlive `skia_mask`.
   DataVector<uint32_t> dst32_storage;
-  SkBitmap skia_mask;
-  if (!Upsample(mask, dst32_storage, &skia_mask, /*forceAlpha=*/true)) {
+  sk_sp<SkImage> skia_mask =
+      Upsample(mask, dst32_storage, /*force_alpha=*/true);
+  if (!skia_mask) {
     return false;
   }
-  skia_mask.setImmutable();
 
   SkPaint paint;
   paint.setBlendMode(SkBlendMode::kDstIn);
-  m_pCanvas->drawImageRect(skia_mask.asImage(),
+  m_pCanvas->drawImageRect(skia_mask,
                            SkRect::Make(m_pCanvas->imageInfo().bounds()),
                            SkSamplingOptions(), &paint);
   return true;
@@ -1511,19 +1514,16 @@
   if (!m_pBitmap)
     return true;
 
-  // TODO(crbug.com/pdfium/2034): Does not need to use `GetWritableBuffer()`.
-  uint8_t* srcBuffer = m_pBitmap->GetWritableBuffer().data();
+  const uint8_t* srcBuffer = m_pBitmap->GetBuffer().data();
   if (!srcBuffer)
     return true;
 
-  int srcWidth = m_pBitmap->GetWidth();
-  int srcHeight = m_pBitmap->GetHeight();
-  size_t srcRowBytes = m_pBitmap->GetPitch();
-  SkImageInfo srcImageInfo = SkImageInfo::Make(
-      srcWidth, srcHeight, SkColorType::kN32_SkColorType, kPremul_SkAlphaType);
-  SkBitmap skSrcBitmap;
-  skSrcBitmap.installPixels(srcImageInfo, srcBuffer, srcRowBytes);
-  skSrcBitmap.setImmutable();
+  SkImageInfo srcImageInfo =
+      SkImageInfo::Make(m_pBitmap->GetWidth(), m_pBitmap->GetHeight(),
+                        SkColorType::kN32_SkColorType, kPremul_SkAlphaType);
+  sk_sp<SkImage> source = SkImages::RasterFromPixmap(
+      SkPixmap(srcImageInfo, srcBuffer, m_pBitmap->GetPitch()),
+      /*rasterReleaseProc=*/nullptr, /*releaseContext=*/nullptr);
 
   uint8_t* dstBuffer = pBitmap->GetWritableBuffer().data();
   DCHECK(dstBuffer);
@@ -1538,8 +1538,7 @@
   skDstBitmap.installPixels(dstImageInfo, dstBuffer, dstRowBytes);
 
   SkCanvas canvas(skDstBitmap);
-  canvas.drawImageRect(skSrcBitmap.asImage(),
-                       SkRect::MakeXYWH(left, top, dstWidth, dstHeight),
+  canvas.drawImageRect(source, SkRect::MakeXYWH(left, top, dstWidth, dstHeight),
                        SkSamplingOptions(), /*paint=*/nullptr);
   return true;
 }
@@ -1679,17 +1678,22 @@
     const CFX_Matrix& matrix,
     BlendMode blend_type) {
   DebugValidate(m_pBitmap, m_pBackdropBitmap);
-  // Storage vectors must outlive `skBitmap` and `skMask`.
+
+  // Storage vectors must outlive `skia_source` and `skia_mask`.
   DataVector<uint32_t> src32_storage;
+  sk_sp<SkImage> skia_source =
+      Upsample(pSource, src32_storage, /*force_alpha=*/false);
+  if (!skia_source) {
+    return false;
+  }
+
   DataVector<uint32_t> mask32_storage;
-  SkBitmap skBitmap;
-  SkBitmap skMask;
-  if (!Upsample(pSource, src32_storage, &skBitmap, /*forceAlpha=*/false)) {
+  sk_sp<SkImage> skia_mask =
+      Upsample(pMask, mask32_storage, /*force_alpha=*/true);
+  if (!skia_mask) {
     return false;
   }
-  if (!Upsample(pMask, mask32_storage, &skMask, /*forceAlpha=*/true)) {
-    return false;
-  }
+
   {
     SkAutoCanvasRestore scoped_save_restore(m_pCanvas, /*doSave=*/true);
 
@@ -1701,17 +1705,17 @@
     SkPaint paint;
     SetBitmapPaintForMerge(pSource->IsMaskFormat(), !m_FillOptions.aliased_path,
                            0xFFFFFFFF, bitmap_alpha, blend_type, &paint);
-    sk_sp<SkImage> skSrc = SkImages::RasterFromBitmap(skBitmap);
-    sk_sp<SkShader> skSrcShader = skSrc->makeShader(
+    sk_sp<SkShader> source_shader = skia_source->makeShader(
         SkTileMode::kClamp, SkTileMode::kClamp, SkSamplingOptions());
-    sk_sp<SkImage> skMaskImage = SkImages::RasterFromBitmap(skMask);
-    sk_sp<SkShader> skMaskShader = skMaskImage->makeShader(
+    sk_sp<SkShader> mask_shader = skia_mask->makeShader(
         SkTileMode::kClamp, SkTileMode::kClamp, SkSamplingOptions());
-    paint.setShader(
-        SkShaders::Blend(SkBlendMode::kSrcIn, skMaskShader, skSrcShader));
-    SkRect r = {0, 0, SkIntToScalar(src_width), SkIntToScalar(src_height)};
-    m_pCanvas->drawRect(r, paint);
+    paint.setShader(SkShaders::Blend(
+        SkBlendMode::kSrcIn, std::move(mask_shader), std::move(source_shader)));
+    m_pCanvas->drawRect(
+        SkRect::MakeWH(SkIntToScalar(src_width), SkIntToScalar(src_height)),
+        paint);
   }
+
   DebugValidate(m_pBitmap, m_pBackdropBitmap);
   return true;
 }
@@ -1749,13 +1753,13 @@
     BlendMode blend_type) {
   DebugValidate(m_pBitmap, m_pBackdropBitmap);
 
-  // Storage vector must outlive `skBitmap`.
+  // Storage vector must outlive `skia_source`.
   DataVector<uint32_t> dst32_storage;
-  SkBitmap skBitmap;
-  if (!Upsample(pSource, dst32_storage, &skBitmap, /*forceAlpha=*/false)) {
+  sk_sp<SkImage> skia_source =
+      Upsample(pSource, dst32_storage, /*force_alpha=*/false);
+  if (!skia_source) {
     return false;
   }
-  skBitmap.setImmutable();
 
   {
     SkAutoCanvasRestore scoped_save_restore(m_pCanvas, /*doSave=*/true);
@@ -1787,12 +1791,13 @@
     }
 
     m_pCanvas->drawImageRect(
-        skBitmap.asImage(),
+        skia_source,
         SkRect::MakeLTRB(src_rect.left, src_rect.top, src_rect.right,
                          src_rect.bottom),
         SkRect::MakeWH(src_rect.Width(), src_rect.Height()), sampling_options,
         &paint, SkCanvas::kFast_SrcRectConstraint);
   }
+
   DebugValidate(m_pBitmap, m_pBackdropBitmap);
   return true;
 }