)]}'
{
  "commit": "cc6d73260e1f866604c8845fc09a73d2a05fa983",
  "tree": "81e431f2457c4d303278825726e718d822815a7b",
  "parents": [
    "3cce25a9ad538e8f4b755f84d49ba08dd9bb4d7f"
  ],
  "author": {
    "name": "Brandon DeRosier",
    "email": "bdero@google.com",
    "time": "Fri Jun 12 16:50:20 2026 -0700"
  },
  "committer": {
    "name": "GitHub",
    "email": "noreply@github.com",
    "time": "Fri Jun 12 23:50:20 2026 +0000"
  },
  "message": "[Flutter GPU] Add surface API for framework presentation (#187358)\n\nFixes https://github.com/flutter/flutter/issues/187357\n\nAdds a Flutter GPU surface API for rendering into a presentable color\ntexture and drawing the latest presented image through Flutter. The\nsurface owns the backing texture pool, tracks acquired frames, keeps the\ncurrent image out of reuse, and waits for producer command buffer\ncompletion before a presented texture can be reused.\n\nThe API is shaped as a small family so later destinations (a Flutter\ncanvas, and eventually the window swapchain) can share one per-frame\ncontract. `GpuSurface` and `GpuSurfaceFrame` are the\ndestination-agnostic base types. This PR ships the first concrete\ndestination, `GpuImageSurface`, which Flutter draws as a `ui.Image`.\n\nTwo parts of the contract are uniform across all future destinations,\neven though the image destination never exercises them.\n`acquireNextFrame` is nullable, because a window swapchain can skip a\nframe. `present` returns a `GpuPresentStatus`, because a window\nswapchain can report that it needs reconfiguring. For an image surface,\nacquire always returns a frame and present always reports success, and\nthe published image is read from `GpuImageSurface.currentImage`.\n\nThe API keeps depth, stencil, MSAA, and intermediate attachments\nrenderer-owned. `GpuSurfaceFrame.colorTexture` is only the final color\ntarget handed back to Flutter as a `ui.Image`.\n\nA minimal example.\n\n```dart\nfinal surface \u003d gpu.gpuContext.createImageSurface(width, height);\nfinal frame \u003d surface.acquireNextFrame();\n\nfinal commandBuffer \u003d gpu.gpuContext.createCommandBuffer();\ncommandBuffer.createRenderPass(\n  gpu.RenderTarget.singleColor(\n    gpu.ColorAttachment(texture: frame.colorTexture),\n  ),\n);\n\n// Bind a pipeline, bind resources, and draw.\n\nframe.present(commandBuffer);\ncommandBuffer.submit();\ncanvas.drawImageRect(surface.currentImage!, src, dst, paint);\n```\n\nDepth and stencil remain normal renderer-owned attachments.\n\n```dart\nfinal frame \u003d surface.acquireNextFrame();\nfinal depthStencil \u003d gpu.gpuContext.createTexture(\n  gpu.StorageMode.deviceTransient,\n  width,\n  height,\n  format: gpu.gpuContext.defaultDepthStencilFormat,\n  enableRenderTargetUsage: true,\n  enableShaderReadUsage: false,\n);\n\nfinal commandBuffer \u003d gpu.gpuContext.createCommandBuffer();\ncommandBuffer.createRenderPass(\n  gpu.RenderTarget.singleColor(\n    gpu.ColorAttachment(texture: frame.colorTexture),\n    depthStencilAttachment: gpu.DepthStencilAttachment(texture: depthStencil),\n  ),\n);\n```\n\nTests cover surface acquisition, presentation, current image behavior,\ndiscard, resize, and rendering a clear color into a surface.\n\n## Pre-launch Checklist\n\n- [x] I read the Contributor Guide and followed the process outlined\nthere for submitting PRs.\n- [x] I read the AI contribution guidelines and understand my\nresponsibilities, or I am not using AI tools.\n- [x] I read the Tree Hygiene wiki page, which explains my\nresponsibilities.\n- [x] I read and followed the Flutter Style Guide, including Features we\nexpect every widget to implement.\n- [x] I signed the CLA.\n- [x] I listed at least one issue that this PR fixes in the description\nabove.\n- [x] I updated/added relevant documentation (doc comments with `///`).\n- [x] I added new tests to check the change I am making, or this PR is\ntest-exempt.\n- [x] I followed the breaking change policy and added Data Driven Fixes\nwhere supported.\n- [x] All existing and new tests are passing.",
  "tree_diff": [
    {
      "type": "modify",
      "old_id": "003df833b591ee86d7068783c9f218b03de8179c",
      "old_mode": 33188,
      "old_path": "engine/src/flutter/BUILD.gn",
      "new_id": "417a4b7848c8bd7dec7979ef90b1d3fdb1208702",
      "new_mode": 33188,
      "new_path": "engine/src/flutter/BUILD.gn"
    },
    {
      "type": "modify",
      "old_id": "503c1fc2a134a74fa6ae5a554f612e904f1af9c4",
      "old_mode": 33188,
      "old_path": "engine/src/flutter/lib/gpu/BUILD.gn",
      "new_id": "9436f5489774fe4392b508a2f44e94f62839179d",
      "new_mode": 33188,
      "new_path": "engine/src/flutter/lib/gpu/BUILD.gn"
    },
    {
      "type": "modify",
      "old_id": "3dfe008c52cf1b5e0068702d2014b93d23b03502",
      "old_mode": 33188,
      "old_path": "engine/src/flutter/lib/gpu/command_buffer.cc",
      "new_id": "fb55795698241cc746d016868558d2f37c5de278",
      "new_mode": 33188,
      "new_path": "engine/src/flutter/lib/gpu/command_buffer.cc"
    },
    {
      "type": "modify",
      "old_id": "1f2e69ad789274c76063b75ab808912c8d1ae7f0",
      "old_mode": 33188,
      "old_path": "engine/src/flutter/lib/gpu/command_buffer.h",
      "new_id": "840bf645a41a8bd9cb029c2c9152e7fb0e69df0e",
      "new_mode": 33188,
      "new_path": "engine/src/flutter/lib/gpu/command_buffer.h"
    },
    {
      "type": "add",
      "old_id": "0000000000000000000000000000000000000000",
      "old_mode": 0,
      "old_path": "/dev/null",
      "new_id": "dd1882f7d17aec4508ceba46c09644f0950093dc",
      "new_mode": 33188,
      "new_path": "engine/src/flutter/lib/gpu/command_buffer_unittests.cc"
    },
    {
      "type": "modify",
      "old_id": "12d8a0b6721009ce8dd34ea5b1c00ca06b1b6239",
      "old_mode": 33188,
      "old_path": "engine/src/flutter/lib/gpu/lib/gpu.dart",
      "new_id": "8b9f75d6c40fd3bf5841da17e665b1bfc04216fc",
      "new_mode": 33188,
      "new_path": "engine/src/flutter/lib/gpu/lib/gpu.dart"
    },
    {
      "type": "modify",
      "old_id": "d02e97cd8e9d97b5901b97e592bbcc366c78acee",
      "old_mode": 33188,
      "old_path": "engine/src/flutter/lib/gpu/lib/src/command_buffer.dart",
      "new_id": "f555252b9d1775b89c59458d26ff868d9afa40d1",
      "new_mode": 33188,
      "new_path": "engine/src/flutter/lib/gpu/lib/src/command_buffer.dart"
    },
    {
      "type": "modify",
      "old_id": "e7eb9756db9072dc1d4ac2c52c70b9cc25620fde",
      "old_mode": 33188,
      "old_path": "engine/src/flutter/lib/gpu/lib/src/context.dart",
      "new_id": "4c4a3edef18068de88585eab2a53350d3b2120a6",
      "new_mode": 33188,
      "new_path": "engine/src/flutter/lib/gpu/lib/src/context.dart"
    },
    {
      "type": "add",
      "old_id": "0000000000000000000000000000000000000000",
      "old_mode": 0,
      "old_path": "/dev/null",
      "new_id": "81a8527474c1c5c253f24deeb41bfe113890b58f",
      "new_mode": 33188,
      "new_path": "engine/src/flutter/lib/gpu/lib/src/surface.dart"
    },
    {
      "type": "modify",
      "old_id": "8ba84be1b9f8633b720545cee2aa4fc7db6e4166",
      "old_mode": 33188,
      "old_path": "engine/src/flutter/lib/gpu/lib/src/texture.dart",
      "new_id": "6fc91b8ccba41fcf3699853763b2c2b23284feee",
      "new_mode": 33188,
      "new_path": "engine/src/flutter/lib/gpu/lib/src/texture.dart"
    },
    {
      "type": "add",
      "old_id": "0000000000000000000000000000000000000000",
      "old_mode": 0,
      "old_path": "/dev/null",
      "new_id": "d1757bc616157545e8d4d6b7e0e34fcbfb8a5373",
      "new_mode": 33188,
      "new_path": "engine/src/flutter/lib/gpu/surface.cc"
    },
    {
      "type": "add",
      "old_id": "0000000000000000000000000000000000000000",
      "old_mode": 0,
      "old_path": "/dev/null",
      "new_id": "87b4c25d5d803bacc6bee8478a73bd884b0a9b33",
      "new_mode": 33188,
      "new_path": "engine/src/flutter/lib/gpu/surface.h"
    },
    {
      "type": "modify",
      "old_id": "ade01c85d5f8fc363cd286a0683cbfd04bb844e0",
      "old_mode": 33188,
      "old_path": "engine/src/flutter/testing/dart/gpu_test.dart",
      "new_id": "dfa965af8a237f4ab0e5a5a44b6b47556826b3f3",
      "new_mode": 33188,
      "new_path": "engine/src/flutter/testing/dart/gpu_test.dart"
    }
  ]
}
