| 169 | } |
| 170 | |
| 171 | void RenderTarget::saveAsync(String filename, const std::function<void(bool)>& callback) { |
| 172 | AssertIf((bgfx::getCaps()->supported & BGFX_CAPS_TEXTURE_READ_BACK) == 0, "texture read back not supported."); |
| 173 | |
| 174 | uint64_t extraFlags = 0; |
| 175 | switch (bgfx::getCaps()->rendererType) { |
| 176 | case bgfx::RendererType::Direct3D11: |
| 177 | case bgfx::RendererType::Direct3D12: |
| 178 | case bgfx::RendererType::OpenGLES: |
| 179 | extraFlags = BGFX_TEXTURE_BLIT_DST; |
| 180 | break; |
| 181 | default: |
| 182 | break; |
| 183 | } |
| 184 | bgfx::TextureHandle textureHandle; |
| 185 | if (extraFlags) { |
| 186 | const uint64_t textureFlags = BGFX_SAMPLER_U_CLAMP | BGFX_SAMPLER_V_CLAMP | BGFX_TEXTURE_READ_BACK; |
| 187 | textureHandle = bgfx::createTexture2D(_textureWidth, _textureHeight, false, 1, _format, textureFlags | extraFlags); |
| 188 | SharedView.pushBack("SaveTarget"_slice, [&]() { |
| 189 | bgfx::blit(SharedView.getId(), textureHandle, 0, 0, _texture->getHandle()); |
| 190 | }); |
| 191 | } else { |
| 192 | textureHandle = _texture->getHandle(); |
| 193 | } |
| 194 | uint8_t* data = new uint8_t[_texture->getInfo().storageSize]; |
| 195 | uint32_t frame = bgfx::readTexture(textureHandle, data); |
| 196 | uint32_t width = s_cast<uint32_t>(_textureWidth); |
| 197 | uint32_t height = s_cast<uint32_t>(_textureHeight); |
| 198 | std::string file(filename); |
| 199 | SharedDirector.getSystemScheduler()->schedule([frame, textureHandle, extraFlags, data, width, height, file, callback](double deltaTime) { |
| 200 | DORA_UNUSED_PARAM(deltaTime); |
| 201 | if (frame <= SharedApplication.getFrame()) { |
| 202 | if (extraFlags) { |
| 203 | bgfx::destroy(textureHandle); |
| 204 | } |
| 205 | SharedAsyncThread.run( |
| 206 | [data, width, height]() { |
| 207 | unsigned error; |
| 208 | LodePNGState state; |
| 209 | lodepng_state_init(&state); |
| 210 | uint8_t* out = nullptr; |
| 211 | size_t outSize = 0; |
| 212 | error = lodepng_encode(&out, &outSize, data, width, height, &state); |
| 213 | lodepng_state_cleanup(&state); |
| 214 | delete[] data; |
| 215 | return Values::alloc(out, outSize); |
| 216 | }, |
| 217 | [callback, file](Own<Values> values) { |
| 218 | uint8_t* out; |
| 219 | size_t outSize; |
| 220 | values->get(out, outSize); |
| 221 | Slice content(r_cast<char*>(out), outSize); |
| 222 | SharedContent.saveAsync(file, content, [out, callback](bool success) { |
| 223 | ::free(out); |
| 224 | callback(success); |
| 225 | }); |
| 226 | }); |
| 227 | return true; |
| 228 | } |
nothing calls this directly
no test coverage detected